堆疊是限定只在表尾進行洗掉和插入操作的線性表,
怎么理解“堆疊”這種資料結構呢?這里舉個較為貼切的栗子,手槍就是一個典型的“堆疊”,
電視節目中的各路英雄在用手槍的時候,通常是先填裝子彈,再將彈夾最上層的子彈射出,先進入彈夾的子彈最后射出,后進入彈夾的子彈最先射出,這其實就是堆疊的思想,

先進后出,后進先出,這就是一種典型的“堆疊”思想,
這是堆疊最大的特點,也是堆疊最大的缺點,因為堆疊這樣的一種特性導致了其只能在同一端插入元素和洗掉元素,
但我們在前面學了鏈表,堆疊能實作的操作鏈表也都可以實作,我們可以說堆疊是線性表的一種特例,其中線性表的順序存盤也對應著順序堆疊(后面會有鏈式堆疊,我還會更的),與此同時,由于堆疊涉及的操作比較少,實作起來也較為容易,
看到這里,你可能會發出疑問:有鏈表了我為什么還要用堆疊呢?鏈表能做的事情可比堆疊多得多了,
一開始我也疑惑,但堆疊存在就一定有他的道理,對比與鏈表來說,我認為有兩點主要原因:
- 鏈表涉及的操作紛雜繁瑣,在使用上稍不留神就會出錯,
- 堆疊在功能上肯定是不如鏈表全面,但是我們所學的每一種資料結構都不是直接單拎出來講的,每一種資料結構肯定對應著一種使用場景,在特定的場景之下,堆疊的實作要比鏈表簡單,這是堆疊相比鏈表在時間上的優勢,
好吧,說了這么多,堆疊相比鏈表來說的優勢其實主要就兩點:簡單容易實作且不容易出錯,
那么如何實作“堆疊”呢?
在實作堆疊之前,先向大家引入幾個概念:
我們把允許插入和洗掉的一段稱為堆疊頂(表尾),
將另一端稱為堆疊底,
將不含任何資料元素的堆疊稱為空堆疊,
線性表的順序存盤是依靠陣列完成的,這里的順序堆疊也與順序表有著異曲同工之妙,
結合“先進后出,后進先出”的思想,我們將陣列的首元素作為堆疊底元素,將陣列的末元素作為堆疊頂元素,操作時只需要針對堆疊頂元素即可,
將堆疊想象為一個容器:

既然堆疊的操作圍繞堆疊頂元素開展,現在的問題就在于如何表示堆疊頂元素在陣列中的位置?
我們用一個Top變數來表示堆疊頂元素在陣列中的位置,有元素插入到堆疊頂元素之上,Top就加一,堆疊頂元素洗掉后,Top就減一,
結合Top變數來表示堆疊的幾種狀態:
(1)堆疊中有兩個元素,Top = 1.
(2)堆疊中沒有元素,Top = -1.
(3)堆疊中有4個元素(滿),Top = 3.

(圖畫的太丑了,別噴我···)
這里的Top變數實際上代表著堆疊頂元素的位置,可以理解為一個指標,指向堆疊頂元素,
但是Top必須小于陣列的最大值,而且最小為 0(只有一個元素a[0]),
如果堆疊中一個元素也沒有,我們通常將Top元素置為 -1,
Top堆疊頂指標其實和陣列下標是一一對應的關系,
看了這么長時間的理論知識,下面我們就可以開始實作堆疊了:
堆疊的幾種基本操作
- 堆疊的結構定義
- 堆疊的初始化
- 清除堆疊
- 檢查堆疊是否為空
- 回傳堆疊的長度
- 回傳堆疊頂元素值
- 在堆疊頂插入元素
- 洗掉堆疊頂元素
堆疊的結構定義
一個陣列存資料,一個top變數來表示堆疊頂元素在堆疊中的位置,
代碼實作:
struct SqStack{
SElemType data[MAX];
//SElemType 是資料型別,int、float、char都可,根據實際情況決定
int top;
};
堆疊的初始化
將top變數置為 -1,表示堆疊中沒有堆疊頂元素,也就是沒有元素,
void InitStack(SqStack *S){
S->top = -1;
}
清除堆疊
同上,
void ClearStack(SqStack *S){
S->top = -1;
}
檢查堆疊是否為空
如果top變數為 -1,表明堆疊為空,反之,不為空,
bool EmptyStack(SqStack S){
if(S.top == -1)
return true;
else
return false;
}
回傳堆疊的長度
堆疊頂元素top代表陣列的最后一個元素,
但top是從 0 開始計數的,所以需要回傳 top + 1,
int LengthStack(SqStack S){
return S.top + 1;
}
回傳堆疊頂元素值
- 判斷堆疊是否為空
- 回傳與堆疊頂指標對應數組的值
Status GetTop(SqStack S,SElemType *e){
if(S.top == -1)
return ERROR;
else
*e = S.data[S.top];
return OK;
}
在堆疊頂插入元素
- 判斷堆疊是否已滿
- 如果堆疊未滿,堆疊頂指標加一
- 對與堆疊頂指標對應的陣列元素賦值
Status Push(SqStack *S,SElemType e){
if(S->top == MAX - 1)
return ERROR;
S->top++;
S->data[S->top] = e;
return OK;
}
洗掉堆疊頂元素
- 判斷堆疊是否為空
- 保留堆疊頂指標對應元素的值
- 堆疊頂指標加一
Status Pop(SqStack *S,SElemType *e){
if(S->top == -1)
return ERROR;
*e = S->data[S->top];
S->top--;
return OK;
}
加入測驗后的全部代碼:
#include<stdio.h>
#define OK 1
#define ERROR 0
#define MAX 20
typedef int Status;
//Status表示函式回傳值的型別,OK代表函式成功運行,ERROR代表運行出錯
typedef int SElemType;
//SElemType型別根據實際情況而定,這里假設為 int
struct SqStack{
SElemType data[MAX];
int top;
};
void InitStack(SqStack *S){
S->top = -1;
}
void ClearStack(SqStack *S){
S->top = -1;
}
bool EmptyStack(SqStack S){
if(S.top == -1)
return true;
else
return false;
}
int LengthStack(SqStack S){
return S.top + 1;
}
Status GetTop(SqStack S,SElemType *e){
if(S.top == -1)
return ERROR;
else
*e = S.data[S.top];
return OK;
}
Status Push(SqStack *S,SElemType e){
if(S->top == MAX - 1)
return ERROR;
S->top++;
S->data[S->top] = e;
return OK;
}
Status Pop(SqStack *S,SElemType *e){
if(S->top == -1)
return ERROR;
*e = S->data[S->top];
S->top--;
return OK;
}
void StackTraverse(SqStack S){
int i = 0;
while(i <= S.top){
printf("%d ",S.data[i]);
i++;
}
printf("\n");
}
int main(){
int e;
SqStack S;
InitStack(&S);
for(int i = 1; i <= 10 ;i++){
Push(&S,i);
}
printf("堆疊頂元素依次為: ");
StackTraverse(S);
Pop(&S,&e);
printf("彈出的堆疊頂元素為: %d\n",e);
if(EmptyStack(S))
printf("堆疊為空\n");
else
printf("堆疊不為空\n");
GetTop(S,&e);
printf("堆疊頂元素為 %d,堆疊的長度為 %d\n",e,LengthStack(S));
ClearStack(&S);
if(EmptyStack(S))
printf("堆疊為空\n");
else
printf("堆疊不為空\n");
return 0;
}
運行結果:

后續我還會將繼續更新,喜歡的話給點個贊吧!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/278901.html
標籤:其他
上一篇:【資料結構】線性表
