資料結構——棧,資料結構
說明:嚴蔚敏的《資料結構》(C語言版)學習筆記,記錄一下,以備後面查看。
如所示,剛開始base指標和top指標都指向棧低,當壓棧的時候,top指標向上移動,直到棧滿後,棧頂指標top指向棧外地址,此時我們需要再分配新空間。
#include <stdio.h>#include <malloc.h>#include <stdlib.h>#define STACK_INIT_SIZE 100 //儲存空間初始分配量#define STACKINCREMENT 10 //儲存空間分配增量const int OK = 1; //定義正確返回const int ERROR = -1; //定義錯誤的返回const int OVERFLOW = -2; //定義溢出//定義元素類型typedef int SElemType;//定義傳回型別typedef int Status;typedef struct{ SElemType *base; //棧底指標,在構造之前和銷毀後base的值為NULL SElemType *top; //棧頂指標 int stacksize; //已指派的空間}SqStack;//初始化棧Status InitStack(SqStack &S){ S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType)); if(!S.base) exit(OVERFLOW); S.top = S.base; S.stacksize = STACK_INIT_SIZE; return OK;}//擷取棧頂元素Status GetTop(SqStack S, SElemType &e){ if(S.top == S.base) return ERROR; e = *(S.top - 1); return OK;}//壓棧Status Push(SqStack &S, SElemType e){ if(S.top - S.base >= S.stacksize){ S.base = (SElemType *)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType)); if(!S.base) exit(OVERFLOW); S.top = S.base + S.stacksize; S.stacksize += STACKINCREMENT; } *S.top = e; S.top++; return OK;}//出棧Status Pop(SqStack &S, SElemType &e){ if(S.top == S.base) return ERROR; e = *(--S.top); return OK;}//判斷棧是否為空白bool StackEmpty(const SqStack &S){ if(S.top == S.base) return true; else return false;}//十進位數轉8進位數void conversion(SqStack &S){ InitStack(S); printf("請輸入10進位數,返回一個8進位數:\n"); int n; scanf("%d", &n); while(n){ Push(S, n % 8); n = n / 8; } SElemType e; printf("8進位數是:0x"); while(!StackEmpty(S)){ Pop(S, e); printf("%d", e); } printf("\n");}int main(){ SqStack sq; //InitStack(sq); //Push(sq, 1); //Push(sq, 2); //Push(sq, 3); //SElemType e3; //Pop(sq, e3); //GetTop(sq, e3); //printf("%d", e3); conversion(sq); scanf("%d"); return 0;}
上面的conversion函數是一個將10進位轉換為8進位的例子,這個就是棧的一個應用,還有例如,括弧匹配的驗證、迷宮求解等。
例如Hanoi塔問題:
假設有3個分別為a,b,c的三個塔座,a上有直徑從大到小的圓盤,可以藉助b塔座將a上的圓盤移動到c上,移動過程中大小順序不變。
void movePic(char a, int n, char b){ printf("將編號為%d的圓盤從%c上移動到%c上\n", n , a, b);}void hanuota(int n, char x, char y, char z){ if(n == 1){ movePic(x, 1, z); //將編號為1的圓盤從x移到z }else{ hanuota(n - 1, x, z, y); //將x上編號為1到n-1的圓盤移到y,z作輔助塔 movePic(x, n, z); //將編號為n的圓盤從x移到z hanuota(n - 1, y, x, z); //將y上編號為1到n-1的圓盤移到z,x作輔助塔 }}int main(){ hanuota(3, 'a', 'b', 'c');}
我們可以將問題簡單抽象成遞迴。
1、要將n個圓盤移動到c,則需要先將n-1個圓盤移動到b
2、再將a上的最底下的圓盤移動到c
3、最後將b上面的n-1個圓盤移動到c
經過這三個步驟就可以完成移動,在這三個步驟中,步驟1,從a將n-1個圓盤移動到b和問題本身是同一個問題,步驟3將n-1個圓盤從b移動到c也和問題本身是同一個問題,所以這兩處我們就可以迭代調用。