c語言數據結構實現-鏈式隊列

一、背景需求

在上一篇文章中介紹了數組實現的隊列,本章節再補充一個鏈式的隊列,實現動態插入空間的操作。

二、相關知識

鏈式隊列由環形鏈表實現,通過鏈表頭和鏈表尾的操作,完成了隊列入列出列的功能。

如圖所示,空隊列時至少需要一個空節點,表示爲隊列頭和隊列尾,相當於哨兵的作用;


入列:新增節點插入到隊列尾,並更新 tail 指針;出列:更新 head 位置,釋放原來 head節點,返回現有位置的 data;

、實現

相關數據結構

struct list_node_t {
    struct list_node_t *next;
    void *data;
};

typedef struct queue
{
    size_t max_size;
    size_t used_num;
    struct list_node_t *head;
    struct list_node_t *tail;
} queue_t;

初始化函數,對於生成圖1的空隊列,注意初始化時尾節點指向頭節點

queue_t *queue_alloc(size_t max_size)
{
    queue_t *pqueue = NULL;

    pqueue = calloc(1, sizeof(queue_t));
    if ( !pqueue ) { 
        return NULL;
    }   

    /* Head is nil */
    pqueue->head = calloc(1, sizeof(struct list_node_t));
    if ( !pqueue->head ) { 
        return NULL;
    }   

    pqueue->head->next = NULL;
    pqueue->head->data = NULL;

    /* Reset tail means empty */
    pqueue->tail = pqueue->head;

    pqueue->max_size = max_size;
    pqueue->used_num = 0;

    return pqueue;
}


入列操作,對於圖2的步驟,新增節點後加入到隊列尾

int queue_push(queue_t *pqueue, void *nill, void *pdata)
{
    struct list_node_t *pnode = NULL;

    if ( !pqueue ) {
        return FAILURE;
    }

    if ( queue_isfull(pqueue) ) {
        return FAILURE;
    }

    pnode = calloc(1, sizeof(struct list_node_t));
    if ( !pnode ) {
        return FAILURE;
    }

    pnode->data = pdata;
    pnode->next = NULL;

    pqueue->tail->next = pnode;
    pqueue->tail = pnode;
    pqueue->used_num++;

    return SUCCESS;
}

出列操作,對應圖3步驟,注意data數據爲外部維護的數據結構,隊列內部只做索引維護。

void *queue_pop(queue_t *pqueue)
{
    struct list_node_t *prev = NULL;

    if ( !pqueue ) {
        return NULL;
    }

    if ( queue_isempty(pqueue) ) {
        return NULL;
    }

    prev = pqueue->head;
    pqueue->head = pqueue->head->next;

    FREE_POINTER(prev);
    return pqueue->head->data;
}


四、總結

相比於數據隊列,鏈式隊列空間使用較少,同樣也可用於單生產者-單消費者的無鎖隊列實現。

注意data數據爲外部維護的數據,隊列內部只是做指針索引管理,並不進行內容的修改。




發佈了46 篇原創文章 · 獲贊 35 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章