這兩天完成了棧的順序存儲結構的相關算法,包括初始化、壓棧、出棧、取棧頂元素、判斷棧是否為空、返回棧長度、棧的遍歷、清棧、銷毀棧。這次的實現過程有兩點收獲,總結如下:
一、清楚遍歷棧的概念
棧的遍歷指的是從棧底想棧頂方向運行visit()函數,這是之前的學習中所忽略的;棧的遍歷解除了棧的輸出順序只能從棧頂像棧底方向的限制。
二、清空棧時要不要將stacksize重置
網上看到有的人在實現清空棧這一功能時,將stacksize重置為0,我覺得有點問題,起初的想法是將其重置為初始化時的值,在與同學討論了后,最后決定不應重置stacksize的值,原因是:
重置的目的是針對使用了realloc()重新分配了地址的棧,但是realloc()函數分配的是一段連續的地址,指向棧底的指針指向了這段空間,即使將stacksize重置回初始值,增加的那段空間還是由指向棧底的指針來控制的(參照這句S.base=(Elemtype *)realloc(S.base,(S.stacksize+STACKINCREACE)*sizeof(Elemtype));思考),因此重置沒有意義。類比順序表的清空:順序表的清空也是只將當前長度置為0,沒有改變它的listsize值。
這次使用的編譯環境是VC++6.0。
//頭文件內容 //--------------------棧的順序存儲結構-------------------- #define STACK_INIT_SIZE 100 #define STACKINCREACE 10 typedef char Elemtype;//在頭文件中說明 typedef int Status; typedef struct{ Elemtype *base; Elemtype *top; int stacksize; }SqStack; //----------------------函數聲明部分---------------------- Status InitStack(SqStack &S); Status Push(SqStack &S,Elemtype e); Status Pop(SqStack &S,Elemtype &e); Status GetTop(SqStack S,Elemtype &e); Status StackEmpty(SqStack S); int StackLength(SqStack S); Status StackTraverse(SqStack S); Status ClearStack(SqStack &S); Status DestroyStack(SqStack &S); //源文件內容 #include <stdio.h> #include <stdlib.h> #include "SqStackHeader.h" //--------------------主函數入口-------------------- void main(){ SqStack stack; char temp='a'; char getElem=NULL; char popElem=NULL; InitStack(stack); Push(stack,temp); Push(stack,'b'); GetTop(stack,getElem); printf("棧頂元素是:%c\n",getElem); char *empty=NULL; empty=StackEmpty(stack)?"是空棧!":"不是空棧!"; // printf("是否為空棧判斷結果:%s\n",empty); // ClearStack(stack); DestroyStack(stack); StackTraverse(stack); // printf("棧的長度:%d\n",StackLength(stack)); // Pop(stack,popElem); } //------------------棧的初始化函數------------------ Status InitStack(SqStack &S){ S.base = (Elemtype *)malloc(STACK_INIT_SIZE*sizeof(Elemtype)); //2016.4.17編譯時報錯:missing “)”before ; //錯誤原因:由於頭文件中定義常量時后面加了;導致編譯的時候將STACK_INIT_SIZE用100;代替, //使得該函數提前結束語100處,malloc后的“(”找不到匹配的“)”而報錯 //解決方法:去掉常量定義中的; if(!S.base){ return false; } S.stacksize=STACK_INIT_SIZE; S.top=S.base; return true; } //---------------------入棧函數--------------------- Status Push(SqStack &S,Elemtype e){ //判斷是否溢出 if(S.top-S.base>=S.stacksize){ S.base=(Elemtype *)realloc(S.base,(S.stacksize+STACKINCREACE)*sizeof(Elemtype)); if(!S.base){ return false; } S.top=S.base+S.stacksize;//注意因為這里的棧底指針的改變,導致棧頂指針隨之改變 S.stacksize+=STACKINCREACE; } //壓棧部分 *S.top=e; S.top++; return true; } //---------------------出棧函數--------------------- Status Pop(SqStack &S,Elemtype &e){ //非法判斷 if(S.base==S.top){ return false; } S.top--; //注意這里因為top指向棧中當前元素的上一個空間,所以要先將其位置減一 e=*S.top; return true; } //-------------------查看棧頂元素------------------- Status GetTop(SqStack S,Elemtype &e){ if(S.base==S.top ){ return false; } e=*(S.top-1); return true; } //------------------判斷棧是否為空------------------ Status StackEmpty(SqStack S){ if(S.base==S.top){ return true; } return false; } //------------------返回棧元素個數------------------ int StackLength(SqStack S){ if(S.base==S.top){ return 0; } return S.top-S.base; } //--------------------遍歷棧------------------------ Status StackTraverse(SqStack S){//從棧底到棧頂的方向 if(S.top==S.base){ return false; } while(S.base <S.top ){ printf("%c\t",*(S.base++)); } printf("\n"); return true; } //--------------------清空棧------------------------ Status ClearStack(SqStack &S){//清空棧的時候不用將stacksize重新賦值 S.top=S.base; //因為經過realloc函數重新分配空間后(stacksize大小改變), return true; //S.base指向的是一段stacksize大小的連續存儲空間 //即使將他重置,剩余的空間也是閑置的(順序表里也只是經當前長度置為0) } //--------------------銷毀棧------------------------ Status DestroyStack(SqStack &S){ free(S.base); free(S.top); S.base=NULL; return true; }