表达式树---中缀表达式变逆波兰表达式

http://dsalgo.openjudge.cn/binarytree/7/
部分算法, 打印树的内容今后有机会再补上

总时间限制: 1000ms 内存限制: 65535kB
描述
众所周知,任何一个表达式,都可以用一棵表达式树来表示。例如,表达式a+b*c,可以表示为如下的表达式树:

+
/ \
a *
/ \
b c

现在,给你一个中缀表达式,这个中缀表达式用变量来表示(不含数字),请你将这个中缀表达式用表达式二叉树的形式输出出来。

输入
输入分为三个部分。
第一部分为一行,即中缀表达式(长度不大于50)。中缀表达式可能含有小写字母代表变量(a-z),也可能含有运算符(+、-、*、/、小括号),不含有数字,也不含有空格。
第二部分为一个整数n(n < 10),表示中缀表达式的变量数。
第三部分有n行,每行格式为C x,C为变量的字符,x为该变量的值。
输出
输出分为三个部分,第一个部分为该表达式的逆波兰式,即该表达式树的后根遍历结果。占一行。
第二部分为表达式树的显示,如样例输出所示。如果该二叉树是一棵满二叉树,则最底部的叶子结点,分别占据横坐标的第1、3、5、7……个位置(最左边的坐标是1),然后它们的父结点的横坐标,在两个子结点的中间。如果不是满二叉树,则没有结点的地方,用空格填充(但请略去所有的行末空格)。每一行父结点与子结点中隔开一行,用斜杠(/)与反斜杠(\)来表示树的关系。/出现的横坐标位置为父结点的横坐标偏左一格,\出现的横坐标位置为父结点的横坐标偏右一格。也就是说,如果树高为m,则输出就有2m-1行。
第三部分为一个整数,表示将值代入变量之后,该中缀表达式的值。需要注意的一点是,除法代表整除运算,即舍弃小数点后的部分。同时,测试数据保证不会出现除以0的现象。
样例输入

这里写图片描述

样例输出
这里写图片描述

思路:
(1) 用两个栈来做临时存放器: s1 存放操作的项,s2存放运算符号
(2) 存放的规则如下:
遇到字母,直接放进s1
遇到运算符,判断: 如果是+或-,用last=s2.top()来操作 s1顶的两项
如果是* 或 %,判断last = s2.top():
如果last 是 + 或-, 把运算符放进s2, 并进行下一步操作
(3) 处理括号: 左括号放进s2, 等待右括号。 遇到右括号,把s2中做括号之前的所有运算符操作完
(4) 存放完后的后续操作: 存放完表达式,s1、s2中肯定还剩下内容,需要完成剩余内容的收尾
(5) 计算表达式的值:在node 的struct中就需要设置一个int sum, 来记录计算结果。在处理表达式的每一步都把sum计算出来,最终输出root的sum, 就是整个表达式的计算结果。


#include <iostream>
#include <stack>

using namespace std;
char suanshi[50];
int val_num[200];
int sum=0;

struct node{
public:
    char val;
    int sum;
    node* zuo, * you;
};
stack<node*> s1,s2; // s1储存项, s2储存运算符号
node * root;

int calculate ( char suan, int s1, int s2){

    if (suan=='+') return s1+s2;
    else if (suan == '-') return s1-s2;
    else if (suan == '*') return s1*s2;
    else return s1/s2;
}

void clear_end(){

    while (!s2.empty()){


        int sum1, sum2;
        node* temp = s2.top(); s2.pop();

        sum2 = s1.top()->sum;
        temp->you = s1.top(); s1.pop();

        sum1 = s1.top()->sum;
        temp->zuo = s1.top(); s1.pop();

        temp->sum = calculate(temp->val, sum1, sum2);

        s1.push(temp);
    }

    root =  s1.top();
    //cout<<root->val<<endl;
}
void push_back_bracket(){
    while(s2.top()->val!= '('){

        int sum1, sum2;
        node* last = s2.top(); s2.pop();

        sum2 = s1.top()->sum;
        last->you = s1.top(); s1.pop();

        sum1 = s1.top()->sum;
        last->zuo = s1.top(); s1.pop();

        last->sum = calculate(last->val, sum1, sum2);

        s1.push(last);
    }
    s2.pop();
}


void push_suanshi(node* tmp_node){

    int sum1, sum2;

    if (!s2.empty() && s2.top()->val!='('){
        node* last = s2.top();
        s2.pop();

        char tmp = tmp_node->val;

        if (tmp=='*' || tmp == '/'){ // 如果tmp运算符号是*或/

            if (last->val=='*' || last->val =='/'){

                sum2 = s1.top()->sum;
                last->you = s1.top(); s1.pop();

                sum1 = s1.top()->sum;
                last->zuo = s1.top(); s1.pop();

                last->sum = calculate(last->val, sum1, sum2);
                s1.push(last);
                s2.push(tmp_node);
            }


            else if (last->val=='+' || last->val=='-'){

                s2.push(last); s2.push(tmp_node);
            }
        }

        else if (tmp=='+' || tmp=='-'){ // 如果tmp是+或-,把last计算掉

            sum2 = s1.top()->sum;
            last->you = s1.top(); s1.pop();

            sum1 = s1.top()->sum;
            last->zuo = s1.top(); s1.pop();
            last->sum = calculate(last->val, sum1, sum2);

            s1.push(last);
            s2.push(tmp_node);
        }
    }
    else s2.push(tmp_node);
}

void print_tree(node * root){

    if (root == NULL) return;
    print_tree(root->zuo);
    print_tree(root->you);
    cout<<root->val;
}
int main() {

    cin>>suanshi;

    int n;
    char val;
    int num;
    cin>>n;

    for (int i=0; i<n; i++){
        cin>>val>>num;
        val_num[(int)val] = num;
        //cout<<val_num[(int)val] <<endl;

    }

    int length=(int)strlen(suanshi);

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

        char tmp= suanshi[i];

        node* tmp_node = new node;
        tmp_node->val = tmp;
        tmp_node->zuo = tmp_node->you = NULL;

        if (tmp=='*' || tmp == '/' || tmp=='+' || tmp =='-')
            push_suanshi(tmp_node);


        else if (tmp=='(')  s2.push(tmp_node);
        else if (tmp==')')
            push_back_bracket();

        else {
            tmp_node->sum = val_num[(int)tmp];
            //cout<<tmp_node->val << " "<<tmp_node->sum<<endl;
            s1.push(tmp_node);}

    }

    clear_end();

    print_tree(root);
    cout<<endl;

    cout<<root->sum<<endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值