目录
目的
验证顺序存储的栈及其上的基本操作。
内容及要求
- 定义顺序栈类。
- 实现如下算法:
1)创建顺序栈;
2)插入操作:向栈顶压入值为x的元素;
3)删除操作:弹出栈顶元素,将数据输出在屏幕上;
4)存取操作:读取栈顶元素,将数据输出在屏幕上;。 - 为了增强程序的可读性,程序中要有适当的注释。
- 随机给出栈操作指令序列,完成程序验证。例如:(压栈a,压栈b,压栈 c,压栈d,弹栈,弹栈,弹栈,压栈e,弹栈,读栈顶,弹栈。屏幕应输出d,c,b,e,a,a)
实验过程
算法设计、代码编写、程序调试、测试数据设计、测试
算法设计
先编写有关顺序栈操作的各个函数:
InitStack(SqStack &S)
DestroyStack(SqStack &S)
ClearStack(SqStack &S)
StackEmpty(SqStack S)
StackLength(SqStack S)
GetTop(SqStack S, ElemType &e)
Push(SqStack &S, ElemType &e)
Pop(SqStack &S, ElemType &e)
StackTraverse(SqStack S)
之后的八个函数对应主函数中的八项功能,通过选择结构语句确定执行哪项功能。
代码编写
//头文件
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
//宏定义
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef int ElemType;
typedef int Status;
//栈的顺序结构表示
typedef struct {
ElemType *base;
ElemType *top;
int stacksize;
}SqStack;
//1.构建一个空栈
Status InitStack(SqStack &S)
{
S.base = (ElemType*)malloc(STACK_INIT_SIZE*sizeof(ElemType));
if (!S.base)
exit(OVERFLOW);//存储分配失败
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
//2.销毁栈
Status DestroyStack(SqStack &S)
{
S.top = NULL;
S.stacksize = 0;
free(S.base);
return OK;
}
//3.清空栈
Status ClearStack(SqStack &S)
{
S.top = S.base;
return OK;
}
//4.判断栈是否为空
Status StackEmpty(SqStack S)
{
if (S.top == S.base)
return ERROR;
else
return TRUE;
}
//5.求栈的长度
Status StackLength(SqStack S)
{
if (S.top == S.base)
return FALSE;
else
return (S.top - S.base);//也可以直接返回S.top - S.base
}
//6.求栈顶元素
Status GetTop(SqStack S, ElemType &e)
{
if (S.top == S.base)
return FALSE;
else e = *(S.top - 1);
return e;
}
//7.栈顶插入元素
Status Push(SqStack &S, ElemType &e)
{
if (S.top - S.base >= STACK_INIT_SIZE)
{
S.base = (ElemType *)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(ElemType));
if (!S.base)
{
return false;
}
S.top = S.base + STACK_INIT_SIZE; //栈底地址可能改变,重新定位栈顶元素
S.stacksize = S.stacksize + STACKINCREMENT;
}
*S.top = e;
S.top++;
return OK;
}
//8.删除栈顶元素
Status Pop(SqStack &S, ElemType &e)
{
if (S.top == S.base)
return ERROR;
else
{
S.top--;
e = *S.top; //实际上此元素并没真正删除,仍在S.top中,但是如果插入元素,就会被更新,就像是删除了一样
return e; }
}
//9.遍历栈
Status StackTraverse(SqStack S)
{
if (S.base == NULL)
return ERROR;
if (S.top == S.base)
printf("栈中没有元素……\n");
ElemType *p;
p = S.top;
while (p > S.base)
{
p--;
printf("%d ",*p);
}
return OK;
}
Status two(SqStack S){
printf("--本栈是空栈吗??--\n");
if (StackEmpty(S) == 1)
printf("NO !\n");
else printf("YES !!!\n");
}
Status three(SqStack S){
printf("--求出栈的长度--\n");
int m;
m = StackLength(S);
printf("栈的长度是:\n");
printf("%d\n",m);
}
Status four(SqStack S){
printf("遍历输出栈中的所有元素:\n");
StackTraverse(S);
printf("\n");
}
Status five(SqStack S){
printf("--输出栈顶元素--\n");
int e;
e = GetTop(S, e);
printf("栈顶元素是:\n");
printf("%d\n",e);
}
Status six(SqStack S){
printf("--栈顶插入元素--\n");
int e;
e = GetTop(S, e);
printf("请输入要插入的元素的数值:\n");
scanf("%d",&e);
Push(S,e);
printf("现在栈中的元素是:\n");
StackTraverse(S);
printf("\n");
}
Status seven(SqStack S){
printf("--栈顶删除元素--\n");
int e;
e = Pop(S,e); printf("被删除的元素是:\n");
scanf("%d",&e); printf("现在栈中的元素是:\n");
StackTraverse(S);
printf("\n");
}
Status eight(SqStack S){
printf("--清空栈--\n");
ClearStack(S);
printf("现在栈中的元素是:\n");
StackTraverse(S);
}
Status nine(SqStack S){
printf("--销毁栈--\n");
if(DestroyStack(S)==1)
printf("销毁栈成功\n");
else
printf("销毁栈失败\n");
}
//主函数
int main()
{
int e;
SqStack S;
printf("构造一个栈……\n");
InitStack(S);
int i,n ;
printf("输入栈的长度:\n");
scanf("%d",&n);
for (i = 1; i <= n; i++)
{
printf("输入栈的第%d个元素\n",i);
++S.top;
scanf("%d",S.top-1);
}
int choice;
while(1){
printf("\n\n1:栈的判空\n2:求栈的长度\n3:遍历输出栈\n4:输出栈顶元素\n5:栈顶删除元素\n6:栈顶插入元素\n7:清空栈\n8:销毁栈\n");
scanf("%d",&choice);
switch(choice){
case 1:two(S);break;
case 2:three(S);break;
case 3:four(S);break;
case 4:five(S);break;
case 5:seven(S);break;
case 6:six(S);break;
case 7:eight(S);break;
case 8:nine(S);break;
}
}
return 0;
}
程序调试
1.顺序栈的操作main.cpp [Error] ‘S’ was not declared in this scope
进行分析后发现错误是由于并未在函数中声明pos的类型,当把pos声明为int类型时,错误消失。
2.在写主函数时,如果是用void main 的形式,可以不用有返回值,如果是int main或status main 的话,要有返回值,即末尾要有return 语句。
3.在定义栈的时候num 中的元素最好使用int类型的而不是char 类型的,因为这样会简化计算复杂度。
测试数据设计
先输入3,再输入1,2,3,创建一个长度为3的栈;
输入1,进行栈的判空,返回NO;
输入2,求栈的长度,返回3;
输入3,遍历栈,返回1,2,3;
输入4,输出栈顶元素3;
输入5,栈顶插入元素4;
输入6,栈顶删除元素4,剩1,2,3;
输入7,清空栈;
输入8,销毁栈;
结果
总结
程序运行过程有些繁复,还有需要改进的地方。关于遇到的问题,有以下几点:在做表达式的计算的时候,一定要注意何时入栈何时出栈,如果情况判断不清楚就无法得出答案;对于表达式的判错情况,根据题目的情况对每次读入的字符进行判断;分号的忘记问题要加强注意。