// c3-1.h 栈的顺序存储结构(见图3.1)
#define STACK_INIT_SIZE 10 // 存储空间初始分配量
#define STACK_INCREMENT 2 // 存储空间分配增量
struct SqStack
{
SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL
SElemType *top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
}; // 顺序栈
// bo3-1.cpp 顺序栈(存储结构由c3-1.h定义)的基本操作(9个)
void InitStack(SqStack &S)
{ // 构造一个空栈S(见图3.2)
if(!(S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType))))
exit(OVERFLOW); // 存储分配失败
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
}
void DestroyStack(SqStack &S)
{ // 销毁栈S,S不再存在(见图3.3)
free(S.base);
S.base=NULL;
S.top=NULL;
S.stacksize=0;
}
void ClearStack(SqStack &S)
{ // 把S置为空栈
S.top=S.base;
}
Status StackEmpty(SqStack S)
{ // 若栈S为空栈,则返回TRUE;否则返回FALSE
if(S.top==S.base)
return TRUE;
else
return FALSE;
}
int StackLength(SqStack S)
{ // 返回S的元素个数,即栈的长度
return S.top-S.base;
}
Status GetTop(SqStack S,SElemType &e)
{ // 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
if(S.top>S.base)
{
e=*(S.top-1);
return OK;
}
else
return ERROR;
}
void Push(SqStack &S,SElemType e)
{ // 插入元素e为新的栈顶元素(见图3.4)
if(S.top-S.base>=S.stacksize) // 栈满,追加存储空间
{
S.base=(SElemType *)realloc(S.base,(S.stacksize+STACK_INCREMENT)*sizeof(SElemType));
if(!S.base)
exit(OVERFLOW); // 存储分配失败
S.top=S.base+S.stacksize;
S.stacksize+=STACK_INCREMENT;
}
*(S.top)++=e;
}
Status Pop(SqStack &S,SElemType &e)
{ // 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;
// 否则返回ERROR(见图3.5)
if(S.top==S.base)
return ERROR;
e=*--S.top;
return OK;
}
void StackTraverse(SqStack S,void(*visit)(SElemType))
{ // 从栈底到栈顶依次对栈中每个元素调用函数visit()
while(S.top>S.base)
visit(*S.base++);
printf("\n");
}
// main3-1.cpp 检验bo3-1.cpp的主程序
#include"c1.h"
typedef int SElemType; // 定义栈元素类型,此句要在c3-1.h的前面
#include"c3-1.h"
#include"bo3-1.cpp"
void print(SElemType c)
{
printf("%d ",c);
}
void main()
{
int j;
SqStack s;
SElemType e;
InitStack(s);
for(j=1;j<=12;j++)
Push(s,j);
printf("栈中元素依次为");
StackTraverse(s,print);
Pop(s,e);
printf("弹出的栈顶元素e=%d\n",e);
printf("栈空否:%d(1:空0:否)\n",StackEmpty(s));
GetTop(s,e);
printf("栈顶元素e=%d 栈的长度为%d\n",e,StackLength(s));
ClearStack(s);
printf("清空栈后,栈空否:%d(1:空0:否)\n",StackEmpty(s));
DestroyStack(s);
printf("销毁栈后,s.top=%u s.base=%u s.stacksize=%d\n",s.top,s.base, s.stacksize);
}
代码运行的结果:
/*
栈中元素依次为1 2 3 4 5 6 7 8 9 10 11 12
弹出的栈顶元素e=12
栈空否:0(1:空0:否)
栈顶元素e=11 栈的长度为11
清空栈后,栈空否:1(1:空0:否)
销毁栈后,s.top=0 s.base=0 s.stacksize=0
Press any key to continue
*/
/*
栈也是线性表,是操作受限的线性表。栈的操作是线性表操作的子集。因此,也可以
将线性表的结构作为栈的结构。例如,可把不带头结点的线性单链表结构(见图212)作
为链栈的结构,如图36 所示。这样,线性单链表的一些基本操作(在bo2-8.cpp 中)就
可以直接用于链栈的操作了。例如,初始化链表
和初始化链栈的操作是一样的,就不必定义
InitStack() 函数, 可通过“ #define InitStack
InitList ” 命令直接把InitList() 函数当作
InitStack()函数使用。同时把栈元素SElemType
定义为线性表元素ElemType。线性表的另一些
基本操作,如ListInsert()也可以作为栈的基本操作Push()来使用(取特例i=1,即在第1 个
元素之前插入)。由于栈的操作被限定仅在栈顶进行,显然,令表头为栈顶可简化栈的操
作。教科书对栈的定义是:限定仅在表尾进行插入或删除操作的线性表(教科书44 页)。
*/