棧的理解與實現[數據結構]

一.棧的定義

Tips:閱讀本文之前,請先熟悉鏈表知識:鏈表的理解與實現

棧是一種可以實現”先進後出“的數據結構。
棧只允許在棧頂進行插入、刪除、遍歷等操作。
如下圖:
依次放入 5-6-7 到棧內。
拿出 6來,得先拿出 7來
拿出 5來,得先拿出7、6來。
也就是7後進的,7先出棧;5先進的,5後出棧。
這裏寫圖片描述


二、棧的實現

1.初始化一個棧

1.1定義鏈表的節點結構

typedef struct Node
{
    int data;
    struct Node * pNext;
}NODE,*PNODE;

1.2定義棧的首指針與尾指針

typedef struct stack
{
    PNODE pTop;  //棧頂指針
    PNODE pBottom;//棧底指針
}STACK,*PSTACK;

1.3初始化一個棧

//初始化一個棧
void initStack(PSTACK pS)
{
    pS->pTop=(PNODE)malloc(sizeof(NODE));
    if(pS->pTop==NULL)
    {
        printf("棧初始化失敗\n");
        exit(-1);
    }
    else
    {
        pS->pBottom=pS->pTop;
        pS->pBottom->pNext=NULL;
    }
}

如果此棧初始化成功,會有如下圖示的結構:
這裏寫圖片描述

2.壓棧

壓棧就是在棧頂壓入一個元素。
壓棧分爲3步:
1.創建一個新節點存放數值;
2.使新節點指向pTop指向的元素;
3.使pTop指向新元素。

代碼實現:

//壓棧
void pushStack(PSTACK pS,int val)
{
    //1.創建一個新節點存放數值;
    PNODE pNew=(PNODE)malloc(sizeof(NODE));
    pNew->data=val;
    //2.使新節點指向pTop指向的元素;
    pNew->pNext=pS->pTop;
    //3.使pTop指向新元素。
    pS->pTop=pNew;
}

如圖:
壓棧前:
這裏寫圖片描述
壓棧後
這裏寫圖片描述

3.遍歷棧

3.1判斷棧是否爲空(空則不遍歷,直接返回)

當棧頂與棧底相等的時候,棧就是空棧。

//判斷棧是否爲空
int isEmpty(PSTACK pS)
{
    if(pS->pTop==pS->pBottom)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

3.2遍歷棧

只要棧頂與棧底不相等,就遍歷棧

//遍歷棧
void traverseStack(PSTACK pS)
{
    if(isEmpty(pS))
    {
        printf("棧爲空,不可遍歷\n");
    }
    else
    {
        PNODE p=pS->pTop;
        while(p!=pS->pBottom)
        {
            printf("%d ",p->data);
            p=p->pNext;
        }
        free(p);
        pS->pTop=pS->pBottom;
    }
}

4.出棧

出棧分爲三步:
1. 創建一個指針p保存pTop指針
2. 讓pTop指針指向下一個元素
3. 釋放掉p
如圖:
這裏寫圖片描述

//出棧
void popStack(PSTACK pS)
{
    if(isEmpty(pS))
    {
        printf("空棧,不可出棧\n");
    }
    else
    {
        //創建一個指針p保存pTop指針
        PNODE p=pS->pTop;
        //讓pTop指針指向下一個元素
        pS->pTop=p->pNext;
        //釋放掉p
        free(p);
    }
}

5.清空棧

1.我們直接讓pTop=pBottom是否可行?

這樣雖然清空了棧,但是pTop—pBottom之間的內存並沒有被釋放,會造成內存泄露,這樣不行。

2.我們先釋放pTop—pBottom之間的內存,再讓pTop=pBottom。

//清空棧
void clearStack(PSTACK pS)
{
    if(isEmpty(pS))
    {
        return ;
    }
    else
    {
        PNODE p=pS->pTop;
        //1.清空pTop---pBottom之間的內存
        while(p!=pS->pBottom)
        {
            PNODE q=p->pNext;
            free(p);
            p=q;
        }
        free(p);
        //2.讓pTop=pBottom
        pS->pTop=pS->pBottom;
    }
}

三.總體代碼

#include <stdio.h>
#include <stdlib.h>
//鏈表節點的數據結構
typedef struct Node
{
    int data;
    struct Node * pNext;
}NODE,*PNODE;
//棧的數據結構
typedef struct stack
{
    PNODE pTop;
    PNODE pBottom;
}STACK,*PSTACK;
//初始化一個棧
void initStack(PSTACK pS)
{
    pS->pTop=(PNODE)malloc(sizeof(NODE));
    if(pS->pTop==NULL)
    {
        printf("棧初始化失敗\n");
        exit(-1);
    }
    else
    {
        pS->pBottom=pS->pTop;
        pS->pBottom->pNext=NULL;
    }
}
//壓棧
void pushStack(PSTACK pS,int val)
{
    PNODE pNew=(PNODE)malloc(sizeof(NODE));
    pNew->data=val;
    pNew->pNext=pS->pTop;
    pS->pTop=pNew;

}
//判斷棧是否爲空
int isEmpty(PSTACK pS)
{
    if(pS->pTop==pS->pBottom)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
//遍歷棧
void traverseStack(PSTACK pS)
{
    if(isEmpty(pS))
    {
        printf("棧爲空,不可遍歷\n");
    }
    else
    {
        PNODE p=pS->pTop;
        while(p!=pS->pBottom)
        {
            printf("%d ",p->data);
            p=p->pNext;
        }
        free(p);
        pS->pTop=pS->pBottom;
    }
}
//出棧
void popStack(PSTACK pS)
{
    if(isEmpty(pS))
    {
        printf("空棧,不可出棧\n");
    }
    else
    {
        //創建一個指針p保存pTop指針
        PNODE p=pS->pTop;
        //讓pTop指針指向下一個元素
        pS->pTop=p->pNext;
        //釋放掉p
        free(p);
    }
}
//清空棧
void clearStack(PSTACK pS)
{
    if(isEmpty(pS))
    {
        return ;
    }
    else
    {
        PNODE p=pS->pTop;
        while(p!=pS->pBottom)
        {
            PNODE q=p->pNext;
            free(p);
            p=q;
        }
        free(p);
        pS->pTop=pS->pBottom;

    }
}
int main()
{
    STACK s;
    initStack(&s);
    pushStack(&s,3);
    pushStack(&s,2);
    pushStack(&s,1);
    popStack(&s);
    clearStack(&s);
    traverseStack(&s);
    return 0;
}

四.總結

棧是一種非常重要的線性結構,也是非常基本的數據結構。本文用鏈表的方式實現了棧。
棧在計算機領域有很多應用。
比如:函數的調用用到棧、判斷迴文也用到棧的知識。

所以,我們一定要掌握它!

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