数据结构-栈与队列

  • 实验项目名称

栈和队列

  • 实验内容

表达式求值运算是实现程序设计语言的基本问题之一,也是栈应用的一个典型例子。设计并演示用算符优先级对算术表达式的求解过程。

  • 算法分析

typedef struct operands {

    double data;

    struct operands* next = NULL;

}ANDS;

typedef struct operators {

    char data;

    struct operators* next = NULL;

}ATORS;

ANDS* Push(double data, ANDS* ands) {

    ANDS* p = new ANDS;

    p->data = data;

    p->next = ands;

    return p;

}

ATORS* Push(char data, ATORS* ators) {

    ATORS* p = new ATORS;

    p->data = data;

    p->next = ators;

    return p;

}

double Pop(ANDS*& p) {

    ANDS* q = new ANDS;

    q = p;

    double e = q->data;

    p = p->next;

    free(q);

    return e;

}

char Pop(ATORS*& p) {

    ATORS* q = new ATORS;

    q = p;

    char e = p->data;

    p = p->next;

    free(q);

    return e;

}

double Top(ANDS* p) {

    return p->data;

}

char Top(ATORS* p) {

    return p->data;

}

栈的定义,以及对栈的基本操作:将元素压入栈,将元素出栈并返回栈顶元素,返回栈顶元素。时间复杂度都为O(1)。

string Transtack(string str) {// 将运算表达式转化为后缀表达式

    string s;

    if (str[str.length() - 1] != '=') {

         str += '=';

    }

    ATORS* OPTR = new ATORS;// 运算符栈

    OPTR = Push('#', OPTR);// '#'为栈底

    for (int i = 0; ; i++) {

         char c;

         switch (str[i]) {

         case '(':

             OPTR = Push(str[i], OPTR);

             s += ' ';

             break;

         case ')':

             c = Pop(OPTR);

             if (c == '(') {

                  s += ' ';

             }

             while (c != '(') {

                  s += c;

                  c = Pop(OPTR);

             }

             break;

         case '+':

         case '-':

             c = Pop(OPTR);

             while (c != '(' && c != '#') {

                  s += c;

                  c = Pop(OPTR);

             }

             OPTR = Push(c, OPTR);

             OPTR = Push(str[i], OPTR);

             s += ' ';

             break;

         case '*':

         case '/':

             c = Pop(OPTR);

             while (c == '*' || c == '/') {

                  s += c;

                  c = Pop(OPTR);

             }

             OPTR = Push(c, OPTR);

             OPTR = Push(str[i], OPTR);

             s += ' ';

             break;

         case '=':

             c = Pop(OPTR);

             while (c != '#') {

                  s += c;

                  c = Pop(OPTR);

             }

             return s;

         default:// 是操作数

             s += str[i];

             if (str[i + 1] > '9' || str[i + 1] < '0') {

                  s += ' ';

             }

             break;

         }

    }

}

将运算表达式转化为后缀表达式:

(1) 首先构造一个运算符栈,运算符(以括号为分界点)在栈内遵循越往栈顶优先级不降低的原则进行排列。

  (2)从左向右扫描算术表达式,从左边第一个字符开始判断:

  a.如果当前字符是字母,则直接输出。

  b.如果是运算符(不包括括号),则比较优先级。

  ①如果是空栈,直接入栈;

  ②如果当前运算符的优先级大于栈顶运算符的优先级,则将运算符直接入栈;

  注:对于优先级相同的运算符来说,先出现的先运算,所以优先级相等的情况是要先将栈顶元素出栈再将当前元素入栈。

  ③否则将栈顶运算符出栈并输出,直到当前运算符的优先级大于栈顶运算符的优先级or栈顶是左括号时,再将当前运算符入栈。

注:括号比任何在括号前面入栈的元素优先级都大,比任何在左括号之后的,右括号之前的优先级都小。因为括号之中的运算符优先级最大

  c.如果是括号,则根据括号的方向进行处理。

   ①如果是左括号,则直接入栈;

  ②否则,遇右括号前将所有的运算符全部出栈并输出,遇左括号后将左右的两括号一起删除。

  (3) 重复上述操作(2)直至扫描结束,将栈内剩余运算符全部出栈并输出。

double Calculation(string s)

{

    s += '#';// 结束标志

    ANDS* ands = new ANDS;// 运算数栈

    double temp = 0;

    for (int i = 0; s[i] != '#'; i++)

    {

         if (s[i] == ' ') {

             temp /= 10;

             if (temp == 0) {

                  continue;

             }

             ands = Push(temp, ands);

             temp = 0;

             continue;

         }

         if (s[i] >= '0' && s[i] <= '9')

         {

             temp = (temp + int(s[i]) - 48) * 10;

         }

         else

         {

             double a, b;

             a = Pop(ands);

             b = Pop(ands);

             if (s[i] == '+')

                  ands = Push(a + b, ands);

             else if (s[i] == '-')

                  ands = Push(b - a, ands);

             else if (s[i] == '*')

                  ands = Push(b * a, ands);

             else if (s[i] == '/')

                  ands = Push(b / a, ands);

         }

    }

    return Pop(ands);

}

计算后缀表达式:通过后缀表达式计算就不用考虑括号问题了,直接计算即可。

  • 实验结果

  • 思考体会

通过后缀表达式计算运算表达式是一种不错的方法,这次实验让我跟多得了解了栈的知识。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

微风-_-

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

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

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

打赏作者

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

抵扣说明:

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

余额充值