鏈式棧

Yxw_lp發表於2024-04-25

以連結串列作為基礎實現棧空間(鏈式棧)

/********************************************************************************
 *
 *  file name:  LinkedStack.c
 *  author   :  yxw18679428019@163.com
 *  date     :  2024/04/25
 *  function :  實現鏈式棧的入棧(Push)與出棧(Pop)
 *  note     :  None
 *
 *  CopyRight  (c)  2023-2024   yxw18679428019@163.com    All  Right  Reseverd
 *   ****************************************************************************/
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

// 鏈棧中的元素的資料型別,使用者可以根據需求進行修改
typedef int DataType_t;

// 構建記錄鏈棧LinkedStack的各項引數(棧底地址,棧容量,棧頂元素的小標)的結構體
typedef struct LinkedStack
{
    struct LinkedStack *next;
    DataType_t data;
} LinkStack_t;

/************************************************************************
 *  name     :  LinkStack_Dreate
 *  function :  建立一個空的鏈棧,並對資料域與指標域進行初始化
 *  argument :  None
 *
 *
 *  retval   :  返回頭結點的地址
 *  author   :  yxw18679428019@163.com
 *  date     :  2024/04/25
 *  note     :  None
 *   *********************************************************************/
LinkStack_t *LinkStack_Create(void)
{
    // 建立一個頭結點並對頭結點申請記憶體
    LinkStack_t *Head = (LinkStack_t *)calloc(1, sizeof(LinkStack_t));
    // 判斷申請堆記憶體是否成功
    if (NULL == Head)
    {
        perror("calloc memroy from Head is failed");
        exit(-1);
    }

    // 進行初始化
    Head->next = NULL;

    return Head;
}


/************************************************************************
 *  name     :  LinkStack_NewNode
 *  function :  建立一個新的結點並對資料域與指標域進行初始化
 *  argument :
 *              @Data :入棧的資料
 *
 *  retval   :  返回新結點的地址
 *  author   :  yxw18679428019@163.com
 *  date     :  2024/04/25
 *  note     :  None
 *   *********************************************************************/
LinkStack_t *LinkStack_NewNode(DataType_t Data)
{
    // 1.建立一個新結點並對新結點申請記憶體
    LinkStack_t *New = (LinkStack_t *)calloc(1, sizeof(LinkStack_t));
    if (NULL == New)
    {
        perror("Calloc memory for NewNode is Failed");
        return NULL;
    }

    // 對新結點的指標域與資料域進行初始化
    New->data = Data;
    New->next = NULL;

    return New;
}


/************************************************************************
 *  name     :  LinkStack_Push
 *  function :  入棧
 *  argument :  
 *              @Head :頭結點的地址
 *              @Data :入棧的資料
 *  retval   :  true and false
 *  author   :  yxw18679428019@163.com
 *  date     :  2024/04/25
 *  note     :  None
 *   *********************************************************************/
bool LinkStack_Push(LinkStack_t *Head, DataType_t Data)
{
    // 建立一個新的結點
    LinkStack_t *New = LinkStack_NewNode(Data);
    if (NULL == New)
    {
        printf("can not insert new node!\n");
        return false;
    }

    // 如果鏈棧為空
    if (NULL == Head->next)
    {
        // 頭結點的next指標指向新結點
        Head->next = New;
        return true;
    }

    // 鏈棧為非空
    New->next = Head->next; // 新結點的next指標指向首結點
    Head->next = New;       // 頭結點的next指標指向新結點

    return true;
}

/************************************************************************
 *  name     :  LinkStack_Pop
 *  function :  出棧
 *  argument :  
 *              @Head :頭結點的地址
 *              
 *  retval   :  true and false
 *  author   :  yxw18679428019@163.com
 *  date     :  2024/04/25
 *  note     :  None
 *   *********************************************************************/
bool LinkStack_Pop(LinkStack_t *Head)
{
    LinkStack_t *Phead = Head->next; // 備份首結點
    // 判斷鏈棧是否為空
    if (NULL == Head->next)
    {
        printf("Linked Stack is empty!\n");
        return false;
    }

    // 鏈棧不為空
    if (NULL == Phead->next) // 鏈棧中只有一個首結點
    {
        Head->next = NULL; // 頭結點的next指標指向NULL
        free(Phead);       // 釋放首結點記憶體
    }
    else
    {
        Head->next = Phead->next; // 頭結點指向待刪除結點的直接後繼
        Phead->next = NULL;       // 待刪除結點的next指標指向NULL
        free(Phead);              // 釋放刪除結點的記憶體
    }
}

/************************************************************************
 *  name     :  LinkStack_Print
 *  function :  遍歷鏈式棧的每個結點並輸出每個結點的資料與的值
 *  argument :  
 *              @Head :頭結點的地址
 *              
 *  retval   :  true and false
 *  author   :  yxw18679428019@163.com
 *  date     :  2024/04/25
 *  note     :  None
 *   *********************************************************************/
bool LinkStack_Print(LinkStack_t *Head)
{
    // 對單向迴圈連結串列的頭結點的地址進行備份
    LinkStack_t *Phead = Head;

    // 判斷當前連結串列是否為空,為空則直接退出
    if (NULL == Head->next)
    {
        printf("current linked stack is empty!\n");
        return false;
    }

    // 從首結點開始遍歷
    while (Phead->next)
    {
        // 把頭結點的直接後繼作為新的頭結點
        Phead = Phead->next;

        // 輸出頭結點的直接後繼的資料域
        printf("data = %d\n", Phead->data);

        // 判斷是否到達尾結點,尾結點的next指標是指向首結點的地址
        if (Phead->next == NULL)
        {
            break;
        }
    }

    return true;
}

int main(void)
{
    LinkStack_t *Head = LinkStack_Create();
    LinkStack_Push(Head, 1);
    LinkStack_Push(Head, 2);
    LinkStack_Push(Head, 3);
    LinkStack_Print(Head);

    LinkStack_Pop(Head);
    LinkStack_Pop(Head);
    LinkStack_Pop(Head);
    LinkStack_Pop(Head);
    LinkStack_Print(Head);
    LinkStack_Push(Head, 1);
    LinkStack_Print(Head);
}

相關文章