棧的原理以及實現(基於陣列)
阿新 • • 發佈:2018-12-23
棧的定義:
限制僅在表的一端進行插入和刪除運算的線性表。
可以實現“先進後出(或者叫後進先出)”的儲存結構。
棧頂(Top): 允許操作的一端。
棧底(Bottom): 不允許操作的一端。
特點:後進先出。
舉例:物流裝車,先裝車的後出來,後裝車的先出來。
棧的結構:
空棧:棧頂和棧頂都指向一個無用的頭結點
存有結點的棧:棧頂指標指向棧頂結點,棧底指標指向頭結點
棧的三種實現方案:靜態陣列、動態分配的陣列、動態分配的鏈式結構。
靜態陣列:長度固定,在編譯時確定。優點:結構簡單,實現方便。缺點:不夠靈活、適用於知道明確長度的場合。
動態陣列:長度可在執行的時才確定,並且可以更改原來陣列的長度。優點:靈活。缺點:會因此增加程式的複雜性。
鏈式結構:無長度上限。需要的時候再申請分配記憶體空間。優點:最靈活。缺點:鏈式結構的連結欄位需要消耗一定記憶體;在鏈式結構中訪問特定元素效率不如陣列。
棧的三種實現:
首先確定一個棧介面的標頭檔案,裡面包含了各個實現方案下的函式原型,放在一起是為了實現程式的模組化以及便於修改。然後再分別介紹各個方案的具體實現方法。
靜態陣列實現棧:
/* ** ** 靜態陣列實現堆疊程式,陣列長度由#define確定 */ #include <stack.h> #include <stdio.h> #include <assert.h> #define STACK_SIZE 100 /*棧最大容納元素數量*/ typedef struct Stack{ SElemType data[STACK_SIZE]; /*棧中的陣列*/ int top; /*指向棧頂元素的指標*/ }SeqStack; /*init stack*/ void InitStack(SeqStack *S) { S->top = 0; } /*判斷棧是否為空*/ int StackEmpty(SeqStack *S) { if(S->top == 0) return 1; else return 0; } /*取棧頂元素*/ int GetTop(SeqStack S, SElemType *e) { if(S->top <= 0){ printf("當前棧已空\n"); return 0; } *e = S.stack[S.top - 1]; return 1; } /*將元素e入棧*/ int push(SeqStack *S, SElemType e) { if(S->top >= StackSize){ printf("棧滿\n"); return 0; } S->stack[S->top] = e; S->top ++; return 1; } /*將棧頂元素出棧,並賦值給e*/ int PopStack(SeqStack *S, SElemType *e) { if(S->top == 0){ printf("空棧"); return 0; } S->top --; *e = S->stack[S->top]; return 1; } /*棧的長度*/ int StackLength(SeqStack S){ return S.top;//儲存著資料的部分是0到top-1,入棧時,如果棧未滿,則在top處存入資料,然後top++ } /*清空棧*/ void ClearStack(SeqStack *S){ S->top = 0; } /*判斷棧是否為空*/ int isEmpty(SeqStack *S) { return S->top == 0; } /*判斷棧是否滿*/ int isFull(SeqStack *S) { return S->top == StackSize; }
動態分配的陣列實現棧:並用棧解決禁止轉換問題:(十進位制轉二進位制或八進位制)
#include<stdio.h> #include<stdlib.h> #define STACK_INIT_SIZE 10 //定義最初申請的記憶體大小 #define STACK_INCREMENT 2 //每一次申請記憶體不足的時候擴充套件的記憶體大小 #define OVERFLOW 0 #define FALSE 0 #define TRUE 1 #define ERROR 0 #define INFEAIBLE 0 //不可實行的 #define OK 1 typedef int SElemType; typedef int Status; int Length; /*****************結構型別部分******************/ typedef struct Stack { SElemType *base; SElemType *top; int stacksize; }SqStack; //sequence stack順序棧 /*****************構造一個空棧**********************/ Status InitStack(SqStack &S) { if( !( S.base = (SElemType *)malloc( STACK_INIT_SIZE * sizeof(SElemType) ) ) ) exit(OVERFLOW); //儲存分配失敗 S.top = S.base; S.stacksize = STACK_INIT_SIZE; //初始棧容量 return OK; } /******************壓入棧元素*********************/ Status Push(SqStack &S, SElemType e)//這裡不是SElemType &e { //棧滿追加記憶體 if(S.top - S.base >= S.stacksize){ S.base = (SElemType *) realloc(S.base, sizeof(SElemType) * (S.stacksize + STACK_INCREMENT)); if(!S.base) exit(OVERFLOW); //給SqStack的三個物件賦值 S.top = S.base + S.stacksize; S.stacksize += STACK_INCREMENT; } *S.top++ = e;//先把e壓入棧頂,S.top再增加1指向棧頂元素e的下一個位置 return OK; } /******************輸出棧元素*********************/ void PrintList(SqStack S) { S.top = S.base; for( int i = 0; i< Length; i++){ printf("%d\n",*(S.top) ++); } } /******************判斷棧是否為空*****************/ Status StackEmpty(SqStack S) { if(S.base == S.top) return true; else return false; } /******************刪除棧頂元素*******************/ Status Pop(SqStack &S, SElemType &e) { //判斷是否為空 if( S.base == S.top ) return ERROR; e = *--S.top; return OK; } /********************進位制轉換********************/ int conversion(unsigned int n,unsigned int m)//十進位制數轉化成m進位制 { SqStack s; InitStack(s); int e = 0; unsigned result = 0; while(n) { Push(s, (SElemType)n%m); n /= m; } while( !StackEmpty(s)) { Pop(s,e); result = result*10 + e; } return result; } int main() { int n = 123; int m = 2; int result = conversion(n,m); printf("%d\n", result); return 0; }