其實棧的順序存儲很方便,因爲它只在表尾進行操作,不存在普通線性表插入與刪除還需要移動元素的情況。同樣它也有普通線性表的缺陷,即必須確定數量。然而對於兩個相同類型的棧,卻可以做到最大限度地利用其開闢的存儲空間來進行操作。
數組有兩個端點,兩個棧使用這一個數組的存儲區域,兩個棧有兩個棧底,分別爲數組的始端和末端。
這樣在壓棧的時候,是棧頂指針往中間靠攏,當兩指針相遇時,則棧滿。棧空即top1=-1,top2=n。而棧滿則是top1 + 1 == top2;
代碼實現:
SqDoubleStack.h
/*兩棧共享空間--順序棧結構 */
#define MAXSIZE 5
typedef int SElemType;
typedef struct
{
SElemType data[MAXSIZE];
int top1; //棧1 棧頂指針
int top2; //棧2 棧頂指針
}SqDoubleStack;
#define OK 1
#define ERROR 0
typedef int Status;
Status InitStack(SqDoubleStack *S); //初始化操作,建立一個空棧S
Status DestroyStack(SqDoubleStack *S); //棧棧存在,則銷燬它
Status ClearStack(SqDoubleStack *S); //將棧清空
int StackEmpty(SqDoubleStack S,int stackNumber); //若棧爲空,返回true,否則返回false
Status GetTop(SqDoubleStack S,SElemType *e,int stackNumber); //若棧存在且非空,用e返回S的棧頂元素
Status Push(SqDoubleStack *S,SElemType e,int stackNumber); //若棧S存在,將新元素e插入棧S中併成爲棧頂元素
Status Pop(SqDoubleStack *S,SElemType *e,int stackNumber); //刪除棧S中棧頂元素,並用e返回其值
int StackLength(SqDoubleStack S,int stackNumber); //返回棧S的長度
SqDoubleStack.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "SqDoubleStack.h"
int main(void)
{
SqDoubleStack S;
InitStack(&S);
printf("已初始化好,現在壓棧1,2,3,4");
Push(&S,1,1);
Push(&S,2,1);
Push(&S,3,2);
Push(&S,4,2);
Push(&S,5,2);
printf("\n現在棧1的長度是:%d,棧2的長度是%d\n",StackLength(S,1),StackLength(S,2));
printf("現在依次彈棧:");
SElemType e ;
Pop(&S,&e,1);
printf("%d,",e);
Pop(&S,&e,1);
printf("%d,",e);
Pop(&S,&e,2);
printf("%d,",e);
Pop(&S,&e,2);
printf("%d,",e);
Pop(&S,&e,2);
printf("%d,",e);
printf("\n現在棧1的長度是:%d,棧2的長度是%d\n",StackLength(S,1),StackLength(S,2));
return 0;
}
Status InitStack(SqDoubleStack *S) //初始化操作,建立一個空棧S
{
memset(S->data,0,sizeof(SElemType)*MAXSIZE);//數組各元素初始化爲0
S->top1 = -1;
S->top2 = MAXSIZE;
return OK;
}
Status DestroyStack(SqDoubleStack *S) //棧棧存在,則銷燬它
{
//free(S);
return OK;
}
Status ClearStack(SqDoubleStack *S) //將棧清空
{
memset(S->data,0,sizeof(SElemType)*MAXSIZE);
S->top1 = -1;
S->top2 = MAXSIZE;
return OK;
}
int StackEmpty(SqDoubleStack S,int stackNumber) //若棧爲空,返回true,否則返回false
{
if(1==stackNumber)
{
return S.top1 == -1;
}
else if(2==stackNumber)
{
return S.top2 == MAXSIZE;
}
return 0;
}
Status GetTop(SqDoubleStack S,SElemType *e,int stackNumber) //若棧存在且非空,用e返回S的棧頂元素
{
if(1==stackNumber)
{
if(StackEmpty(S,1))
{
return ERROR;
}
*e = S.data[S.top1];
return OK;
}
else if(2==stackNumber)
{
if(StackEmpty(S,2))
{
return ERROR;
}
*e = S.data[S.top2];
return OK;
}
return ERROR;
}
Status Push(SqDoubleStack *S,SElemType e,int stackNumber) //若棧S存在,將新元素e插入棧S中併成爲棧頂元素
{
if(S->top1 +1 == S->top2)
{
return ERROR;//已滿
}
if(1==stackNumber)
{
S->top1++;
S->data[S->top1] = e;
return OK;
}
else if(2==stackNumber)
{
S->top2--;
S->data[S->top2] = e;
return OK;
}
return ERROR;
}
Status Pop(SqDoubleStack *S,SElemType *e,int stackNumber) //刪除棧S中棧頂元素,並用e返回其值
{
if(StackEmpty(*S,stackNumber))
{
return ERROR;//爲空
}
if(1==stackNumber)
{
*e = S->data[S->top1];
S->top1--;
return OK;
}
else if(2==stackNumber)
{
*e = S->data[S->top2];
S->top2++;
return OK;
}
return ERROR;
}
int StackLength(SqDoubleStack S,int stackNumber) //返回棧S的長度
{
if(1==stackNumber)
{
return S.top1+1;
}
else if(2==stackNumber)
{
return MAXSIZE-S.top2;
}
return -1;
}
事實上,使用這樣的數據結構,通常都是當兩個棧的空間需求有相反關係時,也即一個棧增長時,另一個棧在縮短。這樣使用兩棧共享空間存儲方法纔有比較大的意義,否則兩個棧都在不停地增長,那很快就會有棧滿而溢出。