首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

數據結構:鏈隊列(Linked Queue)C語言完整實現

     編輯:關於C語言

數據結構:鏈隊列(Linked Queue)C語言完整實現

鏈隊列是隊列的鏈式存儲結構,本質是僅允許表頭刪除、表尾插入的單鏈表。為了操作統一便捷,引入頭結點,空隊列時頭尾指針均指向頭結點。本文提供規範、完整的 C 語言實現,涵蓋初始化、銷毀、清空、判空、求長、取首尾、入隊、出隊、遍歷等全套操作。

一、類型定義

typedef int QElemType;

typedef struct QNode {
    QElemType data;
    struct QNode* next;
} QNode, *QueuePtr;

typedef struct {
    QueuePtr front;  // 隊頭指針(指向頭結點)
    QueuePtr rear;   // 隊尾指針(指向最後一個數據結點)
} LinkQueue;

二、核心操作實現

1. 初始化(帶頭結點)

void Init_LinkQueue(LinkQueue* Q) {
    QueuePtr head = (QueuePtr)malloc(sizeof(QNode));
    if (!head) exit(EXIT_FAILURE);
    head->next = NULL;
    Q->front = Q->rear = head;  // 空隊列:頭尾均指向頭結點
}

2. 銷毀隊列(釋放所有結點含頭結點)

void Destroy_LinkQueue(LinkQueue* Q) {
    while (Q->front) {
        QueuePtr p = Q->front;
        Q->front = Q->front->next;
        free(p);
    }
    Q->rear = NULL;
}

3. 清空隊列(保留頭結點)

void Clear_LinkQueue(LinkQueue* Q) {
    // 釋放所有數據結點
    QueuePtr p = Q->front->next;
    while (p) {
        QueuePtr tmp = p;
        p = p->next;
        free(tmp);
    }
    Q->front->next = NULL;
    Q->rear = Q->front;  // 恢復空隊列狀態
}

4. 判空

int IsEmpty_LinkQueue(const LinkQueue* Q) {
    return Q->front == Q->rear;
}

5. 求長度

int GetLength_LinkQueue(const LinkQueue* Q) {
    int count = 0;
    QueuePtr p = Q->front->next;  // 跳過頭結點
    while (p) {
        ++count;
        p = p->next;
    }
    return count;
}

6. 取隊首元素

int GetHead_LinkQueue(const LinkQueue* Q, QElemType* x) {
    if (IsEmpty_LinkQueue(Q)) return 0;
    *x = Q->front->next->data;
    return 1;
}

7. 取隊尾元素

int GetRear_LinkQueue(const LinkQueue* Q, QElemType* x) {
    if (IsEmpty_LinkQueue(Q)) return 0;
    *x = Q->rear->data;
    return 1;
}

8. 入隊(尾插法)

int En_LinkQueue(LinkQueue* Q, QElemType x) {
    QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
    if (!p) return 0;
    p->data = x;
    p->next = NULL;
    Q->rear->next = p;
    Q->rear = p;
    return 1;
}

9. 出隊(頭刪法,跳過頭結點)

int De_LinkQueue(LinkQueue* Q, QElemType* x) {
    if (IsEmpty_LinkQueue(Q)) return 0;
    QueuePtr p = Q->front->next;  // 首個數據結點
    *x = p->data;
    Q->front->next = p->next;
    if (p->next == NULL)  // 刪除後隊列變空
        Q->rear = Q->front;
    free(p);
    return 1;
}

10. 遍歷輸出

void Print_LinkQueue(const LinkQueue* Q) {
    if (IsEmpty_LinkQueue(Q)) {
        printf("Queue empty\n");
        return;
    }
    QueuePtr p = Q->front->next;
    while (p) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

三、測試主程序

int main(void) {
    LinkQueue Q;
    Init_LinkQueue(&Q);
    QElemType val;
    
    for (int i = 1; i <= 5; ++i) En_LinkQueue(&Q, i * 10);
    Print_LinkQueue(&Q);  // 10 20 30 40 50
    printf("Length: %d\n", GetLength_LinkQueue(&Q));
    
    GetHead_LinkQueue(&Q, &val); printf("Head: %d\n", val); // 10
    GetRear_LinkQueue(&Q, &val); printf("Rear: %d\n", val); // 50
    
    De_LinkQueue(&Q, &val); printf("Dequeue: %d\n", val); // 10
    Print_LinkQueue(&Q);  // 20 30 40 50
    
    Destroy_LinkQueue(&Q);
    return 0;
}

四、鏈隊列 vs 循環順序隊列 對比

特性鏈隊列循環順序隊列
存儲結構鏈表,動態分配數組,固定大小
空間利用率無內部碎片,有指針開銷MAXSIZE-1,無指針開銷
擴容能力天然支持,受限於內存需重新分配數組並拷貝
隨機訪問O(n)O(1)
適用場景長度難預估、頻繁增減、嵌入式長度可預估、高性能、緩存友好

五、關鍵細節避坑

  1. 頭結點作用:統一空/非空操作邏輯,出隊時無需特別判斷是否為第一個數據結點。
  2. 出隊後置尾指針:刪除最後一個數據結點時,rear 必須回指頭結點,否則陷入野指針。
  3. 銷毀順序:從頭結點開始依次釋放,避免內存洩漏。
  4. 返回錯誤碼:所有操作函數返回 int 表示成功/失敗,調用者必須檢查。

鏈隊列以其動態靈活的特性,成為實現無界緩衝區、任務調度隊列、異步消息傳遞的首選結構。掌握帶頭結點的鏈表操作模式,是寫出健壯系統代碼的關鍵一步。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved