棧的鏈式儲存結構實現()
阿新 • • 發佈:2018-11-19
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;
}
除錯結果
成功啦!!
總結
- 鏈棧跟連結串列很像
- 建立使一定要記清楚自己寫的結構體裡邊到底包含了什麼!!!
- 自己給它起的什麼名字!!!
- 永遠要清楚自己的指標指向了什麼地方!!!