您的位置:首页 > 其它

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

2017-05-02 16:56 176 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: