前面既然写了中缀转后缀的,那么现在说下中缀转前缀的,至于后缀(前缀)转中缀,可以根据相关的转换规则自行转换。
目的
将中缀表达式(即标准的表达式)转换为前缀表达式
例如: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;
}