鏈式隊列的八種基本運算[考研重點]

NOTICE: 代碼測試沒問題,直接複製就能跑!

環境:

Visual Stdio Code

 

鏈式隊列和有頭尾結點的單鏈表:

鏈式隊列可以看成一個有頭尾節點的單鏈表,但是它跟有頭尾節點的單鏈表的唯一區別就是:鏈式隊列只能從一端(rear 端)插入,從另一端(front 端)刪除。

 

廢話不多說,上代碼:

#include<stdio.h>
#include<stdlib.h>

#define MAXQSIZE 100  // 最大隊列長度
#define ERROR 0
#define OK 1

typedef int QElemType;
typedef int Status;

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

typedef struct 
{
    QueuePtr front;   // 隊頭指針
    QueuePtr rear;    // 隊尾指針
}LinkQueue;

Status InitQueue(LinkQueue &Q)
{   // 初始化
    Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));  // 分配兩個空間,一個 data 一個 next
    if(!Q.front)  return ERROR;    // 分配失敗
    Q.front->next = NULL;

    return OK;
}//InitQueue

Status DestroyQueue(LinkQueue &Q)
{   // 銷燬
    while(Q.front)      // 如果 front 不爲空
    {
        Q.rear = Q.front->next;     // rear 指向 front 的直接後繼結點
        free(Q.front);              // 釋放 front 指向的結點
        Q.front = Q.rear;           // 將 front 後移
    }
    return OK;
}//DestroyQueue

Status EnQueue(LinkQueue &Q, QElemType e)
{   // 插入新元素 e
    QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
    if(!p) return ERROR;                            // 分配失敗
    p->data = e;                                    
    p->next = NULL;                                 
    Q.rear->next = p;                               // 插入的是隊尾
    Q.rear = p;                                     // 隊尾指針後移

    return OK;
}//EnQueue

Status DeQueue(LinkQueue &Q, QElemType &e)
{   // 刪除隊頭元素, 用 e 返回
    if(Q.front == Q.rear) return ERROR;             // 判斷隊列是否爲空
    QueuePtr p = Q.front->next;                     
    e = p->data;
    Q.front->next = p->next;
    if(Q.rear == p) Q.rear = Q.front;
    free(p);

    return e;
}//DeQueue

Status ClearQueue(LinkQueue &Q)
{   // 清空
    QueuePtr p, q;
    if(Q.front == Q.rear)  return ERROR;        // 隊列爲空
    Q.rear = Q.front;                          // 空隊列的 rear 與 front 指向的是同一個結點
    p = Q.front->next;                          // p 指向 front 的直接後繼結點
    Q.front->next = NULL;                       // 將 front 指向的結點的 next 置位空
    while(p)
    {
        q = p;                                  // 逐個刪除
        p = p->next;
        free(q);
    }
    return OK;
}//ClearQueue

Status QueueEmpty(LinkQueue &Q)
{   // 判斷隊列是否爲空
    return Q.front == Q.rear;
}//QueueEmpty

Status QueueLength(LinkQueue &Q)
{   // 輸出非空隊列的長度
    int i = 0;
    QueuePtr p;
    p = Q.front;
    while(p != Q.rear)
    {
        p = p->next;
        i++;
    }
    return i;
}//QueueLength

Status GetHead(LinkQueue &Q, QElemType e)
{   // 用 e 返回 Q 的隊頭元素
    if(Q.front == Q.rear)  return ERROR;
    e = Q.front->next->data;                // 隊頭元素可類比於單鏈表的首元結點
    return e;
}//GetHead

Status QueueTraverse(LinkQueue &Q)  // 書上還有一個形參: visit() 這個形參可以看成一個打印函數,這裏我們用的是 printf()
{   // 打印隊列元素
    QueuePtr p;
    if(Q.front == Q.rear)  return ERROR;    // 隊列爲空
    p = Q.front->next;                      // p 指向隊列的隊頭結點
    while(p)
    {
        printf("%d\t", p->data);
        p = p->next;
    }
    return OK;
}//QueueTraverse

int main()
{
    int choice = 1;
    LinkQueue Q;
    QElemType e;
    printf("請輸入序號進行相應的操作:\n");
    while(choice)
    {    
        printf("\n1.InitQueue   2.QueueLength   3.QueueTraverse   4.GetHead   5.ClearQueue \n6.EnQueue   7.DeQueue   8.QueueEmpty   9.DestroyQueue   0.exit\n");
        scanf("%d", &choice);
        switch (choice)
        {
            case 1:
                if(InitQueue(Q))
                    printf("\n初始化隊列成功!\n");
                break;
            case 2:
                if(QueueEmpty(Q))
                    printf("\n隊列爲空\n");
                else
                    printf("\n隊列的長度爲:%d\n", QueueLength(Q));
                break;
            case 3:
                if(QueueEmpty(Q))
                    printf("\n隊列爲空\n");
                else
                {
                    printf("\n隊列元素爲:\n");
                    QueueTraverse(Q);
                }
                break;
            case 4:
                if(!QueueEmpty(Q))
                    printf("\n隊列的隊頭元素爲:%d\n", GetHead(Q, e));
                else
                    printf("\n隊列爲空\n");
                break;
            case 5:
                if(QueueEmpty(Q))
                    printf("\n隊列爲空!\n");
                else if(ClearQueue(Q))
                    printf("\n成功清空隊列!\n");
                break;
            case 6:
                printf("\n請輸入想要插入的的元素:\n");
                scanf("%d", &e);
                if(EnQueue(Q, e))
                    printf("\n插入成功!\n");
                else
                    printf("\n插入失敗!\n");
                break;
            case 7:
                if(QueueEmpty(Q))
                    printf("\n隊列爲空!\n");
                else
                    printf("\n刪除的隊頭元素爲:%d\n", DeQueue(Q, e));
                break;
            case 8:
                if(QueueEmpty(Q))
                    printf("\n隊列爲空!\n");
                else
                    printf("\n隊列不爲空!\n");
                break;
            case 9:
                if(DestroyQueue(Q))
                    printf("\n銷燬成功\n");
                else
                    printf("\n銷燬失敗!\n");
                break;
            case 0:
                choice = 0;
                break;
            default:
                printf("\n程序出錯!\n");
                break;
        }
    }
    DestroyQueue(Q);
    return 0;
}

運行結果示意圖就不貼出來了,太長了!

THE END!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章