关闭

[置顶] 栈的应用——表达式求值

标签: 表达式求值
506人阅读 评论(0) 收藏 举报
分类:

概要

表达式求值问题可以说是一个经典问题。具体思路就是首先把输入的中缀表达式转换为后缀表达式,然后再根据后缀表达式进行计算求值。


中缀表达式转换为后缀表达式

首先我们设定运算符在进栈前与进栈后的优先级:
这里写图片描述

  1. 首先在栈把“#”进行压栈,并在中缀表达式追加“#”。“#”作为结束标志。
  2. 对中缀表达式进行遍历,遇到数字进行输出到后缀表达式中
  3. 如果遇到运算符,把栈顶的元素(前者)的栈内优先级与即将入栈元素(后者)的栈外优先级进行比较,如前者小,则运算符入栈,否则,则把栈顶元素(前者)出栈并输出到后缀表达式中,然后把后者入栈。
  4. 循环2,3两步直至中缀表达式的尾部的“#”。

后缀表达式求值

对后缀表达式进行遍历,如果是数字就入栈,如果是运算符,就连续出栈两次的结果进行保存,之后进行相应运算,把运算结果入栈,直至遍历结束,结果为栈顶元素。


下面是具体代码,但是为了减小码量,下面的程序对输入数字有如下要求:必须是0-9的数字,大于等于10不行,即如表达式:(1+(10-5)*2+2)/2是不合法的,10以上的数字不能出现。


#include <iostream>
#include <cstring>
#include <string>
using namespace std;

//这是把中缀表达式转化成后缀表达式的类 
class Transform{
    private:
        char* str;
        int top;
        int size;
    public:
        //表达式求值的构造函数 
        Transform(int size){
            this->size = size;
            str = new char[size];
            top = -1;
        }

        //栈是否为空的函数
        bool IsEmpty(){
            return top == -1;
        }

        //栈是否已满的函数
        bool IsFull(){
            return top == this->size-1;
        }

        //入栈函数
        void Push(char ch){
            if(!this->IsFull()){
                this->str[++top] = ch;  
            }
        }

        //获得栈顶元素 
        char Top(){
            return this->str[top];
        }

        //出栈函数
        void Pop(){
            this->top--;
        } 

        //栈外运算符优先级 
        int icp(char ch){
            int result = 0;
            if(ch == '#'){
                result = 0;
            }
            if(ch == '('){
                result = 6;
            }
            if(ch == '*'||ch == '/'){
                result = 4;
            }
            if(ch == '+'||ch == '-'){
                result = 2;
            }   
            if(ch == ')'){
                result = 1;
            }
            return result;      
        }

        //栈内运算符优先级 
        int isp(char ch){
            int result = 0;
            if(ch == '#'){
                result = 0;
            }
            if(ch == '('){
                result = 1;
            }
            if(ch == '*'||ch == '/'){
                result = 5;
            }
            if(ch == '+'||ch == '-'){
                result = 3;
            }   
            if(ch == ')'){
                result = 6;
            }
            return result;      
        }

        //中缀表达式转为后缀表达式函数
        string Transform_Median(string median){
            //在中缀表达式和栈中追加"#"表示结束 
            median.append("#"); 
            this->Push('#');
            char* c;
            int cnt = 0;
            char* tmp;
            c = new char[median.length()];
            tmp = new char[median.length()];            //后缀表达式的暂存数组 
            strcpy(c,median.c_str());
            for(int i = 0 ; i < median.length() ; i++){
                //如果是数字直接输出到后缀表达式中 
                if(c[i] >= '0' && c[i] <= '9'){
                    tmp[cnt++] = c[i];
                }else{
                    //如果不是数字,则需要和栈顶元素比较运算符优先级 
                    char ch = this->Top();
                    //栈顶元素在栈内的优先级比栈外元素的优先级高,则栈外元素入栈 
                    if(this->isp(ch) < this->icp(c[i])){
                        this->Push(c[i]); 
                    }else if(this->isp(ch) > this->icp(c[i])){
                        //栈顶元素在栈内的优先级比栈外元素的优先级低
                        //则栈内元素出栈,并输出到后缀表达式中,循环变量减1 
                        tmp[cnt++] = ch;
                        this->Pop();
                        i--;
                    }else{
                        //栈顶元素在栈内的优先级等于栈外元素的优先级
                        //说明已经运行到“#”,则出栈即可 
                        this->Pop();    
                    }
                }
            }
            //返回中缀表达式的字符串 
            string after = string(tmp,cnt);
            return after;
        }   
}; 

//这是后缀表达式计算类 
class Sum{
    private:
        int* sum;
        int top;
        int size;
    public:
        //表达式求值的构造函数 
        Sum(int size){
            this->size = size;
            sum = new int[size];
            top = -1;
        }

        //栈是否为空的函数
        bool IsEmpty(){
            return top == -1;
        }

        //栈是否已满的函数
        bool IsFull(){
            return top == this->size-1;
        }

        //入栈函数
        void Push(int num){
            if(!this->IsFull()){
                this->sum[++top] = num; 
            }
        }

        //获得栈顶元素 
        int Top(){
            return this->sum[top];
        }

        //出栈函数
        void Pop(){
            this->top--;
        } 

        //后缀表达式求和
        int Sum_After(string after){
            char* s;
            s = new char[after.length()];
            strcpy(s,after.c_str());
            for(int i = 0 ; i < after.length() ; i++){
                if(s[i] >= '0' && s[i] <= '9'){
                    this->Push(s[i]-'0');
                }else{
                    int b = this->Top();
                    this->Pop();
                    int a = this->Top();
                    this->Pop();
                    int result = 0;
                    switch(s[i]){
                        case '+': result = a + b ;break;
                        case '-': result = a - b ;break;
                        case '*': result = a * b ;break;
                        case '/': result = a / b ;break;
                    };
                    this->Push(result);
                }
            }
            return this->Top();
        } 
};


int main()
{
    string median;
    cout<<"请输入中缀表达式:"<<endl;
    cin>>median;
    Transform transform(median.length());
    string after = transform.Transform_Median(median);
    cout<<"后缀表达式为:"<<endl<<after<<endl;
    Sum sum(after.length()); 
    int result = sum.Sum_After(after);
    cout<<"结果为:"<<endl<<result<<endl; 

    return 0;
 } 

这里写图片描述

1
0
查看评论

栈的应用之算术表达式求值

栈是一种后进先出的数据结构。表达式求值是对栈的一个典型的应用。 对于如下一个表达式: 1 + 2 * (3 + 4) 此算术表达式由一些操作符和操作数组成。其中,操作符有‘+’、‘*’、‘(’等,操作数有‘1’、‘2’、‘3’等。对于操作符来说,其运算是有优先级的。比如,上述表达式中,3+...
  • zjdnwpu
  • zjdnwpu
  • 2016-04-28 22:12
  • 3909

栈的应用之表达式求值(算符优先法)

为了简化问题,我们只考虑+、-、*、/四种运算,他们的优先级规则: (1)先乘除,后加减 (2)从左算到右 (3)先括号内,再括号外为了实现算符优先算法,需要两个工作栈,一个用来存放操作数(CZS),一个用来存放运算符(YSF)。 算法的基本思想: (1)首先置操作数栈、运算符栈均为空,将...
  • qianchangdiyin
  • qianchangdiyin
  • 2015-10-30 16:11
  • 688

栈的应用:四则运算表达式求值

栈的一个应用就是四则运算表达式的求值,
  • lub0807
  • lub0807
  • 2014-07-17 20:08
  • 2052

使用栈实现表达式求值

任何一个表达式都是由操作数,运算符,界限符组成的。操作数即是参加运算的数值或者变量,运算符则是加减乘除等组成,为简单起见,这里只实现加减乘除的运算,而常见的界限符则是左右括号和终止符。在运算过程中,要判断两个先后出现的运算符之间的优先顺序。 为了实现算法,设置两个工作栈:用于存储运算符的栈opter...
  • BestFSQ
  • BestFSQ
  • 2017-02-19 21:54
  • 4912

栈的应用——四则表达式求值

栈的应用有很多,四则运算是一个比较常见的应用。对于四则运算,括号内的要先运算,而且还要先乘除后加减,又要涉及到负数和浮点数,看上去简简单单的式子,其实暗藏杀机。        常用的方法是利用后缀表达式(逆波兰)进行计算。主要分为两步:   ...
  • hcx25909
  • hcx25909
  • 2014-07-15 15:31
  • 5131

使用栈解决表达式求值(C语言)及问题总结

一、理论知识 表达式=(操作数)+(运算符)+(操作数)设 Exp = S1+OP+S2则称OP+S1+S2为前缀表示法 S1+OP+S2为中缀表示法         S1+S2+OP为后缀表示法 例如:Exp = a ...
  • F__shigang
  • F__shigang
  • 2017-03-15 13:14
  • 1253

栈的应用——表达式求值

概要表达式求值问题可以说是一个经典问题。具体思路就是首先把输入的中缀表达式转换为后缀表达式,然后再根据后缀表达式进行计算求值。中缀表达式转换为后缀表达式首先我们设定运算符在进栈前与进栈后的优先级: 首先在栈把“#”进行压栈,并在中缀表达式追加“#”。“#”作为结束标志。 对中缀表达式进行遍历,遇到数...
  • qq_30091945
  • qq_30091945
  • 2017-08-23 16:55
  • 506

栈的应用之表达式求值

#include #include #include #include #include #include #include typedef int SElemType; #define OK 1 #define ERROR 0 #define FALSE 0 //#define OVERFL...
  • dh0144298
  • dh0144298
  • 2015-11-22 22:52
  • 258

数据结构Java实现——①栈-->栈的应用三、算术表达式求值

当一个算术表达式中含有多个运算符,且运算符的优先级不同的情况下,如何才能处理一个算术表达式????? 2、思路 首先我们要知道表达式分为三类: ①中缀表达式:a+(b-c/d)*e ②前缀表达式+a*-b/cde ③后缀表达式abcd/-e*+ 由于运算符有优先级,所以在计算机中计算一...
  • u011446177
  • u011446177
  • 2015-01-04 12:44
  • 2945

用java编写栈的经典应用-表达式求值

表达式求值是程序设计编程中的基本问题也是栈的经典应用,这里使用的是书上的方法,也是最广为流传的方法“算符优先法”      所谓算符优先就是算术运算中不同运算符有不同的计算优先级,所以需要使用一个算符优先表来确定计算顺序。下面代码中有算符优先表,这里就不写了...
  • tianchaixiaoniuniu
  • tianchaixiaoniuniu
  • 2017-05-25 14:44
  • 439
    个人资料
    • 访问:155742次
    • 积分:4932
    • 等级:
    • 排名:第6843名
    • 原创:329篇
    • 转载:0篇
    • 译文:0篇
    • 评论:81条
    博客专栏
    最新评论