隊列---鏈隊列:隊列的鏈式存儲結構


一、鏈隊列的基本結構

隊列的鏈式存儲結構,其實就是線性表的單鏈表,只不過它只能尾進頭出而已,我們把它簡稱為鏈隊列。

為了操作上的方便,我們將隊頭指針指向鏈隊列的頭結點,而隊尾指針指向終端結點。鏈隊列示意圖:

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

二、鏈隊列結構體定義

鏈隊列結構體的定義,需要兩個步驟:
(1)鏈隊列節點的定義

/* QElemType類型根據實際情況而定,這里假設為int */
typedef int QElemType;

typedef struct QNode            /* 結點結構 */
{
    QElemType data;
    struct QNode *next;
} QNode;

(2) LinkQueue的結構體定義。只要定義隊頭和隊尾指針即可。

typedef struct          /* 隊列的鏈表結構 */
{
    QNode *front; /* 隊頭、隊尾指針 */
    QNode *rear;
} LinkQueue;

三、實現要點

1、初始化。

鏈隊列的初始化可以依據單鏈表的初始化,單鏈表的初始化是這樣的:

(1)首先產生頭結點(分配內存空間),並使L指向此頭結點:

L=(LinkList*)malloc(sizeof(Node));

(2)再將指針域置空:L->next=NULL;

因此,鏈隊列的初始化如下:

(1)產生頭結點 (LinkQueue)malloc(sizeof(LinkQueue)),然后讓隊頭指針(頭指
針)與隊尾指針都指向頭結點。
(2)置空頭結點 Q->front 的指針域 Q->front->next=NULL;

代碼如下:

/* 構造一個空隊列q */
LinkQueue *InitQueue(LinkQueue *q)
{
    q->front = q->next =(QNode*)malloc(sizeof(QNode));
    q->front->next = NULL;
    return q;
}

2、入隊。入隊操作就是在鏈隊列的尾部插入結點。

如上圖,入隊操作步驟大致如(1)(2)所示。實現算法為:

(1)創建結點s,QNode p=(QNode)malloc(sizeof(QNode));
(2)給s的data域賦值e,指針域next賦值null。p->data=e;p->next=NULL; 目的
是讓它成為新的隊尾元素。
(3)前任隊尾元素呢?直接讓它的指針域指向p。Q->rear->next=p;
(4)把隊尾指針重新指向新任隊尾s。Q->rear=p;

3、出隊。出隊操作時,就是頭結點的后繼結點(隊頭)出隊,將頭結點的后繼改為它后面的結點,若鏈表除頭結點外只剩一個元素時,則需將rear指向頭結點。

一般情況下,鏈隊列的出隊圖示:

如果鏈隊列只剩下一個元素的時候,出隊則如下圖:

具體步驟:
(1)如圖中,要刪除掉a1結點,思路很簡單,就是讓頭結點Q->front的后繼next直接指向a2。但是a2如何標識呢?
(2)假設a1結點為p結點,那么a2就是p->next了。如何讓a1結點存到p呢?
(3)直接讓頭結點的后繼指向p就行,p=Q->front->next;
(4)假如隊尾已經是p結點的話(Q->rear==p),隊尾指針需要指向頭結點Q->rear=Q->front;
(5)最后把p free掉。

四、鏈隊列代碼實現

#include <iostream>
#include<stdlib.h>
using namespace std;

typedef int QElemType;

typedef struct QNode
{
    QElemType data;
    struct QNode *next;
}QNode;
typedef struct
{
    QNode *front;
    QNode *rear;
}LinkQueue;

// 構造一個空隊列q
LinkQueue *InitQueue(LinkQueue *q)
{
    q->front = q->rear =(QNode*)malloc(sizeof(QNode));
    q->front->next = NULL;
    return q;
}

// 元素入隊
LinkQueue *EnQueue(LinkQueue *q, QElemType e)
{
    QNode *p = (QNode*)malloc(sizeof(QNode));//為插入節點分配空間
    if(!p)
    {//分配空間失敗
        cout<<"插入節點內存分配失敗!"<<endl;
    }
    else
    {   //建節點
        p->data = e; //為插入節點數據域賦值
        p->next = NULL;//為插入節點指針域賦值
        //實現插入
        q->rear->next = p;//插入到隊尾
        q->rear = p;//隊尾指針重新指向新任隊尾
    }
    return q;
}
//元素出隊
LinkQueue *DeQueue(LinkQueue *q)
{
    QNode *p;
    if(q->front == q->rear)
    {
        cout<<"鏈隊列已空,不可再執行刪除操作!"<<endl;
    }
    else
    {
        p = q->front->next;//將欲刪除的隊頭結點暫存給p
        QElemType e = p->data;//把隊頭數據賦給e
        cout<<"delete: "<<e<<endl;
        q->front->next = p->next;//刪除,將原隊頭結點的后繼p->next賦值給頭結點后繼
        if(q->rear == p)
        {//若隊頭就是隊尾,則刪除后將rear指向頭結點
            cout<<"鏈隊列數據全部刪除完畢!"<<endl;
            q->rear = q->front;
        }
        free(p);
    }
    return q;
}
//返回隊頭元素
void GetQHead(LinkQueue *q)
{
    QNode *p;
    if(q->front == q->rear)
    {
        cout<<"鏈隊列為空,無法返回隊頭數據"<<endl;
    }
    else
    {
        p = q->front->next;//隊頭
        cout<<"隊頭元素:"<<p->data<<endl;
    }
}
//求隊列長度
void QueueLength(LinkQueue *q)
{
    int length = 0;
    QNode *p;
    p = q->front->next;//隊頭
    while(p)
    {
        length++;
        p = p->next;
    }
    cout<<"隊列長度:"<<length<<endl;
}
//打印。帶頭結點,真正存儲元素的位置從頭結點下一位置(隊頭)開始!!!
void PrintQueue(LinkQueue *q)
{
    QNode *p;//隊頭
    p = q->front->next;//頭結點的下一節點,即為隊頭!!!
    while(p)
    {//從隊頭開始,依次往后遍歷
        cout<<p->data<<" ";
        p = p->next;
    }
    cout<<endl;
}
int main()
{
    LinkQueue *q = InitQueue(q);

    EnQueue(q, 1);
    PrintQueue(q);
    EnQueue(q, 2);
    PrintQueue(q);
    EnQueue(q, 3);
    PrintQueue(q);
    EnQueue(q, 4);
    PrintQueue(q);

    GetQHead(q);

    QueueLength(q);
    cout<<"***************"<<endl;
    DeQueue(q);
    PrintQueue(q);
    GetQHead(q);

    DeQueue(q);
    PrintQueue(q);
    GetQHead(q);

    DeQueue(q);
    PrintQueue(q);

    DeQueue(q);
    PrintQueue(q);

    QueueLength(q);

    cout<<"***************"<<endl;
    DeQueue(q);
    cout<<"***************"<<endl;

    return 0;
}

輸出結果:

1
1 2
1 2 3
1 2 3 4
隊頭元素:1
隊列長度:4
***************
delete: 1
2 3 4
隊頭元素:2
delete: 2
3 4
隊頭元素:3
delete: 3
4
delete: 4
鏈隊列數據全部刪除完畢!

隊列長度:0
***************
鏈隊列已空,不可再執行刪除操作!
***************

Process returned 0 (0x0)   execution time : 0.053 s
Press any key to continue.

更多參考


免責聲明!

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



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