隊列的鏈式存儲結構及實現


ref : https://blog.csdn.net/qq_29542611/article/details/78907339


 

隊列的鏈式存儲結構,其實就是線性表的單鏈表,只不過它只是尾進頭出而已,我們把它簡稱為鏈隊列。為了操作上的方便,我們將隊頭指針指向鏈隊列的頭結點,而隊尾指針指向終端節點。如果


 

 

空隊列時,front和rear都指向頭結點。

 


入隊操作:

 

在隊尾添加元素,先將隊尾元素的next指向添加的元素,然后將隊尾指針重新指向新的隊尾即可。

出隊操作:

頭結結點指向的結點即為隊頭結點,出隊操作,就是把隊頭結點干掉,先把頭結點指向新的隊頭結點(也就是舊的隊頭結點的后繼結點),然后釋放舊的隊頭結點。如果鏈表除頭結點外只剩一個元素時,則需將rear指向頭結點即可

 

下面是隊列鏈式存儲結構實現的具體代碼:

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #include <stdlib.h>
    #define QUEUESIZE 10
    #define ERROR 0
    #define OK 1
    #define TRUE 1
    #define FALSE 0
    #define EleType int
    #define Status int
    //鏈隊列結點
    typedef struct QueueNode
    {
    EleType e;//數據域
    struct QueueNode* next;//指針域
    }QueueNode,*LinkQueuePoi;
    typedef struct LinkQueue
    {
    LinkQueuePoi front;//指向頭結點
    LinkQueuePoi rear;//指向隊尾
    }LinkQueue;
    /*
    初始化鏈隊列
    鏈隊列為空時,鏈隊列隊頭指針隊尾指針均指向頭結點
    */
    Status InitLinkQueue(LinkQueue* queue)
    {
    //空指針
    if (!queue)
    {
    return ERROR;
    }
    QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));//頭結點
    node->next = NULL;
    queue->front = queue->rear = node;
    return OK;
    }
    /*
    清空鏈隊列
    將所有元素釋放
    */
    Status CleaerLinkQueue(LinkQueue* queue)
    {
    //空指針
    if (!queue)
    {
    return ERROR;
    }
    //空鏈隊列
    if (queue->front == queue->rear)
    {
    return ERROR;
    }
    QueueNode* node = queue->front->next;//隊頭元素
    while (node)
    {
     
    queue->front->next = node->next;//指向新的隊頭結點
    if (queue->rear == node)//當刪除的是隊尾元素時,將隊尾指針指向頭結點
    {
    queue->rear = queue->front;
    }
    free(node);//釋放舊的隊頭結點
    node = queue->front->next;
    }
    return OK;
    }
    /*
    判斷鏈隊列是否為空隊列
    */
    Status EmptyLinkQueue(LinkQueue* queue)
    {
    //空指針
    if (!queue)
    {
    return ERROR;
    }
    //空鏈隊列
    if (queue->front == queue->rear)
    {
    return TRUE;
    }
    return FALSE;
    }
    /*
    獲取鏈隊列長度
    */
    int LengthLinkQueue(LinkQueue* queue)
    {
    //空指針
    if (!queue)
    {
    return ERROR;
    }
    //空鏈隊列
    if (queue->front == queue->rear)
    {
    return 0;
    }
    QueueNode* node = queue->front->next;
    int num = 0;
    while (node)
    {
    node = node->next;
    num++;
    }
    return num;
    }
    /*
    在鏈隊列隊尾添加元素
    先將新元素添加到鏈表尾部,然后將隊列尾指針指向這個新元素
    */
    Status AddQueue(LinkQueue* queue,EleType e)
    {
    //空指針
    if (!queue)
    {
    return ERROR;
    }
    QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));
    if (!node)
    {
    return ERROR;
    }
    node->next = NULL;
    node->e = e;
    queue->rear->next = node;//將新結點添加到鏈表表中
    queue->rear = node;//隊尾指針指向新的隊尾結點
    return OK;
    }
    /*
    從鏈隊列中刪除隊頭元素
    先將頭結結點指向新的隊頭結點,然后釋放原來的隊頭結點
    */
    Status DelQueue(LinkQueue* queue, EleType *e)
    {
    //空指針
    if (!queue)
    {
    return ERROR;
    }
    //注意queue->front是頭結點,頭結點指向的結點才是隊頭結點
    QueueNode* node = queue->front->next;//舊隊頭結點
    *e = node->e;
    queue->front->next = node->next;//隊頭指針指向新的隊頭結點
    //當刪除的是隊尾元素時,將隊尾指針指向頭結點
    if (node = queue->rear)
    {
    queue->rear = queue->front;
    }
    return OK;
    }
    /*
    打印鏈隊列元素
    */
    void PrintfLinkQueue(LinkQueue* queue)
    {
    if (!queue)
    {
    return;
    }
    QueueNode* node = queue->front->next;
    while (node)
    {
    printf("%d,", node->e);
    node = node->next;
    }
    printf("\n");
    return;
    }
    int main(int argc, char *argv[])
    {
    LinkQueue queue;
    InitLinkQueue(&queue);
    AddQueue(&queue, 1);
    AddQueue(&queue, 2);
    AddQueue(&queue, 3);
    AddQueue(&queue, 4);
    AddQueue(&queue, 5);
    AddQueue(&queue, 6);
    AddQueue(&queue, 7);
    AddQueue(&queue, 8);
    AddQueue(&queue, 9);
    printf("鏈隊列元素個數:%d\n",LengthLinkQueue(&queue));
    printf("展示元素:\n");
    PrintfLinkQueue(&queue);
    int e1, e2;
    DelQueue(&queue, &e1);
    DelQueue(&queue, &e2);
    printf("刪除元素:%d,%d\n", e1, e2);
    printf("展示元素:\n");
    PrintfLinkQueue(&queue);
    printf("鏈隊列元素個數:%d\n", LengthLinkQueue(&queue));
    CleaerLinkQueue(&queue);
    printf("清空元素后,長度為%d,rear = %p,front=%p",LengthLinkQueue(&queue), queue.rear,queue.front);
    printf("\n");
    return 0;
    }

 

驗證結果截圖:

 

對於循環隊列與鏈隊列的比較,可以從時間和空間2方面來考慮,從時間上,他們的基本操作都是常數時間,即都為O(1),不過循環隊列是事先申請好空間,使用期間不釋放,而對於鏈隊列,每次申請和釋放結點也會存在一些時間開銷,如果入隊出隊頻繁,則2者還是有些細微的差異。對於空間方面來說,循環隊列必須有一個固定的長度,所以就有了存儲元素個數和空間浪費的問題。而鏈隊列就不存在這個問題,盡管它需要一些指針域,會產生一些空間上的開銷,但也可以接受。所以在空間上,鏈隊列更加靈活。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM