資料結構,資料結構與演算法
棧
1 棧的概念
棧(Stack):是限制在表的一端進行插入和刪除操作的線性表。又稱為後進先出LIFO (Last In First Out)或先進後出FILO (First In Last Out)線性表。
棧頂(Top):允許進行插入、刪除操作的一端,又稱為表尾。用棧頂指標(top)來指示棧頂元素。
棧底(Bottom):是固定端,又稱為表頭。
空棧:當表中沒有元素時稱為空白棧。
設棧S=(a1,a2,…an),則a1稱為棧底元素,an為棧頂元素,3-1所示。棧中元素按a1,a2,…an的次序進棧,退棧的第一個元素應為棧頂元素。即棧的修改是按後進先出的原則進行的。
棧的抽象資料類型定義
ADT Stack{
資料對象:D ={ ai|ai∈ElemSet, i=1,2,…,n,n≥0 }
資料關係:R ={(ai-1, ai)| ai -1, ai ∈D, i=2,3,…,n }
基本操作:初始化、進棧、出棧、取棧頂元素、求棧的長度、判斷棧是否為空白等
} ADT Stack
棧的靜態順序儲存表示
採用靜態一維數組來儲存棧。
◆ 棧底固定不變的;棧頂則隨著進棧和退棧操作而變化,用一個整型變數top(稱為棧頂指標)來指示當前棧頂位置。
◆ 用top=0表示棧空的初始狀態,每次top指向棧頂在數組中的儲存位置。
◆ 結點進棧:首先執行top加1,使top指向新的棧頂位置,然後將資料元素儲存到棧頂(top所指的當前位置)。
◆ 結點出棧:首先把top指向的棧頂元素取出,然後執行top減1,使top指向新的棧頂位置。
棧的基本操作的實現
棧的類型定義define MAX_STACK_SIZE 100 /* 棧向量大小 */typedef int ElemType ;typedef struct sqstack{ ElemType stack_array[MAX_STACK_SIZE] ;int bottom; //棧底,實為數組下標int top; //棧頂,實為數組下標}SqStack ;
棧的初始化SqStack Init_Stack(void){ SqStack S ;S.bottom=S.top=0 ; return(S) ;}
壓棧(元素進棧)Status push(SqStack &S , ElemType e) /* 使資料元素e進棧成為新的棧頂 */{ if (S.top==MAX_STACK_SIZE-1) return ERROR; /* 棧滿,返回錯誤標誌 */S.top++ ; /* 棧頂指標加1,下標為0的位置不放元素 */S.stack_array[S.top]=e ; /* e成為新的棧頂 */return OK; /* 壓棧成功 */}思考:若調換S.top++ 和S.stack_array[S.top]=e 的位置,結果如何?
彈棧(元素出棧)ElemType pop( SqStack &S) /*彈出棧頂元素*/{ if ( S.top==0 )return ERROR ; /* 棧空,返回錯誤標誌 */e=S.stack_array[S.top] ; S.top-- ; return e ; }
當棧滿時做進棧運算必定產生空間溢出,簡稱“上溢”。上溢是一種出錯狀態,應設法避免。
當棧空時做退棧運算也將產生溢出,簡稱“下溢”。下溢則可能是正常現象,因為棧在使用時,其初態或終態都是空棧,所以下溢常用來作為控制轉移的條件。
棧的動態順序儲存表示
採用動態一維數組來儲存棧。所謂動態,指的是棧的大小可以根據需要增加。
◆ 用bottom表示棧底指標,棧底固定不變;棧頂則隨著進棧和退棧操作而變化。用top(稱為棧頂指標)指示當前棧頂位置。
◆ 用top=bottom作為棧空的標記,每次top指向棧頂數組中的下一個儲存位置(或指向棧頂元素)。
◆ 結點進棧:判斷棧是否已滿,如果棧滿,則重新申請更大的記憶體空間,然後將資料元素儲存到棧頂(top所指的當前位置),然後執行top加1,使top指向棧頂的下一個儲存位置;
◆ 結點出棧:首先執行top減1,使top指向棧頂元素的儲存位置,然後將棧頂元素取出。
基本操作的實現
1 棧的類型定義#define STACK_SIZE 100 /* 棧初始向量大小 */#define STACKINCREMENT 10 /* 儲存空間分配增量 */typedef int ElemType ;typedef struct sqstack{ ElemType *bottom; /* 棧不存在時值為NULL */ElemType *top; /* 棧頂指標 */int stacksize ; /* 當前已指派空間,以元素為單位 */}SqStack ;
2 棧的初始化Status Init_Stack(SqStack *S ){S ->bottom=(ElemType *)malloc(STACK_SIZE *sizeof(ElemType));if (! S -> bottom) //若返回null 指標,記憶體配置失敗 return ERROR;S -> top=S -> bottom ; /* 棧空時棧頂和棧底指標相同 */S -> stacksize=STACK_SIZE; return OK ;}
3 壓棧(元素進棧)Status push(SqStack *S , ElemType e) { if (S -> top-S -> bottom>=S -> stacksize-1) { S -> bottom=(ElemType *) realloc (S -> bottom, (STACKINCREMENT+STACK_SIZE) *sizeof(ElemType)); /* 棧滿,追加儲存空間 */if (! S -> bottom) return ERROR; S -> top=S -> bottom+S -> stacksize ; //為什嗎?S -> stacksize+=STACKINCREMENT ;} *S-> top=e; S -> top++ ; /* 棧頂指標加1,e成為新的棧頂 */return OK;}
4 彈棧(元素出棧)ElemType pop( SqStack *S) /*彈出棧頂元素*/{ if ( S->top== S-> bottom ) return ERROR ; /* 棧空,返回失敗標誌 */S-> top-- ; e=*S -> top ; return e ; }
地址傳遞與值傳遞的區別
ElemType pop( SqStack *S) /*彈出棧頂元素*/{ if ( S ->top== 0 ) return ERROR ; /* 棧空,返回失敗標誌 */S -> top-- ; e =S-> bottom[S ->top]; return e ; } ElemType Get_top( SqStack *S) /*彈出棧頂元素*/{ if ( S ->top== 0 ) return ERROR ; /* 棧空,返回失敗標誌 */S -> top-- ; e =S-> bottom[S ->top]; return e ; }