1. 程式人生 > >棧的鏈式儲存結構實現()

棧的鏈式儲存結構實現()

18.11.18

學習過之前的順序的棧了,這回介紹一下鏈式的棧

我們對棧進行操作時,通常都是在其棧頂進行,所以我們應該在鏈的頭部進行操作,我們之前學過的連結串列大多是有頭結點的,頭結點可以大大方便我們對連結串列的呼叫,現在,我們的這個鏈棧可以通過設定一個棧頂指標top來代替頭結點,或者說起到頭結點的作用

結構定義

鏈棧有些不同的是,我們需要定義兩個結構體,比之前稍增加了點難度,第一個結構體,是用來定義鏈棧中的每一個結點的(包括top結點)的結構,即StackNode,第二個結構體,是用來定義棧頂指標的,其包含top結點以及一個計數器count,我們通常將第二個結構體命名為LinkStack,因為當我們需要壓棧和出棧時,需要呼叫函式,呼叫函式時,需要傳入引數,一般都是傳入棧頂指標來對整個鏈棧進行操作的,所以直接把棧頂指標命名為LinkStack(即鏈棧),就應該是它可以代表整個鏈棧了吧(個人理解)

typedef int SElemType;
//這裡將SElemType等同於int,實際運用中資料不一定是int的,可以改變

typedef struct StackNode{//這裡設定鏈棧的結點結構
    //每個結點包含一個數據域和一個指標域
    SElemType data;
    struct StackNode *next;
}StackNode,*pNode;//*pNode是結點的結構體指標

typedef struct LinkStack{//這裡設定棧頂指標
//包含了top結點的地址和一個計數器count
    pNode top;
    int count;
}LinkStack;

鏈棧初始化

跟連結串列很像,連結串列是頭結點指向NULL,這裡是top結點指向NULL,同時將計數器置0

void InitStack(LinkStack *ST){//初始化函式
    ST->top=NULL;//top結點指向空
    ST->count=0;//置0
}

壓棧(入棧)

現在是隻有棧頂指標的空棧,我們要加入一下元素,就要壓棧
思路是創造一個新的結點,將要加入的資料存入裡面,在將新結點壓入就行了,具體程式碼如下

void Insert(LinkStack *ST,SElemType e){//將棧頂指標地址和將要入棧的元素傳入
    pNode s=(pNode)malloc(sizeof(StackNode));//給新結點分配空間
    s->data=e;
    s->next=ST->top;
    ST->top=s;
    ST->count++;//每壓入一個元素,棧的計數器加1
}

出棧

我們不僅要給函式傳入一個棧頂指標地址,還要傳入一個整型指標的地址來儲存彈出的元素,記得事後將彈出的結點free掉

int Pop(LinkStack *ST,SElemType *e){
    pNode p;//創造一個結點p,用於儲存要彈出結點的地址
    if(ST->count==0)//如果是空棧就不能彈出了
        return 0;
    p=ST->top;//存入要彈出的地址
    *e=ST->top->data;//儲存要彈出的元素
    ST->top=ST->top->next;//棧頂指標向後指
    ST->count--;//計數器減1
    free(p);//釋放掉彈出結點的空間
    return 1;
}

列印棧

需要一個定位指標,通過其遍歷整個鏈棧,列印遍歷到的每個結點的data域上的值

int Print(LinkStack *ST){//列印函式
    pNode H=ST->top;//定位指標
    if(H==NULL)//如果定位指標都是指向空的,說明沒什麼好列印的了
        return 0;
    printf("此時棧為:  ");
    printf("%d  ",H->data);
    while(H->next!=NULL){
        H=H->next;
        printf("%d  ",H->data);
    }
    printf("\n");
    return 1;
}

源程式

將上述的函式合併起來進行除錯

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

typedef int SElemType;

typedef struct StackNode{//這裡設定鏈棧的結點結構
    //每個結點包含一個數據域和一個指標域
    SElemType data;
    struct StackNode *next;
}StackNode,*pNode;//*pNode是結點的結構體指標

typedef struct LinkStack{//這裡設定棧頂指標
    pNode top;
    int count;
}LinkStack;

//函式宣告
void InitStack(LinkStack *ST);
void Insert(LinkStack *ST,SElemType e);
int Pop(LinkStack *ST,SElemType *e);
int Print(LinkStack *ST);


int main(){//主函式除錯
    LinkStack ST;
    int i,e;
    InitStack(&ST);
    for(i=0;i<10;i++){
        Insert(&ST,i);
    }
        Print(&ST);
    for(i=0;i<5;i++){
        Pop(&ST,&e);
        printf("彈出了一個數字%d,",e);
        Print(&ST);
        printf("\n");
    }
    Print(&ST);
}

void InitStack(LinkStack *ST){//初始化函式
    ST->top=NULL;//top結點指向空
    ST->count=0;//置0
}

void Insert(LinkStack *ST,SElemType e){//將棧頂指標地址和將要入棧的元素傳入
    pNode s=(pNode)malloc(sizeof(StackNode));//給新結點分配空間
    s->data=e;
    s->next=ST->top;
    ST->top=s;
    ST->count++;//每壓入一個元素,棧的計數器加1
}

int Pop(LinkStack *ST,SElemType *e){
    pNode p;//創造一個結點p,用於儲存要彈出結點的地址
    if(ST->count==0)//如果是空棧就不能彈出了
        return 0;
    p=ST->top;//存入要彈出的地址
    *e=ST->top->data;//儲存要彈出的元素
    ST->top=ST->top->next;//棧頂指標向後指
    ST->count--;//計數器減1
    free(p);//釋放掉彈出結點的空間
    return 1;
}

int Print(LinkStack *ST){//列印函式
    pNode H=ST->top;//定位指標
    if(H==NULL)//如果定位指標都是指向空的,說明沒什麼好列印的了
        return 0;
    printf("此時棧為:  ");
    printf("%d  ",H->data);
    while(H->next!=NULL){
        H=H->next;
        printf("%d  ",H->data);
    }
    printf("\n");
    return 1;
}

除錯結果
在這裡插入圖片描述
成功啦!!

總結

  • 鏈棧跟連結串列很像
  • 建立使一定要記清楚自己寫的結構體裡邊到底包含了什麼!!!
  • 自己給它起的什麼名字!!!
  • 永遠要清楚自己的指標指向了什麼地方!!!