标签:出栈 中缀转后缀 编码 out flag ref 中缀 pre turn
如 1-10(10-10)-12,输出对应的结果
这是一条比较常规的栈的题目,将中缀表达式转换为后缀,在编码过程中,有几个点犯了错误
1、中缀转后缀时,运算符要和stack栈顶的优先级判断,如果优先级小于或等于栈顶,要把栈顶出栈
2、负号的判断,只有前面是括号或者是运算符,才可能是括号,尽可能采用正向判断,避免错误,我最开始判断是前一个不是数字,前一个不是数字,也有可能是右括号或运算符
#include <iostream>
#include <cstdio>
#include <stack>
#include <vector>
#include <string>
using namespace std;
#define is_digit(x) (x>='0' && x<='9')
#define is_right(x) (x==')' || x==']' || x== '}')
#define is_left(x) (x=='(' || x=='[' || x== '{')
struct Item {
int type;
int val;
char op;
};
bool is_oper_high(char a, char b)
{
int pri_a;
int pri_b;
if(a == '+' || a == '-') {
pri_a = 0;
} else {
pri_a = 1;
}
if(b == '+' || b == '-') {
pri_b = 0;
} else {
pri_b = 1;
}
return pri_a >= pri_b;
}
int do_op(int a, int b, char c)
{
if(c == '+') {
return a+b;
} else if(c == '-') {
return a-b;
} else if(c == '*') {
return a*b;
} else {
return a/b;
}
}
int get_width(int val)
{
int s = 0;
if(val == 0) {
return 1;
} else if(val < 0) {
val = 0 - val;
}
while(val != 0) {
val /= 10;
s++;
}
return s;
}
int calc(string &mid_prefix)
{
int sum = 0;
char c = 0;
struct Item item;
int neg_flag = 0;
int pos = 0;
int val;
vector <struct Item> post_prefix;
stack <char> oper_stack;
while(pos < mid_prefix.size()) {
c = mid_prefix[pos];
/*判断负数*/
if(c == '-' && is_left(mid_prefix[pos-1])) {
sscanf(mid_prefix.substr(pos).c_str(), "%d", &val);
item.type = 0;
item.val = val;
post_prefix.push_back(item);
pos += get_width(val) + 1;
} else {
if(is_digit(c)) {
sscanf(mid_prefix.substr(pos).c_str(), "%d", &val);
item.type = 0;
item.val = val;
post_prefix.push_back(item);
pos += get_width(val);
} else {
if(!is_right(c)) {
if(is_left(c)) {
oper_stack.push('(');
} else {
/*判断当前字符和栈顶的优先级,弹出优先级高的元素,或者到(截止*/
while(!oper_stack.empty() && oper_stack.top() != '(' && is_oper_high(oper_stack.top(), c)) {
item.type = 1;
item.op = oper_stack.top();
post_prefix.push_back(item);
oper_stack.pop();
}
oper_stack.push(c);
}
} else {
/*出栈*/
while(oper_stack.top() != '(') {
item.type = 1;
item.op = oper_stack.top();
post_prefix.push_back(item);
oper_stack.pop();
}
oper_stack.pop();
}
pos++;
}
}
}
/*操作符出栈*/
while(!oper_stack.empty()) {
item.type = 1;
item.op = oper_stack.top();
post_prefix.push_back(item);
oper_stack.pop();
}
/*
for(int i = 0; i<post_prefix.size(); i++) {
if(post_prefix[i].type == 0) {
cout << post_prefix[i].val << " ";
} else {
cout << post_prefix[i].op << " ";
}
}
cout << endl;
*/
/*后缀表达式计算*/
stack <int> num_stack;
for(int i=0; i<post_prefix.size(); i++) {
if(post_prefix[i].type == 0) {
num_stack.push(post_prefix[i].val);
} else {
int a = num_stack.top();
num_stack.pop();
int b = num_stack.top();
num_stack.pop();
/*do op*/
sum = do_op(b, a, post_prefix[i].op);
num_stack.push(sum);
}
}
return sum;
}
int main(void)
{
string mid_prefix;
while(cin >> mid_prefix) {
cout << calc(mid_prefix) << endl;
}
return 0;
}
标签:出栈 中缀转后缀 编码 out flag ref 中缀 pre turn
原文地址:https://www.cnblogs.com/joechow/p/12316183.html