桂电-数学与计算科学学院-《数据结构实验-宁黎华编》(实验三)

2019-04-13 16:03发布

实验三:栈的基本运算

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 } 验证程序结果如下图:
输出NO
输出YES

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(" "); } 上述代码可以转换成任意进制。
转换成二进制
转换成六进制
转换成八进制