基礎數據結構-用鏈表實現隊列和棧

鏈表在memcached、redis中做爲核心數據結構出現。相比數組,鏈表能動態增減容量,就比數組要靈活,而且hash表結構通常都使用鏈表進行數據存儲git

完整案例代碼已上傳github: github.com/neatlife-le…github

隊列

元素結構

對應代碼以下redis

typedef struct _element {
    struct _element *previous;
    struct _element *next;
    void *value;
} element;
複製代碼

隊列結構

一個隊列中包含多個元素,爲了可以方便的獲得這個隊列頭和尾,以及隊列裏的元素個數,使用這個queue結構來存放這些信息數組

對應代碼以下數據結構

typedef struct _queue {
    element *head;
    element *end;
    size_t size;
} queue;
複製代碼

新建隊列

queue* new_queue(void *value) {
    element *item = (element *) malloc(sizeof(element));
    item->value = value;
    item->previous = NULL;
    item->next = NULL;
    
    queue *a_queue = (queue *) malloc(sizeof(queue));
    a_queue->head = item;
    a_queue->end = item;
    a_queue->size = 1;
    return a_queue;
}
複製代碼
  1. 爲元素分配內存空間,並獲得指向這個元素內存空間的指針
  2. 爲隊列分配內存空間,並把隊列頭、尾指針指向上面建立的元素,由於這個隊列裏初始化的時候只有這一個元素
  3. 把隊列大小設置爲1

進隊列

void push(queue *a_queue, void *value) {
    element *item = (element *) malloc(sizeof(element));
    item->value = value;
    
    item->previous = a_queue->end;
    item->next = NULL;
    
    a_queue->end->next = item;
    a_queue->end = item;
    a_queue->size = a_queue->size + 1;
}
複製代碼

隊列的特性是先進先出,通常出的時候都是拿鏈表的最後一個元素,進的時候就把新元素加到鏈表尾memcached

  1. 建立新元素,並把這個元素的next置爲NULL
  2. 把新元素掛到鏈表尾
  3. 隊列中的元素數量+1

出隊列

element* pop(queue *a_queue) {
    element *item = a_queue->end;
    
    a_queue->end = a_queue->end->previous;
    item->previous = NULL;
    a_queue->end->next = NULL;
    
    a_queue->size = a_queue->size - 1;
    
    return item;
}
複製代碼
  1. 取出隊列的最後一個元素
  2. 隊列的最後一個元素變成了倒數第二個元素
  3. 短掉取出的元素和隊列的關係
  4. 隊列中的元素數量-1

獲取隊列狀態

void stats(queue *a_queue) {
    cout << "current queue size: " << a_queue->size << endl;
    
    cout << "current queue content: " << endl;
    element *item = a_queue->head;
    while (item) {
        cout << (size_t) item->value << endl;
        item = item->next;
    }
}
複製代碼

測試腳本

queue* a_queue = new_queue((size_t *) 1)
push(a_queue, (size_t *) 2);

stats(a_queue);
element *item = pop(a_queue);
stats(a_queue);
cout << (size_t)item->value << endl;
複製代碼

效果以下: 測試

能夠看到出隊列是從隊列尾部出的

異常處理

出隊列時可對a_queue->size進行判斷,若是size等於0了,表示隊列中已經沒有數據了,就不能再執行出隊列操做了ui

當出隊列出到a_queue->size等於0時,須要清空隊列的end、previous指針spa

棧和隊列除了出棧操做不同,其它部分徹底一致,隊列出隊列的時候從尾部出,棧出棧的時候從頭部出,核心代碼以下3d

element* pop(stack *a_stack) {
    element *item = a_stack->head;
    
    a_stack->head = a_stack->head->next;
    item->next = NULL;
    a_stack->head->previous = NULL;
    
    a_stack->size = a_stack->size - 1;
    
    return item;
}
複製代碼

一些注意的點

cpp指針初始化須要明確設置爲NULL

參考資料

  1. www.zhihu.com/question/24…
相關文章
相關標籤/搜索