实验三:栈的基本运算
1、 实验目的
(1) 掌握栈的各种存储结构及基本运算的实现。
(2) 掌握堆栈后进先出的运算原则在解决实际问题中的应用。
(3) 复习c语言中相关语句及函数的用法。
2、 实验要求
(1) 熟练掌握栈的存储结构及其基本操作。
(2) 理解所给出的算法,掌握栈在实际中的应用。
(3) 将上机程序调试通过,并能独立完成一至两个拓展题目。
3、 实验内容
括号配对检查。试设计一个程序对任意输入的语句或数学表达式,判断其括号是否匹配。若匹配,则返回1,否则返回0。调试程序并对相应的输出作出分析;修改输入数据,预期输出并验证输出的结果。加深对算法的理解。
4、 实验方法
首先建立一个栈结构,且初始化栈为空。然后由键盘上随即输入一个带括号的语句或带括号的数学表达式,同时将它们保存在一个字符型数组exps[]中。扫描表达式exps,当遇到“(”、“[”、“{”时,将其入栈。遇到“)”、“]”、“}”时,判断栈顶是否有相匹配的括号。若没有,则退出扫描过程,返回0,否则直到exps扫描完毕为止。若top为0,则返回1。
5、验证程序
#include "stdio.h"
#define MAXSIZE 100
#define TRUE 1
#define FALSE 0
#define NULL 0
typedef int datatype;
typedef struct /*顺序栈的结构体类型定义*/
{datatype stack[MAXSIZE];
int top;
}seqstack;
void setnull(seqstack *s) //置空栈-由于c语言的数组下标是从0开始的,所以置
{s->top=-1;} //空栈操作时将栈顶指针放在下标为0之前,即-1处。
int empty(seqstack *s) /*判断当前栈是否为空栈*/
{if(s->top<0)
return TRUE;
else
return FALSE;
}
int push(seqstack *s,datatype x) /*把元素x压入栈s中*/
{if(s->top>=MAXSIZE-1)
{printf("stack overflow!
"); /*发生上溢*/
return FALSE;
}
else
{s->stack[++s->top]=x; /*栈顶指针上移,数据元素入栈*/
return TRUE;
}
}
datatype pop(seqstack *s) /*弹出当前栈s的栈顶元素*/
{if(s->top<0)
{printf("stack empty!
"); /*栈空,返回空值*/
return NULL;
}
else
{s->top--;
return(s->stack[s->top+1]);
}//由于return语句的特点,必须先使top减1,然后再执行return语句。而此
} //时栈顶元素的表示应该为s->top+1.
int judge(seqstack *s) //括号匹配检查算法。--遇到"("、"["、"{"时,将其压入栈s中。
{
datatype symb,ch;
push(s,'#');
symb=getchar();//从键盘接受字符
while(symb!='#')
{
switch(symb)
{
case '(':
case '[':
case '{': push(s,symb);break;
case ')':
ch=pop(s);
if(ch!='(') return FALSE;
break;
case ']':
ch=pop(s);
if(ch!='[') return FALSE;
break;
case '}':
ch=pop(s);
if(ch!='{') return FALSE;
break;
default:;
}
symb=getchar();
}
if(pop(s)=='#') return TRUE;
else return FALSE;
}
main()
{
seqstack q;
setnull(&q);
printf("please input an express end with symbol '#':
");
if(judge(&q)) printf("yes
"); //括号匹配,则输出yes
else printf("no
"); //括号不匹配,则输出no
}
验证程序结果如下图:
6、 预习思考题
调试好上述程序后,试着完成以下拓展内容:
(1) 假定表达式不是通过getchar()函数一个个传送的,而是存放在一个字符数组A[n]中,程序需要做哪些改变?
(2) 在judge()函数中,如果不用switch()函数,你会怎么处理?
思考一:解题思路是用数组储存字符,并用数组传递字符。在主函数里面定义一个字符,用一个for循环向数组输入字符,以#结束。在传递数据的时候,传递栈和数组即可,在子函数中用while(B[i]!=’#’)进行读取字符,进而取代getchar()函数。
int judge(seqstack *s,char B[]) //括号匹配检查算法。--遇到"("、"["、"{"时,将其压入栈s中。
{
datatype symb,ch;
int i=0;
push(s,'#');
while(B[i]!='#')
{
symb=B[i];
switch(symb)
{
case '(':
case '[':
case '{': push(s,symb);break;
case ')':
ch=pop(s);
if(ch!='(') return FALSE;
break;
case ']':
ch=pop(s);
if(ch!='[') return FALSE;
break;
case '}':
ch=pop(s);
if(ch!='{') return FALSE;
break;
default:;
}
i++;
}
if(pop(s)=='#') return TRUE;
else return FALSE;
}
main()//主函数
{
char A[MAXSIZE];
int i=0;
seqstack q;
setnull(&q);
printf("please input an express end with symbol '#':
");
for(i=0;i
思考二:解题思路可以用if······else······if····嵌套实现,此时要注意,要把之前的break删掉,否则会提前退出。
int judge(seqstack *s) //括号匹配检查算法。--遇到"("、"["、"{"时,将其压入栈s中。
{
datatype symb,ch;
push(s,'#');
symb=getchar();//从键盘接受字符
while(symb!='#')
{
if(symb=='('||symb=='['||symb=='{')
{
push(s,symb);
}
else if(symb==')')
{
ch=pop(s);
if(ch!='(') return FALSE;
}
else if(symb==']')
{ ch=pop(s);
if(ch!='[') return FALSE;
}
else if(symb=='}')
{ ch=pop(s);
if(ch!='{') return FALSE;
}
symb=getchar();
}
if(pop(s)=='#') return TRUE;
else return FALSE;
}
main()
{
seqstack q;
setnull(&q);
printf("please input an express end with symbol '#':
");
if(judge(&q)) printf("yes
"); //括号匹配,则输出yes
else printf("no
"); //括号不匹配,则输出no
}
将上述代码直接和之前的源代码替换即可。
7、 分析讨论题:
数制转换问题是栈应用的一个典型实例。将十进制数转换成其它进制的数有一种简单的方法:例:十进制转换成八进制:(66)10=(102)8
66/8=8 余 2
8/8=1 余 0
1/8=0 余 1
结果为余数的逆序:102 。如果用栈的算法来实现,怎样实现?其基本原理是什么?
解题思路:根据进制转化的算法,取余之后倒序输出。同时栈也是先进后出的性质,可以用栈来依次储存余数,最后输出栈元素,即可转化进制。
算法实现:用x表示需要转化的数,用N表示转化的进制。
void trans(seqstack *s,int x,int N)
{
while(x!=0)
{
push(s,x%N);
x=x/N;
}
while(s->top!=-1)
printf("%d",pop(s));
}
main()
{
int a,b;
seqstack q;
setnull(&q);
printf("请输入需要转换的数和与转换进制类型:
");
scanf("%d%d",&a,&b);
printf("输出结果:
");
trans(&q,a,b);
printf("
");
}
上述代码可以转换成任意进制。

