算法 表达式求值

标签: 算法 表达式求值
21人阅读 评论(2) 收藏 举报
分类:

表达式求值中用到了两个栈,一个栈存放的是操作数,另一个栈存放的是操作符(运算符号和#),#可以让循环结束(#优先级最小),下面是各个操作符优先级的比较,其中θ1为opter(操作符)栈的栈顶,θ2位字符ch,x意为不可比较


步骤:

1.先初始化两个栈opval(操作数)栈,opter(操作符)栈

2.将起始符#压入opter栈中,以便后续循环中输入#能够结束循环

3.定义一个count变量,并将初值设为0,这个变量的作用是能够将多位数字字符转化为double型压入栈中

4.循环(opter栈为空退出),内有两部分,一部分为数字的存放,另一部分为操作符的比较和存放,以及运算

①第一部分中分两类,一类实现的是多位数字的存入,另一类实现个位数字或第一次进入栈的单个数字字符的存入,同时这里就可以体现出count的作用了,具体实现看代码

②第二部分中使用到了两个函数,一个是返回二维数组下标的函数,另一个是返回优先级比较结果的函数

按照上表的顺序返回下标的函数中各个符号在数组中的位置是+~1,-~2,*~3,/~4,(~5,)~6,#~7

注意在优先级比较函数中,要减一(下标是从0开始的)

根据比较出来的结果:

如果是>,则将opval栈顶元素以及栈顶前面的一个元素弹出栈,最后将结果两数的计算结果存入栈中

如果是<,则直接将运算符压入opter栈中,接着读取字符

如果是=,则将opter栈顶元素弹出,接着读取字符

代码:

#include <iostream>
#include <stack>
#include <cctype>
#include <cstdio>
#include <cstdlib>
using namespace std;

stack <char> opter; //存储操作符
stack <double> opval;   //存储操作数
//根据上表返回操作符的位置下标
int Index(char ch)
{
    int index = 0;
    switch(ch)
    {
        case '+':
            index = 1;
            break;
        case '-':
            index = 2;
            break;
        case '*':
            index = 3;
            break;
        case '/':
            index = 4;
            break;
        case '(':
            index = 5;
            break;
        case ')':
            index = 6;
            break;
        case '#':
            index = 7;
            break;
        default:
            break;
    }
    return index;
}
//比较运算符之间的优先级
char Compare(char ch1, char ch2)
{
    char compare[][7] = {
                            {'>', '>', '<', '<', '<', '>', '>'},    //x表示不能比较
                            {'>', '>', '<', '<', '<', '>', '>'},
                            {'>', '>', '>', '>', '<', '>', '>'},
                            {'>', '>', '>', '>', '<', '>', '>'},
                            {'<', '<', '<', '<', '<', '=', 'x'},
                            {'>', '>', '>', '>', 'x', '>', '>'},
                            {'<', '<', '<', '<', '<', 'x', '='}
                        };
    int index1 = Index(ch1);
    int index2 = Index(ch2);
    return compare[index1 - 1][index2 - 1];
}
//计算
double Calculate(char ch, double v1, double v2)
{
    double v;
    switch(ch)
    {
        case '+':
            v = v1 + v2;
            break;
        case '-':
            v = v1 - v2;
            break;
        case '*':
            v = v1 * v2;
            break;
        case '/':
            v = v1 / v2;
            break;
        default:
            break;
    }
    return v;
}
//得到表达式的值
double GetValue()
{
    int count = 0;  //用来将多为数字存入栈中
    char ch;
    opter.push('#');
    ch = getchar();
    while(!opter.empty())   //操作符不为空是执行循环
    {
        if(isdigit(ch)) //isdigit若字符是数字,返回非0值
        {
            if(count == 1)  //count是1,说明数字是连续的
            {
                double t = opval.top();    //将多位数字字符变为int型存放入栈中
                opval.pop();
                opval.push(t * 10 + ch - '0');
            }
            else    //数字第一次入栈或者数字是个位
            {
                opval.push(ch - '0');
                count = 1;
            }
            ch = getchar();
        }
        else    //字符是操作数
        {
            char c1, c2;
            double v1, v2;
            c1 = Compare(opter.top(), ch);
            switch(c1)
            {
                case '<':
                    opter.push(ch);
                    ch = getchar();
                    break;
                case '>':
                    c2 = opter.top();
                    opter.pop();
                    v2 = opval.top();
                    opval.pop();
                    v1 = opval.top();
                    opval.pop();
                    opval.push(Calculate(c2, v1, v2));
                    break;
                case '=':
                    opter.pop();
                    ch = getchar();
                    break;
                default:
                    cout << "输入有误,退出" << endl;
                    exit(0);
                    break;
            }
            count = 0;  //将其再次置位0
        }
    }
    return opval.top();
}
int main()
{
    int n;
    cout << "你想要输入几次表达式:";
    cin >> n;
    getchar();
    while(n--)
    {
        cout << GetValue() << endl;
        opval.pop();    //将最后一个值弹出
    }
    return 0;
}

运行结果:


查看评论

表达式求值算法总结

表达式求值算法表达式求值,一般采用栈和队列的方式来求值,下面介绍表达式求值的两种算法。方法一、使用两个栈,一个为操作符栈OPTR(operator),一个是操作数栈OPND(operand) 算法过...
  • honglicu123
  • honglicu123
  • 2016-09-18 16:00:14
  • 2374

经典算法-算术表达式求值

网上找了几个相关的代码 可惜不满足我的要求 修改如下 /**//*经典算法-算术表达式求值析用堆栈解析算术表达式的基本方法。给出的示例代码能解析任何包括+,-,*,/,()和0到9数字组成的算术表达式...
  • thecrazyboy
  • thecrazyboy
  • 2007-03-07 21:19:00
  • 15634

表达式求值算法

编写代码对算术表达式求值的经典方法由 Donald Knuth 描述于 1962 年(请参阅 参考资料)。Knuth 将此概括为三个步骤: 对中缀表达式进行语法分析中缀表达式到后缀表达式的转换对...
  • hewei0241
  • hewei0241
  • 2014-04-02 23:36:04
  • 2323

基于栈的算术表达式求值算法

  • 2013年12月22日 16:07
  • 81KB
  • 下载

C++实现任意表达式求值(栈)

今天花了大概四个小时时间,用栈(stack)实现了“任意表达式的值计算”的问题。 C++ 比 C 好的一点就是,C++ 的STL定义了大量的数据类型和算法,相比于 C 更加视觉化。 实现这个的基本思路...
  • flyfy1
  • flyfy1
  • 2010-02-16 10:51:00
  • 11612

使用逆波兰式进行表达式求值

中缀表达式及后缀表达式图解中说明了使用逆波兰式进行表达式求值的方法,这里使用C++进行实现。实现和原理讲解有一点不同,需要进一步进行细化。 关于将中缀表达式转换成后后缀表达式的规则: 规则:从左到...
  • u012501459
  • u012501459
  • 2015-08-13 23:12:39
  • 2908

【经典算法】-算术表达式求值

算术表达式求值 中缀表达式 我们平时写的计算式的式子一般是这样子 格式:"操作数1 操作符 操作数2" 12 * (3 + 4) - 6 + 8 / 2; // 中缀表达式 ...
  • dream_1996
  • dream_1996
  • 2017-09-28 18:20:37
  • 1020

一个支持函数,浮点数表达式求值算法

由于工作原因,需要写一个可以解析表达式的接口
  • ybxuwei
  • ybxuwei
  • 2014-08-31 18:38:01
  • 1399

数据结构 栈的应用——算术表达式求值

实验目的 : 1 .掌握栈的定义及实现; 2 .掌握利用栈求解算术表达式的方法。 实验内容: 通过修改完善教材中的算法3.4,利用栈来实现算术表达式求值的算法。对算法3.4中调用的几个函数...
  • yao1373446012
  • yao1373446012
  • 2016-10-07 10:51:04
  • 9495

表达式求值 算法 代码 报告 流程图

  • 2010年02月06日 10:45
  • 230KB
  • 下载
    个人资料
    持之以恒
    等级:
    访问量: 945
    积分: 197
    排名: 90万+
    文章存档
    最新评论