数据结构 实验报告05

一、实验目的和要求

设计并实现一个整型算术表达式计算器。(链栈实现)

二、实验环境

编译器:Vscode DevC++

系统:Windows10

CPU:i5-8265U@1.60GHz

三、实验内容

1. 基于课后作业03内容,存储结构采用链式存储。基于链栈,尽量少的改动课后作业-03代码,完成计算器功能。

2. 要求抽象出链栈结构进行独立实现(建议直接利用 课堂作业-03代码)。

3. 其它要求同作业-01要求。

四、实验过程

4.1 任务定义和问题分析

使用模板类来实现链栈的入栈、出栈、判空、判满、返回栈顶元素等等

        利用函数进行对运算符优先级的比较操作(需要用到迭代)

        由于第3次实验报告将栈的代码写在了my_stack_first.h里面

        所以此次报告 仅需将链栈写在新的类里面,并将头文件替换即可

4.2 数据结构的选择和概要设计

 

使用结构体创建节点

template <typename DataType>  

struct node

{

    DataType data;

    node *next;

};

4.3 详细设计

还是使用模板类来实现链栈

template <typename DataType>

class my_stack

需要实现入栈、出栈、判空、判满、返回栈顶元素等功能

 

my_stack()

~my_stack()

bool IsEmpty() const

bool IsFull()

void InsertStack(const DataType x)

E_code insertstack(const DataType x)

E_code get_top(DataType &xconst

DataType GetTop()

E_code OutStack(int x = 0)

在上面一些函数有些需要注意

  1. 初始化函数:不需要传参  指针的性质导致 无法预定大小
  2. 析构函数:由于默认析构函数不能将top后继节点delete 所以需要设置特殊析构函数处理
  3. 判满函数:由于不能自主控制大小,所以一般不会满 直接返回假就好(存在是要加强代码的可移植性)
  4. 返回栈顶元素:可供两种选择  在确保无非法状态时 可直接使用 GetTop函数 如果不确定 应该使用 get_top函数 有效判断各种情况  这种情况  我认为使用switch比较好
  5. 出栈函数:注意到 我添加了参数 由指针的特性 增加了删除任意位置的节点  默认为0 即栈顶

 

需要创建计数器(count)和栈顶指针(top)

private:

    int count;

    node<DataType> *top;

 

再测试实验数据的时候发现  当算式中出现空格  会导致 空格后的字符不能读入(cin>>sh;)

所以将 读入方式改为

getline(cin, sh);

再在循环当中加入忽略空格的语句

if(sh[i]==' ')

            continue;

测试  完成!!

之后想起 不能识别中文括号  所以想尝试解决一下  发现中文字符char的int型一直为-93

失败  此想法搁浅

五、测试及结果分析

5.1 实验数据

        使用第三次实验的数据

5.2 结果及分析

    

测试表达式

输出结果

正确结果

1+2

3

3

1+2*3-6/2+2/1*0

4

4

12+5*(2+3)*6/2-4

83

83

3*0+(9-6*4/2)*(2+1)

-9

-9

(1+2)+(2)+3*(4)

17

17

-1+3*0+(9-6*4/2)*(2+1)

-10

-10

(-1)*12+5*(2+3)*6/2-4

59

59

(-1)* 12 +5*(  2+3)*  6/2- 4

59

59

 

 

 

 

 

 

 

 

六、实验收获

深入理解了链栈存储结构  并进行了代码编写

        认识到代码规范性对代码可移植性的影响

        将类写在.h文件是个很不错的方法

七、参考文献

八、附录(源代码)

请自己实现链栈

cal.cpp

// #include"my_stack_first.h"

#include "my_stack_second.h"

#include <algorithm>

#include <cmath>

#include <cstdio>

#include <cstring>

#include <map>

using namespace std;

map<charint> ys;

my_stack<charstk_ch;

my_stack<doublestk_di;

int solve[5][5];//第一维表示待入栈运算符 第二表示栈顶运算符

//值为表示栈顶运算符出栈进行操作

//值为表示待入栈运算符入栈

//值为表示待入栈运算符出栈  栈顶运算符出栈  ()以及##

void init()

{

    ys['+'] = 1;

    ys['-'] = 1;

    ys['*'] = 2;

    ys['/'] = 2;

    ys['('] = 3;

    ys[')'] = 4;

    ys['#'] = 0;

    //以上是先给各个运算符编号

    solve[1][0] = 0;

    solve[1][1] = 1;

    solve[1][2] = 1;

    solve[1][3] = 0;

    // solve[1][4] = 1;

    //由于根本不会入栈 所以不存在4作为第二维出现

    //以下注释掉的组合均是不会出现的情况

    solve[2][0] = 0;

    solve[2][1] = 0;

    solve[2][2] = 1;

    solve[2][3] = 0;

    // solve[2][4] = ;

 

    solve[3][0] = 0;

    solve[3][1] = 0;

    solve[3][2] = 0;

    solve[3][3] = 0;

    // solve[3][4] = 1;

 

    // solve[4][0] = 1;

    //不会存在这种情况

    solve[4][1] = 1;

    solve[4][2] = 1;

    solve[4][3] = 2;

    // solve[4][4] = 1;

 

    solve[0][0] = 2;

    solve[0][1] = 1;

    solve[0][2] = 1;

    // solve[0][3] = 0;

    // solve[0][4] = 2;

}

void work(char wit)

{

    char top = stk_ch.GetTop();

    if (solve[ys[wit]][ys[top]] == 0)

    {

        stk_ch.InsertStack(wit);

        return;

    }       

    while (solve[ys[wit]][ys[top]] == 1)

    {

        double num2 = stk_di.GetTop();

        stk_di.OutStack();

        double num1 = stk_di.GetTop();

        stk_di.OutStack();

        switch(top){

            case '+':

                num1 += num2;

                break;

            case '-':

                num1 -= num2;

                break;

            case '*':

                num1 *= num2;

                break;

            case '/':

                num1 /= num2;

                break;

        }

        stk_di.InsertStack(num1);

        stk_ch.OutStack();

        top = stk_ch.GetTop();

    }

    if (solve[ys[wit]][ys[top]] == 0)

    {

        stk_ch.InsertStack(wit);

        return;

    }

    if (solve[ys[wit]][ys[top]] == 2)

        stk_ch.OutStack();

}

int main()

{

    string sh;

    getline(cin,sh);

    init();

    sh = '#'+sh + '#';

    stk_ch.InsertStack('#');

    for (int i = 1; i < sh.length();i++)

    {

        if(isdigit(sh[i])){

            int flag = 1;

            if(ys[sh[i-1]]==1&&(sh[i-2]=='('||sh[i-2]=='#'))

            {

                if (sh[i - 1] == '-')

                    flag = -1;

                // cout << i << "\n";

                stk_ch.OutStack();

            }

            int di = 0;

            while (isdigit(sh[i])){

                di *= 10;

                di += sh[i] - '0';

                i++;

            }

            di *= flag;

            stk_di.InsertStack(di);

            

            // cout << di;

        }

        if(sh[i]== ' ')

              continue;

        work(sh[i]);

    }

    // cout << "\n";

    cout << stk_di.GetTop();

    system("pause");

}

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值