数据结构实验三

实验三栈的基本操作必做,设计性实验)

  1. 实验目的

熟练掌握栈的抽象数据类型,能在相应的应用问题中正确选用它,熟练掌握栈的实现方法(顺序和链式),两种存储结构和基本操作的实现算法,注意空和满的判断条件及它们的描述方法。深入了解栈的特性,能在实际问题的背景下灵活运用他们,并加深对这种结构的理解。

  1. 实验内容(选其中之一书写实验报告)

选择合适的存储结构(顺序栈或链式栈)表示栈,给出其定义,在上述存储结构上实现栈的基本操作:初始化、置栈空、入栈、出栈、取栈顶元素等。然后完成下述任务之一:

1)用栈实现括号匹配的检验

2)用栈实现形如a+b@b+a#的中心对称的字符序列的检验。

(3)设计一个程序,演示用算符优先法对算术表达式求值的过程。以字符序列的形式从终端输入语法正确的、不含变量的整数表达式。利用教科书表3.1给出的算符优先关系,实现对算术四则运算混合运算表达式的求值,并仿照教科书的例子3-1演示在求值中运算符栈、运算数栈、输入字符和主要操作的变化。测试数据可以选择例子3-1的算术表达式 3*(7-2),或自选。

  1. 数据结构定义

说明你算法中用到的数据结构、数据类型的定义

数据结构:一种只能在一端进行插入或删除操作的线性表—栈。表中允许插入、删除操作的一端称为栈顶。栈顶的当前位置是动态的,栈顶的当前位置由一个称为栈顶指针的位置指示器指示。当栈中没有元素时,为空栈,栈的插入操作和删除操作通常称为进栈和出栈。栈的主要特点是后进先出。采用的存储结构是链式存储。

数据类型的定义:stacksize表示栈当前可使用的最大容量。Base时栈底指针,top作为栈顶指针。

typedef struct{

 SElemType *base;//栈底指针

 SElemType *top;//栈顶指针

 int stacksize;//当前已经分配的存储空间

}SqStack;

  1. 算法思想及算法设计

先文字说明算法的思想,然后给出类C语言算法

(1)算法思想

①首先定义一个算符优先关系的二维数组,为实现算符优先算法,使用两个工作栈,一个称作OPTR,用以寄存运算符,另一个称作OPND,用以寄存操作数或者运算结果;②依次读入每个字符,若操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权后再操作,若高于OPTR栈的栈顶运算符优先权则入栈,若低于OPTR栈的栈顶运算符优先权则将OPTR栈的栈顶运算符和OPND栈的两个操作数出栈并将运算结果入OPND栈,若与OPTR栈的栈顶运算符优先权相等则将栈内括号出栈即可,直到整个表达式求值完毕;③最后输出算术表达式结果。

(2)类C语言算法

OperandType EvaluateExpression(){

//算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈

  InitStack(OPTR); Push(OPTR,'#');

InitStack(OPND); c = getchar();

  while(c!='#'||GetTop(OPTR)!='#'){

  if(isdigit(c)){ //如果是数字的话将其转化为数字然后入操作数栈

    i = num =0; //num用于将字符串中的数字转化为整数然后入栈

    while(isdigit(c)){ //先将数字转化为整数

     data[i] = c-'0'; i++; c = getchar();}

    for(int j=0;j<i;j++)  

     num = num*10+data[j];

    Push(&OPND,num); //不是运算符入栈

   }

  else

  switch(Priority(GetTop(&OPTR),c)){

  case '<':

Push(&OPTR,c); c = getchar();

        break;

     case '>':

Pop(&OPND,&b); Pop(&OPND,&a);

        Pop(&OPTR,&theta);

        Push(&OPND,Reckon(a,theta,b));

        break;//将结果入栈

     case '=':

Pop(&OPTR,&theta); c = getchar();

        break;//说明括号相遇 删除栈内括号即可

     default:break;

    }

   }

  }

  Pop(&OPND,&result);

  printf("结果是:%d",result);

}

  1. 实验代码

即C语言程序

详见电子版

  1. 算法测试结果

说明测试数据,粘贴实验结果图

  1. 分析与总结

(1)算法复杂度分析及优、缺点分析

说明你编写算法的复杂度,算法的优点和缺点有哪些

算法复杂度分析:

InitStack(SqStack *s),   Push(SqStack *s,SElemType e),    Pop(SqStack *s,SElemType *e),

GetTop(SqStack *s),    Index(char c),    Priority(char a,char b),

Reckon(int a,char theta,int b),     isdigit(char ch)

算法时间复杂度为O(1)

main()

时间复杂度为O(n*i)(i为算数表达式中最大数的位数)

优点:

①方便求解复杂表达式:栈提供了一种便捷的数据结构,可以嵌套存储操作数和运算符,使得复杂的算术表达式的求解变得相对简单明了。

②支持多层嵌套括号:栈的先进后出特性使得我们可以处理多层嵌套的括号,并能够正确计算出表达式的值。

③减少重复计算:在利用栈求值时,可以通过对操作数进行运算并将结果存储在栈中,避免了重复计算,提高了效率。

④灵活性强:通过使用栈,我们可以容易地扩展算术表达式的解析能力,例如支持更多的运算符、函数等。

缺点:

①内存消耗较大:使用栈来解决算术表达式的求值需要额外的内存空间存储栈元素,这对于大型表达式可能导致较大的内存消耗。

②需要预处理和转换:在使用栈求解算术表达式之前,通常需要对中缀表达式进行转换为后缀表达式的操作,这增加了实现算法的复杂性和开销。

③不适用于大型表达式:当算术表达式非常大或者括号嵌套层数过多时,使用栈求解可能导致栈的溢出或者内存不足等问题。

④对表达式有一定要求:在使用栈求解算术表达式时,要求表达式的格式和语法正确,否则可能会导致求值结果不准确或报错。

(2)实验总结

说明你怎么解决实验中遇到的问题,有什么收获

问题:如何正确判断运算符的优先级并进行正确的转换。

解决办法:可以使用运算符的优先级来建立一个优先级表,并在转换过程中使用该表进行判断。在程序中,定义一个算符之间优先关系的二维数组,确定输入的字符是操作符就判断在二维数组中的下标,从而等运算符之间的优先关系。另外,要注意处理括号的情况,左括号和右括号的优先级相同,将左括号先入栈,若遇到右括号,则左括号出栈。

收获:

①深入理解了栈的特性和用途,学会了栈的基本操作,以及在算术表达式求值中的应用,对算术表达式的求值过程有了更深入的理解,在实践中加深了对栈的认识和掌握。

②提高了解决问题的能力,通过思考和调试找到并解决了不同的问题。

③培养了耐心和细心的精神,因为算术表达式的求值在每个步骤都需要仔细考虑和处理。

④对数据结构和算法的学习也有了更深入的体会。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玛卡巴卡hhh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值