利用栈实现中缀表达式转前缀表达式
来源:互联网 发布:vmware os x 优化 编辑:程序博客网 时间:2024/04/29 09:45
前面既然写了中缀转后缀的,那么现在说下中缀转前缀的,至于后缀(前缀)转中缀,可以根据相关的转换规则自行转换。
目的
将中缀表达式(即标准的表达式)转换为前缀表达式
例如:1+2*3+(4*5+6)7 转换成 ++1*23+*4567
转换原则:
与中缀转后缀不同,前者是顺序从左到右读取每一个字符,后者是从右到左顺序读取每一个字符,然后进行反转字符串。
- 如果遇到操作数,直接将操作数放入到prefix 中
- 如果遇到操作符,如果符号栈为空,直接放入符号栈中,如果符号栈不为空,则判断当前栈顶元素
- 如果当前栈顶元素为右括号‘)’,直接将操作符放入符号栈中
- 如果当前栈顶元素的优先级大于操作数的优先级,则将栈顶元素移除,再次和判断移除后栈的栈顶元素比较优先级大小,直到当前栈顶元素小于或等于操作数优先级,将操作符放入符号栈中
- 如果遇到右括号,直接将右括号放入符号栈中
- 如果遇到左括号,将右括号到左括号之间的全部符号移出到prefix 中(记得左括号不要入栈,并且在最后将右括号从栈中删除)
- 重复1-4,直到最后一个字符被读入。
- 判断当前栈是否为空,如果不为空,将栈中的元素依次移出到prefix 中
- 翻转字符串
和中缀转后缀不同,进行优先级比较的时候,需要注意等号的问题
实例
首先,读入‘7’,并送到输出,然后‘*’被读入并压入栈中。接下来‘)’读入并送到栈中,此时状态如下:
栈:*)
输出:7
接下来读入‘6’,并送到输出,然后读入‘+’此时状态如下:
栈:* ) +
输出:7 6
然后读入‘5’,并送到输出,然后继续读入‘*’,由于‘*’的优先级比‘+’高,所以直接加入栈中,再将‘4’送到输出,因此状态如下:
栈:* ) + *
输出:7 6 5 4
下一个读入的符号‘(’,由于规则4,因此将符号栈中的操作符依次出栈,然后读入‘4’,并在最后将右括号弹出:
栈:*
输出: 7 6 5 4 * +
继续读入,此时读入‘+’,由优先级小于栈中‘*’的优先级,因此依照规则2,依次出栈,最后将‘+’入栈,接下来读入‘3’:
栈:+
输出:7 6 5 4 * + * 3
往后读入的符号是‘*’,将‘*’入栈。然后将‘2’放入输出:
栈:+ *
输出:7 6 5 4 * + * 3 2
现在读入‘+’,由于符号栈中存在‘+’且它们的优先级相同,根据规则,除非,优先级大于栈顶元素,否则不出栈,依次栈中状态如下:
栈:+ +
输出:7 6 5 4 * + * 3 2 *
下一个读入‘1’:
栈:+ +
输出:7 6 5 4 * + * 3 2 * 1
现在输入为空,弹出所有栈中元素
栈:空
输出:7 6 5 4 * + * 3 2 * 1 + +
最后翻转
输出:+ + 1 * 2 3 * + * 4 5 6 7
实现代码
/* 利用栈将(中缀表达式)转换成(前缀表达式) e.g. 1+2*3+(4*5+6)*7 转换成 ++1*23*+*4567 infix(中缀表达式) : 1+2*3+(4*5+6)*7 prefix(前缀表达式) : ++1*23*+*4567*/#include <algorithm>#include <iostream>#include <stack>#include <string>#include <map>using namespace std;void InfixToPrefix(const string infix, string& prefix){ stack<char> mark; // 符号栈 map<char, int> priority; // 符号优先级 priority['+'] = 0; priority['-'] = 0; priority['*'] = 1; priority['/'] = 1; int infix_length = infix.size(); // 中缀表达式的字符长度 prefix.reserve(infix_length); // 提高效率 for(int i = infix_length - 1; i >= 0; --i) { switch(infix[i]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': prefix.push_back(infix[i]); break; case '+': case '-': case '*': case '/': if(!mark.empty()) { char markTop = mark.top(); // 注意此处,与中缀转后缀有所不同 while(markTop != ')' && priority[infix[i]] < priority[markTop]) { prefix.push_back(markTop); mark.pop(); if(mark.empty()) { break; } markTop = mark.top(); } } mark.push(infix[i]); break; case ')': mark.push(infix[i]); break; case '(': { char markTop = mark.top(); while(markTop != ')') { prefix.push_back(markTop); mark.pop(); markTop = mark.top(); } mark.pop(); } break; } } // 剩余的全部出栈 while(!mark.empty()) { prefix.push_back(mark.top()); mark.pop(); } reverse(prefix.begin(), prefix.end());}int main(int argc, char const *argv[]){ std::string infix = "1+2*3+(4*5+6)*7"; std::string prefix; cout << "infix : " << infix << endl; InfixToPrefix(infix, prefix); cout << "prefix : " << prefix << endl; return 0;}
- 利用栈实现中缀表达式转前缀表达式
- 中缀转前缀表达式
- 中缀表达式转前缀表达式
- 中缀表达式转前缀表达式
- 中缀表达式转前缀表达式
- 利用栈实现中缀表达式转后缀表达式
- 利用栈实现中缀表达式转后缀表达式
- VS2015,C++实现前缀、中缀、后缀表达式求值、前缀转中缀、前缀转后缀。
- 前缀、中缀、后缀表达式(栈)
- [Python]中缀表达式转前缀表达式
- 中缀表达式转前缀和后缀表达式
- 前缀表达式、中缀表达式、后缀表达式及转换实现
- 【stack 实现前缀、后缀、中缀表达式运算】
- 中缀表达式求值、后缀表达式求值、中缀转后缀、前缀
- 中缀,前缀,后缀表达式
- 前缀、中缀、后缀表达式
- 前缀、中缀、后缀表达式
- 前缀、中缀、后缀表达式
- 0003-数据库设计问题与核心
- 本地资源图片和视频的使用
- Play框架文件上传
- 针对B/S、C/S架构的180个简单测试案例
- http server response 一览
- 利用栈实现中缀表达式转前缀表达式
- UITableView 做刷新或者分页时候出现的BUG
- Play框架的@OneToMany、@ManyToOne级联操作
- 2017--写在新年上班第一天
- hdu 1114 Piggy-Bank (完全背包)
- KVO 使用注意事项
- GitLab使用
- windows系统中显示文件的后缀名称方法
- 输出今年指定月份的日历