简体   繁体   English

Shunting Yard算法C ++

[英]Shunting Yard Algorithm C++

I have written an attempt at Dijkstra's Shunting Yard Algorithm as part of a college project. 我曾尝试将Dijkstra的Shunting Yard算法作为大学项目的一部分。 All is working as expected but I am also required to show how the operators are sequenced after the process and I'm not sure how to do this, I believe the best way to do this is a Queue? 一切都按预期工作,但我也需要显示操作符在进程后如何排序,我不知道如何做到这一点,我相信最好的方法是队列? Does anyone have an idea of how this can be done? 有没有人知道如何做到这一点? My Code: 我的代码:

// Finding operators 
int operators(char op){ 
    if(op == '+'||op == '-') 
    return 1; 
    if(op == '*'||op == '/') 
    return 2; 
    return 0; 
} 

// The maths
int maths(int a, int b, char op){ 
    switch(op){ 
        case '+': return a + b; 
        case '-': return a - b; 
        case '*': return a * b; 
        case '/': return a / b; 
    } 
  return 0;
} 

// Returning value of expression
int evaluate(string tokens){ 
    int i; 

    // stack to store integers and operators. 
    stack <int> numbers;  
    stack <char> ops; 

    for(i = 0; i < tokens.length(); i++){ 

        // if token blank, skip 
        if(tokens[i] == ' ') 
            continue; 

        // if token '(' add to stack
        else if(tokens[i] == '('){ 
            ops.push(tokens[i]); 
        } 

        // if token is a number, add to stack
        else if(isdigit(tokens[i])){ 
            int val = 0; 

            // single or double digit number.
            while(i < tokens.length() && 
                        isdigit(tokens[i])) 
            { 
                val = (val*10) + (tokens[i]-'0'); 
                i++; 
            } 

            numbers.push(val); 
        } 

        // if token ')', solve entire brace. 
        else if(tokens[i] == ')') 
        { 
            while(!ops.empty() && ops.top() != '(') 
            { 
                int val2 = numbers.top(); 
                numbers.pop(); 

                int val1 = numbers.top(); 
                numbers.pop(); 

                char op = ops.top(); 
                ops.pop(); 

                numbers.push(maths(val1, val2, op)); 
            } 

            // pop opening brace. 
            ops.pop(); 
        } 

        // Current token is an operator. 
        else
        { 

            while(!ops.empty() && operators(ops.top()) 
                                >= operators(tokens[i])){ 
                int val2 = numbers.top(); 
                numbers.pop(); 

                int val1 = numbers.top(); 
                numbers.pop(); 

                char op = ops.top(); 
                ops.pop(); 

                numbers.push(maths(val1, val2, op)); 
            } 

            // Push current token to 'ops'. 
            ops.push(tokens[i]); 
        } 
    } 

    //Do remaining operations 
    while(!ops.empty()){ 
        int val2 = numbers.top(); 
        numbers.pop(); 

        int val1 = numbers.top(); 
        numbers.pop(); 

        char op = ops.top(); 
        ops.pop(); 

        numbers.push(maths(val1, val2, op)); 
    } 

    // Top of 'numbers' contains result, return
    return numbers.top(); 
} 

int main() { 
    cout << evaluate("10 + 10 * 10") << "\n"; 
    cout << evaluate("3 + 4 * 2 + ( 23 - 5 )") << "\n"; 
    cout << evaluate("100 * ( 2 + 12 )") << "\n"; 
    cout << evaluate("100 * ( 5 + 8 ) / 7") << "\n"; 
    return 0; 
}  

Consider that a postfix expression shows unambiguously the evaluation order. 考虑后缀表达式明确显示评估顺序。 For example, the infix expression a+b*c becomes abc*+ , and (a+b)*c becomes ab+c* . 例如,中缀表达式a+b*c变为abc*+ ,并且(a+b)*c变为ab+c*

If you follow the expression evaluation of your code, you'll see that the order of evaluation can be represented by a postfix expression. 如果您遵循代码的表达式评估,您将看到评估的顺序可以由后缀表达式表示。

You can modify your code to output a postfix expression at the same time it's evaluating. 您可以修改代码以在评估的同时输出后缀表达式。 The basic idea is that whenever you push an operand (a number), you also append it to your postfix expression. 基本思想是每当你按下一个操作数(一个数字),你也可以将它附加到你的后缀表达式。 And whenever you perform an operation, you append the operator to the postfix expression. 每当执行操作时,都会将操作符附加到后缀表达式。 Parentheses, of course, are never added to the postfix. 当然,括号永远不会添加到后缀中。

So when you're evaluating (a+b)*c , you do the following: 因此,当您评估(a+b)*c ,请执行以下操作:

  1. Push '(' onto the operators stack. 将'('推到运算符堆栈上。
  2. Push 'a' onto the operands stack, and append 'a' to your postfix expression. 将'a'推入操作数堆栈,并在后缀表达式中附加'a'。
  3. Push '+' onto the operators stack. 将“+”推入运算符堆栈。
  4. Push 'b' onto the operands stack, and append 'b' to your postfix expression. 将'b'推入操作数堆栈,并将'b'追加到后缀表达式中。
  5. You encounter ')'. 你遇到')'。 Pop '+' from the operators stack and append to your postfix expression. 从运算符堆栈弹出'+'并附加到您的后缀表达式。 Pop 'a' and 'b' from the operands stack, perform the operation, and push the result back to the operators stack. 从操作数堆栈中弹出“a”和“b”,执行操作,并将结果推回到运算符堆栈。
  6. Push '*' to the operators stack. 将'*'推送到运算符堆栈。
  7. Push 'c' to the operands stack, and append to your postfix expression. 将“c”按到操作数堆栈,然后附加到后缀表达式。
  8. You're at the end of the expression. 你在表达的最后。 Pop '*' from the operators stack, append to postfix expression, pop operands and evaluate. 从运算符堆栈弹出'*',附加到后缀表达式,弹出操作数和求值。

You should be able to make these changes pretty easily in your code. 您应该能够在代码中轻松地进行这些更改。 Whenever you call numbers.push() , also append the number to your postfix expression. 无论何时调用numbers.push() ,还要将数字附加到后缀表达式。 Whenever you call ops.pop() to remove an operator (not a '('), append the popped operator to your postfix expression. When you've completed the evaluation, output the postfix expression. 每当你调用ops.pop()来删除一个运算符(而不是'('))时,将弹出的运算符追加到你的后缀表达式。当你完成评估后,输出后缀表达式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM