简体   繁体   中英

Shunting Yard Algorithm C++

I have written an attempt at Dijkstra's Shunting Yard Algorithm as part of a college project. 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* .

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:

  1. Push '(' onto the operators stack.
  2. Push 'a' onto the operands stack, and append 'a' to your postfix expression.
  3. Push '+' onto the operators stack.
  4. Push 'b' onto the operands stack, and append 'b' to your postfix expression.
  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.
  6. Push '*' to the operators stack.
  7. Push 'c' to the operands stack, and append to your postfix expression.
  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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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