📜  堆栈 |第 2 组(中缀到后缀)

📅  最后修改于: 2022-05-13 01:57:09.289000             🧑  作者: Mango

堆栈 |第 2 组(中缀到后缀)

先决条件 - 堆栈 |第 1 套(介绍)
缀表达式:形式 a op b 的表达式。当运算符位于每对操作数之间时。
后缀表达式: ab op 形式的表达式。当每对操作数都遵循一个运算符时。
为什么用后缀表示表达式?
编译器从左到右或从右到左扫描表达式。
考虑以下表达式: a op1 b op2 c op3 d
如果 op1 = +,op2 = *,op3 = +
编译器首先扫描表达式以计算表达式 b * c,然后再次扫描表达式以将 a 添加到它。然后在另一次扫描后将结果添加到 d 中。
重复扫描使其效率非常低。最好在评估之前将表达式转换为后缀(或前缀)形式。
后缀形式的对应表达式为 abc*+d+。可以使用堆栈轻松评估后缀表达式。我们将在另一篇文章中介绍后缀表达式评估。
算法
1.从左到右扫描中缀表达式。
2.如果扫描到的字符是操作数,则输出。
3.否则,
1如果扫描的运算符的优先级大于堆栈中运算符的优先级(或堆栈为空或堆栈包含'('),则将其压入。
2否则,从堆栈中弹出所有大于或等于优先于扫描运算符的运算符符。之后将扫描的运算符推入堆栈。 (如果在弹出时遇到括号,则停在那里并将扫描的运算符压入堆栈。)
4.如果扫描到的字符是'(',则将其压入堆栈。
5 、如果扫描到的字符是')',则出栈并输出,直到遇到'(',同时丢弃两个括号。
6.重复步骤 2-6,直到扫描到中缀表达式。
7.打印输出
8.从栈中弹出并输出,直到不为空。

以下是上述算法的实现

C++
/* C++ implementation to convert
infix expression to postfix*/
 
#include
using namespace std;
 
//Function to return precedence of operators
int prec(char c) {
    if(c == '^')
        return 3;
    else if(c == '/' || c=='*')
        return 2;
    else if(c == '+' || c == '-')
        return 1;
    else
        return -1;
}
 
// The main function to convert infix expression
//to postfix expression
void infixToPostfix(string s) {
 
    stack st; //For stack operations, we are using C++ built in stack
    string result;
 
    for(int i = 0; i < s.length(); i++) {
        char c = s[i];
 
        // If the scanned character is
        // an operand, add it to output string.
        if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
            result += c;
 
        // If the scanned character is an
        // ‘(‘, push it to the stack.
        else if(c == '(')
            st.push('(');
 
        // If the scanned character is an ‘)’,
        // pop and to output string from the stack
        // until an ‘(‘ is encountered.
        else if(c == ')') {
            while(st.top() != '(')
            {
                result += st.top();
                st.pop();
            }
            st.pop();
        }
 
        //If an operator is scanned
        else {
            while(!st.empty() && prec(s[i]) <= prec(st.top())) {
                result += st.top();
                st.pop(); 
            }
            st.push(c);
        }
    }
 
    // Pop all the remaining elements from the stack
    while(!st.empty()) {
        result += st.top();
        st.pop();
    }
 
    cout << result << endl;
}
 
//Driver program to test above functions
int main() {
    string exp = "a+b*(c^d-e)^(f+g*h)-i";
    infixToPostfix(exp);
    return 0;
}


C
// C program to convert infix expression to postfix
#include 
#include 
#include 
 
// Stack type
struct Stack
{
    int top;
    unsigned capacity;
    int* array;
};
 
// Stack Operations
struct Stack* createStack( unsigned capacity )
{
    struct Stack* stack = (struct Stack*)
           malloc(sizeof(struct Stack));
 
    if (!stack)
        return NULL;
 
    stack->top = -1;
    stack->capacity = capacity;
 
    stack->array = (int*) malloc(stack->capacity *
                                   sizeof(int));
 
    return stack;
}
int isEmpty(struct Stack* stack)
{
    return stack->top == -1 ;
}
char peek(struct Stack* stack)
{
    return stack->array[stack->top];
}
char pop(struct Stack* stack)
{
    if (!isEmpty(stack))
        return stack->array[stack->top--] ;
    return '$';
}
void push(struct Stack* stack, char op)
{
    stack->array[++stack->top] = op;
}
 
 
// A utility function to check if
// the given character is operand
int isOperand(char ch)
{
    return (ch >= 'a' && ch <= 'z') ||
           (ch >= 'A' && ch <= 'Z');
}
 
// A utility function to return
// precedence of a given operator
// Higher returned value means
// higher precedence
int Prec(char ch)
{
    switch (ch)
    {
    case '+':
    case '-':
        return 1;
 
    case '*':
    case '/':
        return 2;
 
    case '^':
        return 3;
    }
    return -1;
}
 
 
// The main function that
// converts given infix expression
// to postfix expression.
int infixToPostfix(char* exp)
{
    int i, k;
 
    // Create a stack of capacity
    // equal to expression size
    struct Stack* stack = createStack(strlen(exp));
    if(!stack) // See if stack was created successfully
        return -1 ;
 
    for (i = 0, k = -1; exp[i]; ++i)
    {
         
        // If the scanned character is
        // an operand, add it to output.
        if (isOperand(exp[i]))
            exp[++k] = exp[i];
         
        // If the scanned character is an
        // ‘(‘, push it to the stack.
        else if (exp[i] == '(')
            push(stack, exp[i]);
         
        // If the scanned character is an ‘)’,
        // pop and output from the stack
        // until an ‘(‘ is encountered.
        else if (exp[i] == ')')
        {
            while (!isEmpty(stack) && peek(stack) != '(')
                exp[++k] = pop(stack);
            if (!isEmpty(stack) && peek(stack) != '(')
                return -1; // invalid expression            
            else
                pop(stack);
        }
        else // an operator is encountered
        {
            while (!isEmpty(stack) &&
                 Prec(exp[i]) <= Prec(peek(stack)))
                exp[++k] = pop(stack);
            push(stack, exp[i]);
        }
 
    }
 
    // pop all the operators from the stack
    while (!isEmpty(stack))
        exp[++k] = pop(stack );
 
    exp[++k] = '\0';
    printf( "%s", exp );
}
 
// Driver program to test above functions
int main()
{
    char exp[] = "a+b*(c^d-e)^(f+g*h)-i";
    infixToPostfix(exp);
    return 0;
}


Java
/* Java implementation to convert
 infix expression to postfix*/
// Note that here we use Stack class for Stack operations
 
import java.util.Stack;
 
class Test
{
     
    // A utility function to return
    // precedence of a given operator
    // Higher returned value means
    // higher precedence
    static int Prec(char ch)
    {
        switch (ch)
        {
        case '+':
        case '-':
            return 1;
      
        case '*':
        case '/':
            return 2;
      
        case '^':
            return 3;
        }
        return -1;
    }
      
    // The main method that converts
    // given infix expression
    // to postfix expression.
    static String infixToPostfix(String exp)
    {
        // initializing empty String for result
        String result = new String("");
         
        // initializing empty stack
        Stack stack = new Stack<>();
         
        for (int i = 0; i


Python
# Python program to convert infix expression to postfix
 
# Class to convert the expression
 
 
class Conversion:
 
    # Constructor to initialize the class variables
    def __init__(self, capacity):
        self.top = -1
        self.capacity = capacity
        # This array is used a stack
        self.array = []
        # Precedence setting
        self.output = []
        self.precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3}
 
    # check if the stack is empty
    def isEmpty(self):
        return True if self.top == -1 else False
 
    # Return the value of the top of the stack
    def peek(self):
        return self.array[-1]
 
    # Pop the element from the stack
    def pop(self):
        if not self.isEmpty():
            self.top -= 1
            return self.array.pop()
        else:
            return "$"
 
    # Push the element to the stack
    def push(self, op):
        self.top += 1
        self.array.append(op)
 
    # A utility function to check is the given character
    # is operand
    def isOperand(self, ch):
        return ch.isalpha()
 
    # Check if the precedence of operator is strictly
    # less than top of stack or not
    def notGreater(self, i):
        try:
            a = self.precedence[i]
            b = self.precedence[self.peek()]
            return True if a <= b else False
        except KeyError:
            return False
 
    # The main function that
    # converts given infix expression
    # to postfix expression
    def infixToPostfix(self, exp):
 
        # Iterate over the expression for conversion
        for i in exp:
            # If the character is an operand,
            # add it to output
            if self.isOperand(i):
                self.output.append(i)
 
            # If the character is an '(', push it to stack
            elif i == '(':
                self.push(i)
 
            # If the scanned character is an ')', pop and
            # output from the stack until and '(' is found
            elif i == ')':
                while((not self.isEmpty()) and
                      self.peek() != '('):
                    a = self.pop()
                    self.output.append(a)
                if (not self.isEmpty() and self.peek() != '('):
                    return -1
                else:
                    self.pop()
 
            # An operator is encountered
            else:
                while(not self.isEmpty() and self.notGreater(i)):
                        # this is to pass cases like a^b^c
                    # without if ab^c^
                    # with if abc^^
                    if i == "^" and self.array[-1] == i:
                        break
                    self.output.append(self.pop())
                self.push(i)
 
        # pop all the operator from the stack
        while not self.isEmpty():
            self.output.append(self.pop())
 
        print "".join(self.output)
 
 
# Driver program to test above function
exp = "a+b*(c^d-e)^(f+g*h)-i"
obj = Conversion(len(exp))
obj.infixToPostfix(exp)
 
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)


C#
using System;
using System.Collections.Generic;
 
/* c# implementation to convert
infix expression to postfix*/
// Note that here we use Stack
// class for Stack operations
 
public  class Test
{
     
    // A utility function to return
    // precedence of a given operator
    // Higher returned value means higher precedence
    internal static int Prec(char ch)
    {
        switch (ch)
        {
        case '+':
        case '-':
            return 1;
 
        case '*':
        case '/':
            return 2;
 
        case '^':
            return 3;
        }
        return -1;
    }
 
    // The main method that converts given infix expression
    // to postfix expression. 
    public static string infixToPostfix(string exp)
    {
        // initializing empty String for result
        string result = "";
 
        // initializing empty stack
        Stack stack = new Stack();
 
        for (int i = 0; i < exp.Length; ++i)
        {
            char c = exp[i];
 
            // If the scanned character is an
            // operand, add it to output.
            if (char.IsLetterOrDigit(c))
            {
                result += c;
            }
 
            // If the scanned character is an '(',
            // push it to the stack.
            else if (c == '(')
            {
                stack.Push(c);
            }
 
            //  If the scanned character is an ')',
            // pop and output from the stack 
            // until an '(' is encountered.
            else if (c == ')')
            {
                while (stack.Count > 0 &&
                        stack.Peek() != '(')
                {
                    result += stack.Pop();
                }
 
                if (stack.Count > 0 && stack.Peek() != '(')
                {
                    return "Invalid Expression"; // invalid expression
                }
                else
                {
                    stack.Pop();
                }
            }
            else // an operator is encountered
            {
                while (stack.Count > 0 && Prec(c) <=
                                  Prec(stack.Peek()))
                {
                    result += stack.Pop();
                }
                stack.Push(c);
            }
 
        }
 
        // pop all the operators from the stack
        while (stack.Count > 0)
        {
            result += stack.Pop();
        }
 
        return result;
    }
 
    // Driver method 
    public static void Main(string[] args)
    {
        string exp = "a+b*(c^d-e)^(f+g*h)-i";
        Console.WriteLine(infixToPostfix(exp));
    }
}
 
// This code is contributed by Shrikant13


Javascript


输出
abcd^e-fgh*+^*+i-

https://youtu.be/ysDharaQXkw?list=PLqM7alHXFySF7Lap-wi5qlaD8OEBx9RMV
测验:堆栈问题