栈作为一种特殊的线性表,在计算机中也主要有两种基本的存储结构:顺序存储结构和链式存储结构。我们称顺序存储的栈为顺序栈,链式存储的栈为链栈。
1.顺序栈
顺序栈是用顺序存储结构实现的栈,即利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时由于栈的操作的特殊性,还必须附设一个位置指针top(栈顶指针)来动态地指示栈顶元素在顺序栈中的位置。通常以top=-1表示空栈。顺序栈的存储结构可以用C语言中的一维数组来表示。栈的顺序存储结构定义如下:
#define TRUE 1 #define FALSE 0 #define Stack_Size 50 typedef struct { StackElementType elem[Stack_Size];/*用来存放栈中元素的一维数组*/ int top;/*用来存放栈顶元素*/ }SeqStack; |
图3.2给出了顺序栈的进栈和出栈过程。
顺序栈基本操作的实现如下:
(1)初始化。
void InitStack(SeqStack *S) {/*构造一个空栈S*/ S->top=-1; } |
(2)判栈空。
int isEmpty(SeqStack *S)/*判栈S为空栈时返回值为真,反之为假*/ { return(S->top==-1?TRUE:FALSE); } |
(3)判栈满。
int IsFull(SeqStack *S) { return(S->top==Stack_Size-1?TRUE:FALSE); } |
(4)进栈。
int Push(SeqStack *S ,StackElementType x) { if(S->top==Stack_Size-1) return(FALSE);/*栈已满*/ S->top++; S->elem[S->top]=x; retun(TRUE); } |
(5)出栈。
int Pop(SeqStack *S,StackElementType *x) {/*将栈S的栈顶元素弹出,放到x所指的存储空间中*/ if(S->top==-1)/*栈为空*/ return(FALSE); else { *x=S->elem[S->top]; S->top--;/*修改栈顶指针*/ return(TRUE); } } |
(6)取栈顶元素。
int GetTop(SeqStack *S,StackElementType *x) {/*将栈S的栈顶元素弹出,放到x所指的存储空间中,但栈顶指针保持不变*/ if(S->top==-1)/*栈为空*/ return(FALSE); else { *x=S->elem[S->top]; return(TRUE); } } |
栈的应用非常广泛,经常会出现在一个程序中需要同时使用多个栈的情况。若使用顺序栈,会因为对栈空间大小难以准确估计,从而产生有的栈溢出、有的栈空间还很空闲的情况。为了解决这个问题,可以让多个栈共享一个足够大的数组空间,通过利用栈的动态特性来使其存储空间互相补充,这就是多栈的共享技术。
在栈的共享技术中最常用的两个栈的共享技术:它主要利用了栈“栈底位置不变,而栈顶位置动态变化”的特性。首先为两个栈申请一个共享的一维数组空间S[M],将两个栈的栈底分别放在一维数组的两端,分别是0,M-1.由于两个栈顶动态变化,这样可以形成互补,使得每个栈可用的最大空间与实际使用的需求有关。由此可见,两栈共享比两个栈分别申请M/2的空间利用率高。两栈共享的数据结构定义如下:
#define M 100 typedef struct { StackElementType Stack[M]; StackElementType top[2];/*top[0]和top[1]分别为两个栈顶指示器*/ }DqStack; |
两个栈共享空间的示意如图3.3所示。下面给出两个栈共用时的初始化、进栈和出栈操作的算法。
(1)初始化操作。
void InitStack(DqStack *S) { S->top[0]=-1; S->top[1]=M; } |
(2)进栈操作算法。
int Push(DqStack *S,StackElementType x,int i) { if(S->top[0]+1==S->top[1])/*栈已满*/ return(FALSE); switch(i) { case 0: S->top[0]++; S->Stack[S->top[0]]=x; break; case 1: S->top[1]--; S->Stack[S-top[1]]=x; break; default:/*参数错误*/ return(FALSE); } return(TRUE); } |
(3)出栈操作算法。
int Pop(DqStack *S,StackElementType *x,int i) {/*从i号堆栈中弹出栈顶元素并送到x中*/ switch(i) { case 0: if(S->top[0]==-1) return(FALSE); *x=S->Stack[S->top[0]]; S->top[0]--; break; case 1: if(S->top[1]==M) return(FALSE); *x=S->Stack[S->top[1]]; S->top[1]++; break; default: return(FALSE); } return(TRUE); } |