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

实验三:栈的基本运算

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!\n"); /*发生上溢*/
    return FALSE;
    }
   else
    {s->stack[++s->top]=x; /*栈顶指针上移,数据元素入栈*/
     return TRUE;
    }
 }

 datatype pop(seqstack *s) /*弹出当前栈s的栈顶元素*/
 {if(s->top<0)
   {printf("stack empty!\n"); /*栈空,返回空值*/
    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 '#':\n");
 if(judge(&q)) printf("yes\n");  //括号匹配,则输出yes
 else          printf("no\n");   //括号不匹配,则输出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 '#':\n");
 for(i=0;i<MAXSIZE;i++)
 {
	 scanf("%c",&A[i]);
	 if(A[i]=='#')break;
 }
 if(judge(&q,A)) printf("yes\n");  //括号匹配,则输出yes
 else          printf("no\n");   //括号不匹配,则输出no
 }

思考二:解题思路可以用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 '#':\n");
 if(judge(&q)) printf("yes\n");  //括号匹配,则输出yes
 else          printf("no\n");   //括号不匹配,则输出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("请输入需要转换的数和与转换进制类型:\n");
 scanf("%d%d",&a,&b);
 printf("输出结果:\n");
 trans(&q,a,b);
 printf("\n");
}

上述代码可以转换成任意进制。
转换成二进制
转换成六进制
转换成八进制

猜你喜欢

转载自blog.csdn.net/sinat_43009982/article/details/83120213
今日推荐