一.棧的定義
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;
}
四.總結
棧是一種非常重要的線性結構,也是非常基本的數據結構。本文用鏈表的方式實現了棧。
棧在計算機領域有很多應用。
比如:函數的調用用到棧、判斷迴文也用到棧的知識。
所以,我們一定要掌握它!