1. 程式人生 > 其它 >佇列的鏈式表示和實現

佇列的鏈式表示和實現

若使用者無法估計所用佇列的長度,則宜採用鏈佇列

鏈式隊列表示:如圖

Q.front 指向頭結點

Q.rear 指向尾結點

鏈佇列的型別定義:

#define MAXQSIZE 100 //最大佇列長度
typedef struct Qnode{
    // 資料域
    QElemType data;
    // 指標域
    // 棧是stack,所以是SNode
    // 佇列是 Queue,所以是QNode
    // 所指向結點仍然是 Qnode 這種型別
    stuct Qnode *next;
}QNode, *QuenPtr;
typedef struct{
    // 隊頭指標
QueuePtr front; // 隊尾指標 QueuePtr rear; // 鏈式佇列 } LinkQueue;

鏈佇列運算指標的變化狀況

① 空佇列時,頭指標尾指標都指向一個結點,如圖:

② 元素 x 入佇列,Q.rear 只能指向隊尾

再有元素入隊,如下圖

③ 要出隊時,只能出 x ,不能直接出 y

------------------------------------------------------------------------------------------------------------------------------------------------

鏈佇列的操作——鏈佇列初始化

直接在記憶體當中找到一個頭結點,然後首尾指標都指向頭結點

#define MAXQSIZE 100 //最大佇列長度
typedef struct Qnode{
    // 資料域
    QElemType data;
    // 指標域
    // 棧是stack,所以是SNode
    // 佇列是 Queue,所以是QNode
    // 所指向結點仍然是 Qnode 這種型別
    stuct Qnode *next;
}QNode, *QuenPtr;


typedef struct{
    // 隊頭指標
    QueuePtr front;

    // 隊尾指標
QueuePtr rear; // 鏈式佇列 } LinkQueue; Status InitQueue(LinkQueue &Q){ Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode)); // 加一個記憶體溢位判斷,防止出問題 if(!Q.front){ exit(OVERFLOW); } // next 域置空 Q.front->next = NULL; }

鏈佇列的操作——銷燬棧佇列

銷燬棧佇列就是從隊頭結點開始,依次釋放所有結點

Status DestroyQueue(LinkQueue &Q){
    while(Q.front){
        p = Q.front -> next;
        free(Q.front);
        Q.front = p;
return OK; } }

或者使用如下程式碼:

Status DestroyQueue(LinkQueue &Q){
    Q.rear = Q.front -> next;
    free(Q.front);
    Q.front = Q.rear;
    return OK;
}

鏈佇列的操作——將元素 e 入隊

鏈佇列入隊,只能在隊尾入,也就是從 an 後入隊

#define MAXQSIZE 100 //最大佇列長度
typedef struct Qnode{
    // 資料域
    QElemType data;
    // 指標域
    // 棧是stack,所以是SNode
    // 佇列是 Queue,所以是QNode
    // 所指向結點仍然是 Qnode 這種型別
    stuct Qnode *next;
}QNode, *QuenPtr;


typedef struct{
    // 隊頭指標
    QueuePtr front;

    // 隊尾指標
    QueuePtr rear;

// 鏈式佇列
} LinkQueue;

Status EnQueue(LinkQueue &Q, QElemType e){
    // 開闢一個記憶體空間
    p = (QueuePtr)malloc(sizeof(QNode));

    // 如果分配不成功,則直接退出
    if(!p){
        exit(OVERFLOW);
    }

    // 將 e 存入 p所指結點 的資料域,且將 P所指結點 
    p -> data = e;
    p -> next = NULL;

    // 尾指標所指結點的指標域修改,使其接上新新增的結點
    Q.rear -> next = p;

    // 修改尾指標所指向結點
    Q.rear = p;

    return OK;
}

鏈佇列的操作——鏈隊列出隊

鏈佇列的出隊是從隊頭出隊的,因此要刪掉頭結點後面的那個結點

直接修改前驅的指標域,就可以完成。最後再釋放掉

① new 一個指標p,使 指標p 指向頭結點後邊那個結點

p = Q.fornt -> next;

② 修改 Q.front -> next ,使其原本指向出隊結點的指標域指向出隊結點後邊那個結點

Q.front -> next = p -> next;

③ 釋放掉指標P

用 C++ 就是 delete p;

用 C 就是 free(p);

④ 假如需要知道出隊的元素是啥,就讓 e 存放並返回:

e = p -> data;

具體程式碼如下:

#define MAXQSIZE 100 //最大佇列長度
typedef struct Qnode{
    // 資料域
    QElemType data;
    // 指標域
    // 棧是stack,所以是SNode
    // 佇列是 Queue,所以是QNode
    // 所指向結點仍然是 Qnode 這種型別
    stuct Qnode *next;
}QNode, *QuenPtr;


typedef struct{
    // 隊頭指標
    QueuePtr front;

    // 隊尾指標
    QueuePtr rear;

// 鏈式佇列
} LinkQueue;

Status DeQueue(LinkQueue &Q, QElemType &e){
    
    // 判空
    if(Q.front == Q.rear){
        return ERROR;
    }

    p = Q.front -> next;
    e = p -> data;
    Q.front -> next = p -> next;
    
    // 如果刪除後,p 指標向後移動一個,下一個元素正好就是尾結點
    // 那麼就不僅要修改頭結點的指標,也要修改尾指標
    if(Q.rear == p){
        Q.rear = Q.front;
    }

    delete p;
    return OK;
}

鏈佇列的操作——求鏈佇列的隊頭元素

#define MAXQSIZE 100 //最大佇列長度
typedef struct Qnode{
    // 資料域
    QElemType data;
    // 指標域
    // 棧是stack,所以是SNode
    // 佇列是 Queue,所以是QNode
    // 所指向結點仍然是 Qnode 這種型別
    stuct Qnode *next;
}QNode, *QuenPtr;


typedef struct{
    // 隊頭指標
    QueuePtr front;

    // 隊尾指標
    QueuePtr rear;

// 鏈式佇列
} LinkQueue;

// 求鏈佇列的隊頭元素
Status GetHead(LinkQueue Q, QElemType &e){
    if(Q.front == Q.rear){
        return ERRORl;
    }
    e = Q.front -> next -> data;
    return OK;
}