資料結構-佇列、棧

sleeeeeping發表於2024-07-20

功能受限的表結構

一、棧和佇列介紹

  • 棧和佇列是兩種重要的線性結構,從資料結構角度,他們都是線性表,特殊點在於它們的操作被限制,也就是所謂的功能受限,統稱功能受限的線性表
  • 從資料型別角度,它們也可以是看成處理、管理資料的一種規則

二、棧結構

  • 棧(stack)是限定在表尾進行資料的插入、刪除等操作的線性表(只允許操作一個埠的資料)

  • 表尾稱為棧頂,表頭稱為棧底 ,當沒有元素的空表稱為空棧,當元素的數量到達棧的容量時稱為滿棧 ,新增資料到棧頂中的動作稱為入棧壓棧,把資料從棧頂中拿出的動作稱為出棧彈棧,正因為這個資料的新增、刪除的規則,所以棧中元素滿足先進後出,簡稱FILO表LIFO

  • 棧結構可以具備的功能

    • 建立

    • 銷燬

    • 是否滿棧

    • 是否空棧

    • 入棧

    • 出棧

    • 檢視棧頂元素

    • 檢視元素數量

      注意:只有順序棧才有需要判斷棧是否滿

1、棧結構的順序實現

//  設計順序棧結構
typedef struct ArrayStack {
    TYPE* ptr;      //  儲存棧元素的記憶體首地址
    size_t cap;     //  棧的容量
    size_t top;     //  棧頂的位置 
} ArrayStack;

程式碼實現

2、棧結構的鏈式實現

#define TYPE int

typedef struct ListNode {
    TYPE data;
    struct ListNode* next;
} ListNode;

//  鏈式棧結構
typedef struct ListStack {
    ListNode* top;      // 棧頂指標 指向棧頂節點
    size_t size;        // 節點數量
} ListStack;

程式碼實現

3、棧的應用

  • 記憶體管理,例如棧記憶體,之所以叫棧記憶體因為它遵循棧的先進後出原則,函式呼叫、函式引數的傳參、定義,先把資料入棧,等結束時,逆序出棧,函式的呼叫、結束跳轉也是遵循棧結構原則
  • 特殊的演算法:算術表示式的轉換(中綴表示式轉字尾表達) 、進位制轉換、迷宮演算法

三、佇列結構

1、佇列介紹

  • 與棧結構相似的是,也只允許在埠處進行新增、刪除操作,但是有兩個埠,一個負責新增資料,稱為入隊 ,該埠稱為隊尾,另一個埠只負責刪除資料,稱為出隊,該埠稱為隊頭,屬於一種先進先出結構,稱為FIFO

2、佇列所具備的功能

  • 建立佇列
  • 銷燬佇列
  • 判斷隊空
  • 判斷隊滿 (只有順序儲存時才有)
  • 入隊
  • 出隊
  • 檢視隊頭元素
  • 檢視隊尾元素
  • 佇列元素數量

3、佇列的鏈式實現

#define TYPE int

typedef struct ListNode {
    TYPE data;
    struct ListNode* next;
} ListNode;

//  設計鏈式佇列結構
typedef struct ListQueue {
    ListNode* front;    //  隊頭
    ListNode* rear;     //  隊尾
    size_t size;        //  節點數量
} ListQueue;

程式碼實現

4、佇列的順序實現

  • 順序佇列的隊尾下標rear會隨著入隊而增大rear+1,隊頭下標front會隨著出隊增大front+1,因為是順序結構,就有隨著入隊和出隊的進行,可能超出有效的下標範圍,如果不進行處理,那麼佇列無法重複使用。
  • 為了避免這種情況,當隊尾、隊頭下標達到儲存空間的末尾時,要想辦法讓它們回到記憶體的開頭位置,相當於把記憶體想象成一個環形,從而可以迴圈使用佇列,這樣的佇列稱為迴圈佇列
    • 因此當隊尾、隊頭下標增加時,都要對佇列的容量求餘
    • rear = (rear+1)%cap
    • front = (front+1)%cap

帶計數器版本的迴圈佇列

  • 很直接地解決了元素數量的問題
  • 可以直接解決隊空、隊滿的判斷矛盾問題
  • 但是在佇列結構中會多增加一個資料項,並且每次入隊、出隊操作都要對其進行修改
typedef struct ArrayQueue {
    TYPE* ptr;      //  儲存元素的記憶體首地址
    size_t cap;     //  容量
    size_t cnt;     //  元素個數  計數器
    int front;      //  隊頭下標
    int rear;       //  隊尾下標
} ArrayQueue;

程式碼實現

不帶計數器的版本

程式碼實現

相關文章