📜  使用堆栈内和堆栈外的不同优先级值对后缀进行中缀

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

使用堆栈内和堆栈外的不同优先级值对后缀进行中缀

可以使用两个优先级函数优雅地完成中缀到后缀表达式的转换。每个运算符都被分配一个值(值越大意味着优先级越高),这取决于运算符是在堆栈内部还是外部。此外,不同运算符的左右关联性可以通过改变两个优先级函数中的值来处理。
中缀表达式示例: a+b*c
其对应的后缀表达式:abc*+

以下步骤说明了这些转换是如何完成的。

第 1 步: a + bc*(这里我们有两个运算符:+ 和 *,其中 * 具有更高的优先级,因此将首先评估它)。

第 2 步: abc*+ (现在我们剩下一个运算符,即 +,所以它被评估)


要了解有关中缀和后缀表达式的更多信息,请访问链接。
注意:在本文中,我们假设所有运算符都是从左到右关联的。
例子:

方法:

  1. 如果输入字符是操作数,则打印它。
  2. 如果输入字符是运算符-
    • 如果堆栈为空,则将其推入堆栈。
    • 如果其优先级值大于顶部字符的优先级值,则推送。
    • 如果它的优先级值小于或等于,则从堆栈中弹出并打印,而顶部字符的优先级大于输入字符的优先级值。
  3. 如果输入字符是')',则弹出并打印直到顶部是'('。(弹出'('但不打印它。)
  4. 如果堆栈在遇到'('之前变空,那么它是一个无效的表达式。
  5. 重复步骤 1-4,直到完全读取输入表达式。
  6. 从堆栈中弹出剩余的元素并打印它们。

上面的方法通过在堆栈外分配更高的优先级值和在堆栈内分配更低的优先级值来处理取幂运算符(此处为 ^)的右关联性,而左关联运算符则相反。
下面是上述方法的实现:

C++
// C++ program to convert an infix expression to a
// postfix expression using two precedence function
#include 
using namespace std;
 
// to check if the input character
// is an operator or a '('
int isOperator(char input)
{
    switch (input) {
    case '+':
        return 1;
    case '-':
        return 1;
    case '*':
        return 1;
    case '%':
        return 1;
    case '/':
        return 1;
    case '(':
        return 1;
    }
    return 0;
}
 
// to check if the input character is an operand
int isOperand(char input)
{
    if (input >= 65 && input <= 90
        || input >= 97 && input <= 122)
        return 1;
    return 0;
}
 
// function to return precedence value
// if operator is present in stack
int inPrec(char input)
{
    switch (input) {
    case '+':
    case '-':
        return 2;
    case '*':
    case '%':
    case '/':
        return 4;
    case '(':
        return 0;
    }
}
 
// function to return precedence value
// if operator is present outside stack.
int outPrec(char input)
{
    switch (input) {
    case '+':
    case '-':
        return 1;
    case '*':
    case '%':
    case '/':
        return 3;
    case '(':
        return 100;
    }
}
 
// function to convert infix to postfix
void inToPost(char* input)
{
    stack s;
 
    // while input is not NULL iterate
    int i = 0;
    while (input[i] != '\0') {
 
        // if character an operand
        if (isOperand(input[i])) {
            printf("%c", input[i]);
        }
 
        // if input is an operator, push
        else if (isOperator(input[i])) {
            if (s.empty()
                || outPrec(input[i]) > inPrec(s.top()))
                s.push(input[i]);
            else {
                while (!s.empty()
                    && outPrec(input[i]) < inPrec(s.top())) {
                    printf("%c", s.top());
                    s.pop();
                }
                s.push(input[i]);
            }
        }
 
        // condition for opening bracket
        else if (input[i] == ')') {
            while (s.top() != '(') {
                printf("%c", s.top());
                s.pop();
 
                // if opening bracket not present
                if (s.empty()) {
                    printf("Wrong input\n");
                    exit(1);
                }
            }
 
            // pop the opening bracket.
            s.pop();
        }
        i++;
    }
 
    // pop the remaining operators
    while (!s.empty()) {
        if (s.top() == '(') {
            printf("\n Wrong input\n");
            exit(1);
        }
        printf("%c", s.top());
        s.pop();
    }
}
 
// Driver code
int main()
{
    char input[] = "a+b*c-(d/e+f*g*h)";
    inToPost(input);
    return 0;
}


Java
import static java.lang.System.exit;
import java.util.Stack;
 
// Java program to convert an infix expression to a
// postfix expression using two precedence function
class GFG {
 
    // to check if the input character
    // is an operator or a '('
    static int isOperator(char input)
    {
        switch (input) {
        case '+':
            return 1;
        case '-':
            return 1;
        case '*':
            return 1;
        case '%':
            return 1;
        case '/':
            return 1;
        case '(':
            return 1;
        }
        return 0;
    }
 
    // to check if the input character is an operand
    static int isOperand(char input)
    {
        if (input >= 65 && input <= 90
            || input >= 97 && input <= 122) {
            return 1;
        }
        return 0;
    }
 
    // function to return precedence value
    // if operator is present in stack
    static int inPrec(char input)
    {
        switch (input) {
        case '+':
        case '-':
            return 2;
        case '*':
        case '%':
        case '/':
            return 4;
        case '(':
            return 0;
        }
        return 0;
    }
 
    // function to return precedence value
    // if operator is present outside stack.
    static int outPrec(char input)
    {
        switch (input) {
        case '+':
        case '-':
            return 1;
        case '*':
        case '%':
        case '/':
            return 3;
        case '(':
            return 100;
        }
        return 0;
    }
 
    // function to convert infix to postfix
    static void inToPost(char[] input)
    {
        Stack s = new Stack();
 
        // while input is not NULL iterate
        int i = 0;
        while (input.length != i) {
 
            // if character an operand
            if (isOperand(input[i]) == 1) {
                System.out.printf("%c", input[i]);
            } // if input is an operator, push
            else if (isOperator(input[i]) == 1) {
                if (s.empty()
                    || outPrec(input[i]) > inPrec(s.peek())) {
                    s.push(input[i]);
                }
                else {
                    while (!s.empty()
                           && outPrec(input[i]) < inPrec(s.peek())) {
                        System.out.printf("%c", s.peek());
                        s.pop();
                    }
                    s.push(input[i]);
                }
            } // condition for opening bracket
            else if (input[i] == ')') {
                while (s.peek() != '(') {
                    System.out.printf("%c", s.peek());
                    s.pop();
 
                    // if opening bracket not present
                    if (s.empty()) {
                        System.out.printf("Wrong input\n");
                        exit(1);
                    }
                }
 
                // pop the opening bracket.
                s.pop();
            }
            i++;
        }
 
        // pop the remaining operators
        while (!s.empty()) {
            if (s.peek() == '(') {
                System.out.printf("\n Wrong input\n");
                exit(1);
            }
            System.out.printf("%c", s.peek());
            s.pop();
        }
    }
 
    // Driver code
    static public void main(String[] args)
    {
        char input[] = "a+b*c-(d/e+f*g*h)".toCharArray();
        inToPost(input);
    }
}
 
// This code is contributed by Rajput-Ji


Python3
# Python3 program to convert an infix
# expression to a postfix expression
# using two precedence function
 
# To check if the input character
# is an operator or a '('
def isOperator(input):
     
    switch = {
        '+': 1,
        '-': 1,
        '*': 1,
        '/': 1,
        '%': 1,
        '(': 1,
    }
     
    return switch.get(input, False)
 
# To check if the input character is an operand
def isOperand(input):
     
    if ((ord(input) >= 65 and ord(input) <= 90) or
        (ord(input) >= 97 and ord(input) <= 122)):
        return 1
         
    return 0
 
# Function to return precedence value
# if operator is present in stack
def inPrec(input):
     
    switch = {
        '+': 2,
        '-': 2,
        '*': 4,
        '/': 4,
        '%': 4,
        '(': 0,
    }
     
    return switch.get(input, 0)
 
# Function to return precedence value
# if operator is present outside stack.
def outPrec(input):
     
    switch = {
        '+': 1,
        '-': 1,
        '*': 3,
        '/': 3,
        '%': 3,
        '(': 100,
    }
     
    return switch.get(input, 0)
 
# Function to convert infix to postfix
def inToPost(input):
     
    i = 0
    s = []
 
    # While input is not NULL iterate
    while (len(input) != i):
 
        # If character an operand
        if (isOperand(input[i]) == 1):
            print(input[i], end = "")
 
        # If input is an operator, push
        elif (isOperator(input[i]) == 1):
            if (len(s) == 0 or
                outPrec(input[i]) >
                 inPrec(s[-1])):
                s.append(input[i])
             
            else:
                while(len(s) > 0 and
                      outPrec(input[i]) <
                      inPrec(s[-1])):
                    print(s[-1], end = "")
                    s.pop()
                     
                s.append(input[i])
 
        # Condition for opening bracket
        elif(input[i] == ')'):
            while(s[-1] != '('):
                print(s[-1], end = "")
                s.pop()
 
                # If opening bracket not present
                if(len(s) == 0):
                    print('Wrong input')
                    exit(1)
 
            # pop the opening bracket.
            s.pop()
             
        i += 1
         
    # pop the remaining operators
    while(len(s) > 0):
        if(s[-1] == '('):
            print('Wrong input')
            exit(1)
             
        print(s[-1], end = "")
        s.pop()
 
# Driver code
input = "a+b*c-(d/e+f*g*h)"
 
inToPost(input)
 
# This code is contributed by dheeraj_2801


C#
// C# program to convert an infix expression to a
// postfix expression using two precedence function
using System.Collections.Generic;
using System;
public class GFG {
 
    // to check if the input character
    // is an operator or a '('
    static int isOperator(char input)
    {
        switch (input) {
        case '+':
            return 1;
        case '-':
            return 1;
        case '*':
            return 1;
        case '%':
            return 1;
        case '/':
            return 1;
        case '(':
            return 1;
        }
        return 0;
    }
 
    // to check if the input character is an operand
    static int isOperand(char input)
    {
        if (input >= 65 && input <= 90
            || input >= 97 && input <= 122) {
            return 1;
        }
        return 0;
    }
 
    // function to return precedence value
    // if operator is present in stack
    static int inPrec(char input)
    {
        switch (input) {
        case '+':
        case '-':
            return 2;
        case '*':
        case '%':
        case '/':
            return 4;
        case '(':
            return 0;
        }
        return 0;
    }
 
    // function to return precedence value
    // if operator is present outside stack.
    static int outPrec(char input)
    {
        switch (input) {
        case '+':
        case '-':
            return 1;
        case '*':
        case '%':
        case '/':
            return 3;
        case '(':
            return 100;
        }
        return 0;
    }
 
    // function to convert infix to postfix
    static void inToPost(char[] input)
    {
        Stack s = new Stack();
 
        // while input is not NULL iterate
        int i = 0;
        while (input.Length != i) {
 
            // if character an operand
            if (isOperand(input[i]) == 1) {
                Console.Write(input[i]);
            }
 
            // if input is an operator, push
            else if (isOperator(input[i]) == 1) {
                if (s.Count == 0
                    || outPrec(input[i]) > inPrec(s.Peek())) {
                    s.Push(input[i]);
                }
                else {
                    while (s.Count != 0
                           && outPrec(input[i]) < inPrec(s.Peek())) {
                        Console.Write(s.Peek());
                        s.Pop();
                    }
                    s.Push(input[i]);
                }
            } // condition for opening bracket
            else if (input[i] == ')') {
                while (s.Peek() != '(') {
                    Console.Write(s.Peek());
                    s.Pop();
 
                    // if opening bracket not present
                    if (s.Count == 0) {
                        Console.Write("Wrong input\n");
                        return;
                    }
                }
 
                // pop the opening bracket.
                s.Pop();
            }
            i++;
        }
 
        // pop the remaining operators
        while (s.Count != 0) {
            if (s.Peek() == '(') {
                Console.Write("\n Wrong input\n");
                return;
            }
            Console.Write(s.Peek());
            s.Pop();
        }
    }
 
    // Driver code
    static public void Main()
    {
        char[] input = "a+b*c-(d/e+f*g*h)".ToCharArray();
        inToPost(input);
    }
}
 
// This code is contributed by Rajput-Ji


Javascript


输出:
abc*+de/fg*h*+-

如何处理具有从右到左关联性的运算符?
例如,幂运算符^。 “a^b^c”的后缀是“abc^^”,但上面的解决方案会将后缀打印为“ab^c^”,这是错误的。
在上面的实现中,当我们看到一个具有相同优先级的运算符时,我们将其视为较低。如果两个运算符留给关联性,我们需要考虑相同的问题。但是在从右到左关联性的情况下,我们需要将其视为更高的优先级并将其推送到堆栈中。
方法:

  1. 如果输入字符是操作数,则打印它。
  2. 如果输入字符是运算符-
    • 如果堆栈为空,则将其推入堆栈。
    • 如果((其优先级值大于顶部字符的优先级值)或(优先级相同且关联性是从右到左)),推。
    • 如果((其优先级值较低)或(优先级相同且关联性从左到右)),则从堆栈中弹出并打印,而顶部字符的优先级大于输入字符的优先级值。
  3. 如果输入字符是')',则弹出并打印直到顶部是'('。(弹出'('但不打印它。)
  4. 如果堆栈在遇到'('之前变空,那么它是一个无效的表达式。
  5. 重复步骤 1-4,直到完全读取输入表达式。
  6. 从堆栈中弹出剩余的元素并打印它们。