棧的原理與應用

WJnuHhail發表於2024-04-25

棧的原理與應用


大家學習資料結構的目的是為了更好的處理和儲存資料,對於順序表而言改查比較容易,增刪比較麻煩,對於鏈式表而言,增刪比較簡單,改查比較麻煩,所以每種資料結構都有不同的特點,使用者需要選擇合適的資料結構。

linux記憶體分割槽,棧記憶體自頂向下進行遞增,其實棧和順序表以及鏈式表都一樣,都屬於線性結構,儲存的資料的邏輯關係也是一對一的。

image

只不過棧是一種特殊的線性表,特殊在棧的一端是封閉的,資料的插入與刪除只能在棧的另一端進行,也就是棧遵循“*後進先出*”的原則。也被成為“LIFO”結構,意思是“last input first output”。

棧(stack),儲存貨物或供旅客住宿的地方,可引申為倉庫、中轉站,所以引入到計算機領域裡,就是指資料暫時儲存的地方,所以才有進棧(PUSH)、出棧(POP)的說法。

棧就像是一摞書,拿到新書時我們會把它放在書堆的最上面,取書時也只能從最上面的新書開始取。

image

閉合的一端被稱為棧底(Stack Bottom),允許資料的插入與刪除的一端被稱為棧頂(Stack Top),不包含任何元素的棧被稱為空棧。把資料插入到棧空間的動作被稱為入棧或者壓棧

image

l 從棧空間中刪除資料的動作被稱為出棧或者彈棧

image

由於棧也是一種線性結構,所以可以以陣列或者連結串列作為基礎,在此基礎上實現棧的操作。

  1. 以陣列作為基礎實現棧空間(順序棧)

陣列在記憶體中佔用一塊連續的空間,也就是陣列元素的記憶體地址是連續的。為了實現棧,一般是把陣列頭作為棧底,陣列頭部到陣列尾部作為棧的增長方向,也就是使用者只在陣列尾部對資料進行插入和刪除。

image

//指的是順序棧中的元素的資料型別,使用者可以根據需要進行修改

typedef int  DataType_t;

//構造記錄順序棧SequenceStack各項引數(棧底地址+棧容量+棧頂元素的下標)的結構體

typedef struct SequenceStack

{

​	DataType_t * Bottom;     //記錄棧底地址
​	unsigned int Size;      //記錄棧容量
​	int      Top;      //記錄棧頂元素的下標 

}SeqStack_t;

(1) 建立一個空的順序棧,併為記錄順序棧資訊的結構體申請堆記憶體,並進行初始化即可!

/**

  * @function name      :SeqStack_Create
  * @brief              :建立順序表並對順序棧進行初始化
  * @param              :unsigned int size
  * @retval             :SeqStack_t結構體指標
  * @date               :2024/04/25
  * @version 1.0        :V1.0
  * @note               :None
    */

//建立順序表並對順序棧進行初始化   為了方便管理順序棧所以需要構造管理順序棧資訊的結構體型別,用於記錄重要引數
SeqStack_t * SeqStack_Create(unsigned int size)
{
    //1.利用calloc為順序棧的管理結構體申請一塊堆記憶體
    SeqStack_t *Manager = (SeqStack_t *)calloc(1,sizeof(SeqStack_t));

​    if(NULL == Manager)
​    {
​        perror("calloc memory for manager is failed");
​        exit(-1); //程式異常終止
​    }

​    //2.利用calloc為所有元素申請堆記憶體
​    Manager->Bottom = (DataType_t *)calloc(size,sizeof(DataType_t));

​    if (NULL == Manager->Bottom)
​    {
​        perror("calloc memory for Stack is failed");
​        free(Manager);
​        exit(-1); //程式異常終止
​    }

​    //3.對管理順序棧的結構體進行初始化(元素容量 + 最後元素下標)
​    Manager->Size = size;   //對順序棧中的容量進行初始化
​    Manager->Top = -1;      //由於順序棧為空,則棧頂元素的下標初值為-1
​    
​    return Manager;
}

(2)判斷順序棧是否為已滿

/**

  * @function name      :SeqStack_IsFull
  * @brief              :判斷順序棧是否已滿
  * @param              :SeqStack_t *Manager
  * @retval             :布林型別
  * @date               :2024/04/25
  * @version 1.0        :V1.0
  * @note               :None
    */

//判斷順序棧是否已滿
bool SeqStack_IsFull(SeqStack_t *Manager)
{
    return (Manager->Top + 1 == Manager->Size) ? true : false;
}

(3)根據棧的特性,把新元素從棧頂入棧,也就是從陣列的尾部進行元素插入

/**

  * @function name      :SeqStack_Push
  * @brief              :壓棧(push)
  * @param              :SeqStack_t *Manager, DataType_t Data
  * @retval             :布林型別
  * @date               :2024/04/25
  * @version 1.0        :V1.0
  * @note               :None
    */

//入棧
bool SeqStack_Push(SeqStack_t *Manager, DataType_t Data)
{
    //1.判斷順序棧是否已滿
    if ( SeqStack_IsFull(Manager) )
    {
        printf("SeqStack Full is Full!\n");
        return false;
    }

​    //2.如果順序棧有空閒空間,則把新元素新增到順序棧的棧頂
​    Manager->Bottom[++Manager->Top] = Data;

​    return true;
}


(4)判斷順序棧是否為空

/**

  * @function name      :SeqStack_IsEmpty
  * @brief              :判斷順序棧是否為空
  * @param              :SeqStack_t *Manager
  * @retval             :布林型別
  * @date               :2024/04/25
  * @version 1.0        :V1.0
  * @note               :None
    */

//判斷順序棧是否為空
bool SeqStack_IsEmpty(SeqStack_t *Manager)
{
    return (-1 == Manager->Top) ? true : false;
}

(5)根據棧的特性,把元素從棧頂出棧,也就是把元素從陣列的尾部把元素刪除

//出棧

DataType_t SeqStack_Pop(SeqStack_t *Manager)

{

  DataType_t temp = 0;  //用於儲存出棧元素的值

  //1.判斷順序棧是否為空

  if ( SeqStack_IsEmpty(Manager) )

  {

​    printf("SeqStack is Empty!\n");

​    return;

  }

  

  //2.由於刪除了一個元素,則需要讓順序棧的棧頂元素下標-1

  temp = Manager->Bottom[Manager->Top--];

  return temp;

}


(6)遍歷順序棧的元素

/**

  * @function name      SeqStack_Print
  * @brief              :遍歷順序棧
  * @param              :SeqStack_t *Manager
  * @retval             :None
  * @date               :2024/04/25
  * @version 1.0        :V1.0
  * @note               :None
    */

//遍歷順序棧的元素
void SeqStack_Print(SeqStack_t *Manager)
{
    for (int i = 0; i <= Manager->Top; ++i)
    {
        printf(" Stack Element[%d] = %d\n",i,Manager->Bottom[i]);
    }
}


相關文章