// 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(" "); }
// 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 ",e); printf("栈空否:%d(1:空0:否) ",StackEmpty(s)); GetTop(s,e); printf("栈顶元素e=%d 栈的长度为%d ",e,StackLength(s)); ClearStack(s); printf("清空栈后,栈空否:%d(1:空0:否) ",StackEmpty(s)); DestroyStack(s); printf("销毁栈后,s.top=%u s.base=%u s.stacksize=%d ",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 页)。 */