其实栈的顺序存储很方便,因为它只在表尾进行操作,不存在普通线性表插入与删除还需要移动元素的情况。同样它也有普通线性表的缺陷,即必须确定数量。然而对于两个相同类型的栈,却可以做到最大限度地利用其开辟的存储空间来进行操作。
数组有两个端点,两个栈使用这一个数组的存储区域,两个栈有两个栈底,分别为数组的始端和末端。
这样在压栈的时候,是栈顶指针往中间靠拢,当两指针相遇时,则栈满。栈空即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;
}
事实上,使用这样的数据结构,通常都是当两个栈的空间需求有相反关系时,也即一个栈增长时,另一个栈在缩短。这样使用两栈共享空间存储方法才有比较大的意义,否则两个栈都在不停地增长,那很快就会有栈满而溢出。