📜  将中缀转换为前缀表示法

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

将中缀转换为前缀表示法

虽然我们在日常生活中使用中缀表达式。计算机很难理解这种格式,因为它们需要记住运算符优先级和括号的规则。前缀和后缀表达式更容易让计算机理解和评估。
给定两个操作数a                 b                 和一个运算符\odot                 , 中缀表示法意味着 O 将被放置在 a 和 b 之间a \odot b                 .当运算符放在两个操作数之后时,即ab\odot                 ,称为后缀表示法。并且当运算符放在操作数之前时,即\odot a b                 , 前缀表示法的表达式。
给定任何中缀表达式,我们可以获得等价的前缀和后缀格式。

例子:

Input : A * B + C / D
Output : + * A B/ C D 

Input : (A - B/C) * (A/K-L)
Output : *-A/BC-/AKL

要将中缀转换为后缀表达式,请参阅这篇文章 Stack |设置 2(中缀到后缀)。我们使用相同的方法将中缀转换为前缀。

  • 步骤1:反转中缀表达式,即A+B*C 将变为C*B+A。请注意,在反转每个 '(' 将变为 ')' 并且每个 ')' 变为 '('。
  • 第二步:获取修改后的表达式的“nearly”后缀表达式,即CB*A+。
  • 第三步:反转后缀表达式。因此,在我们的示例中,前缀是 +A*BC。

请注意,对于第 2 步,我们没有按原样使用后缀算法。算法有细微的变化。根据 https://www.geeksforgeeks.org/stack-set-2-infix-to-postfix/ ,我们必须从堆栈中弹出所有大于或等于优先于扫描运算符的运算符符.但是在这里,我们必须从堆栈中弹出所有优先级高于扫描运算符符的运算符。只有在“^”运算符的情况下,我们才会从堆栈中弹出大于或等于优先级的运算符。

下面是该算法的 C++ 实现。

C++
// CPP program to convert infix to prefix
#include 
using namespace std;
 
bool isOperator(char c)
{
    return (!isalpha(c) && !isdigit(c));
}
 
int getPriority(char C)
{
    if (C == '-' || C == '+')
        return 1;
    else if (C == '*' || C == '/')
        return 2;
    else if (C == '^')
        return 3;
    return 0;
}
 
string infixToPostfix(string infix)
{
    infix = '(' + infix + ')';
    int l = infix.size();
    stack char_stack;
    string output;
 
    for (int i = 0; i < l; i++) {
 
        // If the scanned character is an
        // operand, add it to output.
        if (isalpha(infix[i]) || isdigit(infix[i]))
            output += infix[i];
 
        // If the scanned character is an
        // ‘(‘, push it to the stack.
        else if (infix[i] == '(')
            char_stack.push('(');
 
        // If the scanned character is an
        // ‘)’, pop and output from the stack
        // until an ‘(‘ is encountered.
        else if (infix[i] == ')') {
            while (char_stack.top() != '(') {
                output += char_stack.top();
                char_stack.pop();
            }
 
            // Remove '(' from the stack
            char_stack.pop();
        }
 
        // Operator found
        else
        {
            if (isOperator(char_stack.top()))
            {
                if(infix[i] == '^')
                {
                      while (getPriority(infix[i]) <= getPriority(char_stack.top()))
                       {
                         output += char_stack.top();
                         char_stack.pop();
                       }
                     
                }
                else
                {
                    while (getPriority(infix[i]) < getPriority(char_stack.top()))
                       {
                         output += char_stack.top();
                         char_stack.pop();
                       }
                     
                }
 
                // Push current Operator on stack
                char_stack.push(infix[i]);
            }
        }
    }
      while(!char_stack.empty()){
          output += char_stack.top();
        char_stack.pop();
    }
    return output;
}
 
string infixToPrefix(string infix)
{
    /* Reverse String
     * Replace ( with ) and vice versa
     * Get Postfix
     * Reverse Postfix  *  */
    int l = infix.size();
 
    // Reverse infix
    reverse(infix.begin(), infix.end());
 
    // Replace ( with ) and vice versa
    for (int i = 0; i < l; i++) {
 
        if (infix[i] == '(') {
            infix[i] = ')';
            i++;
        }
        else if (infix[i] == ')') {
            infix[i] = '(';
            i++;
        }
    }
 
    string prefix = infixToPostfix(infix);
 
    // Reverse postfix
    reverse(prefix.begin(), prefix.end());
 
    return prefix;
}
 
// Driver code
int main()
{
    string s = ("x+y*z/w+u");
    cout << infixToPrefix(s) << std::endl;
    return 0;
}


Java
// JAVA program to convert infix to prefix
import java.util.*;
 
class GFG
{
  static boolean isalpha(char c)
  {
    if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
    {
      return true;
    }
    return false;
  }
 
  static boolean isdigit(char c)
  {
    if (c >= '0' && c <= '9')
    {
      return true;
    }
    return false;
  }
 
  static boolean isOperator(char c)
  {
    return (!isalpha(c) && !isdigit(c));
  }
 
  static int getPriority(char C)
  {
    if (C == '-' || C == '+')
      return 1;
    else if (C == '*' || C == '/')
      return 2;
    else if (C == '^')
      return 3;
 
    return 0;
  }
 
  // Reverse the letters of the word
  static String reverse(char str[], int start, int end)
  {
 
    // Temporary variable to store character
    char temp;
    while (start < end)
    {
 
      // Swapping the first and last character
      temp = str[start];
      str[start] = str[end];
      str[end] = temp;
      start++;
      end--;
    }
    return String.valueOf(str);
  }
 
  static String infixToPostfix(char[] infix1)
  {
    System.out.println(infix1);
    String infix = '(' + String.valueOf(infix1) + ')';
 
    int l = infix.length();
    Stack char_stack = new Stack<>();
    String output="";
 
    for (int i = 0; i < l; i++)
    {
 
      // If the scanned character is an
      // operand, add it to output.
      if (isalpha(infix.charAt(i)) || isdigit(infix.charAt(i)))
        output += infix.charAt(i);
 
      // If the scanned character is an
      // ‘(‘, push it to the stack.
      else if (infix.charAt(i) == '(')
        char_stack.add('(');
 
      // If the scanned character is an
      // ‘)’, pop and output from the stack
      // until an ‘(‘ is encountered.
      else if (infix.charAt(i) == ')')
      {
        while (char_stack.peek() != '(')
        {
          output += char_stack.peek();
          char_stack.pop();
        }
 
        // Remove '(' from the stack
        char_stack.pop();
      }
 
      // Operator found
      else {
        if (isOperator(char_stack.peek()))
        {
          while ((getPriority(infix.charAt(i)) <
                  getPriority(char_stack.peek()))
                 || (getPriority(infix.charAt(i)) <=
                     getPriority(char_stack.peek())
                     && infix.charAt(i) == '^'))
          {
            output += char_stack.peek();
            char_stack.pop();
          }
 
          // Push current Operator on stack
          char_stack.add(infix.charAt(i));
        }
      }
    }
    while(!char_stack.empty()){
          output += char_stack.pop();
    }
    return output;
  }
 
  static String infixToPrefix(char[] infix)
  {
    /*
         * Reverse String Replace ( with ) and vice versa Get Postfix Reverse Postfix *
         */
    int l = infix.length;
 
    // Reverse infix
    String infix1 = reverse(infix, 0, l - 1);
    infix = infix1.toCharArray();
 
    // Replace ( with ) and vice versa
    for (int i = 0; i < l; i++)
    {
 
      if (infix[i] == '(')
      {
        infix[i] = ')';
        i++;
      }
      else if (infix[i] == ')')
      {
        infix[i] = '(';
        i++;
      }
    }
 
    String prefix = infixToPostfix(infix);
 
    // Reverse postfix
    prefix = reverse(prefix.toCharArray(), 0, l-1);
 
    return prefix;
  }
 
  // Driver code
  public static void main(String[] args)
  {
    String s = ("x+y*z/w+u");
    System.out.print(infixToPrefix(s.toCharArray()));
  }
}
 
// This code is contributed by Rajput-Ji


C#
// C# program to convert infix to prefix
using System;
using System.Collections.Generic;
 
public class GFG {
  static bool isalpha(char c) {
    if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') {
      return true;
    }
    return false;
  }
 
  static bool isdigit(char c) {
    if (c >= '0' && c <= '9') {
      return true;
    }
    return false;
  }
 
  static bool isOperator(char c) {
    return (!isalpha(c) && !isdigit(c));
  }
 
  static int getPriority(char C) {
    if (C == '-' || C == '+')
      return 1;
    else if (C == '*' || C == '/')
      return 2;
    else if (C == '^')
      return 3;
 
    return 0;
  }
 
  // Reverse the letters of the word
  static String reverse(char []str, int start, int end) {
 
    // Temporary variable to store character
    char temp;
    while (start < end) {
 
      // Swapping the first and last character
      temp = str[start];
      str[start] = str[end];
      str[end] = temp;
      start++;
      end--;
    }
    return String.Join("",str);
  }
 
  static String infixToPostfix(char[] infix1) {
    String infix = '(' + String.Join("",infix1) + ')';
 
    int l = infix.Length;
    Stack char_stack = new Stack();
    String output = "";
 
    for (int i = 0; i < l; i++) {
 
      // If the scanned character is an
      // operand, add it to output.
      if (isalpha(infix[i]) || isdigit(infix[i]))
        output += infix[i];
 
      // If the scanned character is an
      // ‘(‘, push it to the stack.
      else if (infix[i] == '(')
        char_stack.Push('(');
 
      // If the scanned character is an
      // ‘)’, pop and output from the stack
      // until an ‘(‘ is encountered.
      else if (infix[i] == ')') {
        while (char_stack.Peek() != '(') {
          output += char_stack.Peek();
          char_stack.Pop();
        }
 
        // Remove '(' from the stack
        char_stack.Pop();
      }
 
      // Operator found
      else {
        if (isOperator(char_stack.Peek())) {
          while ((getPriority(infix[i]) < getPriority(char_stack.Peek()))
                 || (getPriority(infix[i]) <= getPriority(char_stack.Peek())
                     && infix[i] == '^')) {
            output += char_stack.Peek();
            char_stack.Pop();
          }
 
          // Push current Operator on stack
          char_stack.Push(infix[i]);
        }
      }
    }
    while (char_stack.Count!=0) {
      output += char_stack.Pop();
    }
    return output;
  }
 
  static String infixToPrefix(char[] infix) {
    /*
         * Reverse String Replace ( with ) and
         // vice versa Get Postfix Reverse Postfix *
         */
    int l = infix.Length;
 
    // Reverse infix
    String infix1 = reverse(infix, 0, l - 1);
    infix = infix1.ToCharArray();
 
    // Replace ( with ) and vice versa
    for (int i = 0; i < l; i++) {
 
      if (infix[i] == '(') {
        infix[i] = ')';
        i++;
      } else if (infix[i] == ')') {
        infix[i] = '(';
        i++;
      }
    }
 
    String prefix = infixToPostfix(infix);
 
    // Reverse postfix
    prefix = reverse(prefix.ToCharArray(), 0, l - 1);
 
    return prefix;
  }
 
  // Driver code
  public static void Main(String[] args) {
    String s = ("x+y*z/w+u");
    Console.Write(infixToPrefix(s.ToCharArray()));
  }
}
 
// This code is contributed by gauravrajput1


输出
++x/*yzwu

时间复杂度:
push() 和 pop() 之类的堆栈操作是在恒定时间内执行的。因为一旦复杂度在时间上是线性的,我们就会扫描表达式中的所有字符,即\ \mathcal{O}(n)                 .