利用栈实现中缀表达式转前缀表达式

来源:互联网 发布:vmware os x 优化 编辑:程序博客网 时间:2024/04/29 09:45

前面既然写了中缀转后缀的,那么现在说下中缀转前缀的,至于后缀(前缀)转中缀,可以根据相关的转换规则自行转换。

目的

将中缀表达式(即标准的表达式)转换为前缀表达式

例如:1+2*3+(4*5+6)7 转换成 ++1*23+*4567

转换原则:

与中缀转后缀不同,前者是顺序从左到右读取每一个字符,后者是从右到左顺序读取每一个字符,然后进行反转字符串。

  1. 如果遇到操作数,直接将操作数放入到prefix
  2. 如果遇到操作符,如果符号栈为空,直接放入符号栈中,如果符号栈不为空,则判断当前栈顶元素
    • 如果当前栈顶元素为右括号‘)’,直接将操作符放入符号栈中
    • 如果当前栈顶元素的优先级大于操作数的优先级,则将栈顶元素移除,再次和判断移除后栈的栈顶元素比较优先级大小,直到当前栈顶元素小于或等于操作数优先级,将操作符放入符号栈中
  3. 如果遇到右括号,直接将右括号放入符号栈中
  4. 如果遇到左括号,将右括号到左括号之间的全部符号移出到prefix 中(记得左括号不要入栈,并且在最后将右括号从栈中删除)
  5. 重复1-4,直到最后一个字符被读入。
  6. 判断当前栈是否为空,如果不为空,将栈中的元素依次移出到prefix
  7. 翻转字符串

和中缀转后缀不同,进行优先级比较的时候,需要注意等号的问题

实例

首先,读入‘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;}
0 0
原创粉丝点击