📜  将中缀表示法转换为表达式树的程序

📅  最后修改于: 2021-09-07 02:26:57             🧑  作者: Mango

给定一个表示中缀符号的字符串。任务是将其转换为表达式树。
表达式树是一种二叉树,其中操作数由叶节点表示,运算符由中间节点表示。任何节点都不能有一个子节点。

表达式树的构建

该算法遵循调车码后缀到表达式树转换的组合

考虑以下行:

((s[i]!='^' && p[stC.top()]>=p[s[i]]) || 
(s[i]=='^' && p[stC.top()]>p[s[i]])))

您可能还记得与‘+’‘-‘‘*’‘/’ 不同‘^’是右结合。
简单来说,a^b^c 是 a^(b^c) 而不是 (a^b)^c。因此,必须从正确的角度对其进行评估。

现在让我们看看算法是如何工作的,(快速浏览一下代码以更好地了解所使用的变量)

Let us have an expression s = ((a+b)*c-e*f)
currently both the stacks are empty- 
(we'll use C to denote the char stack and N for node stack)
    s[0] = '('            ((a+b)*c-e*f)
                          ^
        C|(|, N| |
    
    s[1] = '('           ((a+b)*c-e*f)
                          ^
         |(|  
        C|(|, N| |
                         
    s[2] = 'a'            ((a+b)*c-e*f)
                            ^
         |(|  
        C|(|, N|a|
                         
    s[3] = '+'            ((a+b)*c-e*f)
                             ^
         |+|
         |(|  
        C|(|, N|a|
        
    s[4] = 'b'             ((a+b)*c-e*f)
                               ^
         |+|
         |(|   |b|
        C|(|, N|a|
         
    s[5] = ')'             ((a+b)*c-e*f)
                                ^
         |+|            t = '+'         +
         |(|   |b|  ->  t1= 'b'        / \    ->  
        C|(|, N|a|      t2= 'a'       a   b      C|(|, N|+|
        
    s[6] = '*'              ((a+b)*c-e*f)
                                  ^
         |*|  
        C|(|, N|+|
    
    s[7] = 'c'              ((a+b)*c-e*f)
                                   ^
         |*|   |c|
        C|(|, N|+|
        
    s[8] = '-'   ((a+b)*c-e*f)              now (C.top(*)>s[8](-))
                         ^    t = '*'        *
         |*|   |c|            t1 = c        / \  ->    |-|
        C|(|, N|+|            t2 = +       +   c      C|(|, N|*|
                                          / \
                                         a   b
    s[9] = 'e'            ((a+b)*c-e*f)
                                   ^
         |-|   |e|
        C|(|, N|*|
        
    s[10] = '*'            ((a+b)*c-e*f)      now (C.top(-)>s[10](*))
                                     ^
         |*|                          
         |-|   |e| 
        C|(|, N|*|
    
    s[11] = 'f'             ((a+b)*c-e*f)
                                       ^
         |*|   |f|
         |-|   |e|
        C|(|, N|*|
    
    s[12] = ')'             ((a+b)*c-e*f)
       1>                               ^
         |*|   |f|         t = '*'          *        
         |-|   |e|  ->     t1= 'f'  ->     / \  ->   |-|   |*|
        C|(|, N|*|         t2= 'e'        e   f     C|(|, N|*|
        
       2>                               
                           t = '-'           -        
         |-|   |*|  ->     t1= '*'  ->     /   \  ->   
        C|(|, N|*|         t2= '*'        *     *     C| |, N|-|
                                         / \   / \
                                        +   c  e  f
                                       / \
                                      a   b 
      now make (-) the root of the tree

下面是上述方法的实现:

CPP
// C++ implementation of the approach
#include 
using namespace std;
 
// Tree Structure
typedef struct node
{
    char data;
    struct node *left, *right;
} * nptr;
 
// Function to create new node
nptr newNode(char c)
{
    nptr n = new node;
    n->data = c;
    n->left = n->right = nullptr;
    return n;
}
 
// Function to build Expression Tree
nptr build(string& s)
{
 
    // Stack to hold nodes
    stack stN;
 
    // Stack to hold chars
    stack stC;
    nptr t, t1, t2;
 
    // Prioritising the operators
    int p[123] = { 0 };
    p['+'] = p['-'] = 1, p['/'] = p['*'] = 2, p['^'] = 3,
    p[')'] = 0;
 
    for (int i = 0; i < s.length(); i++)
    {
        if (s[i] == '(') {
 
            // Push '(' in char stack
            stC.push(s[i]);
        }
 
        // Push the operands in node stack
        else if (isalpha(s[i]))
        {
            t = newNode(s[i]);
            stN.push(t);
        }
        else if (p[s[i]] > 0)
        {
            // If an operator with lower or
            // same associativity appears
            while (
                !stC.empty() && stC.top() != '('
                && ((s[i] != '^' && p[stC.top()] >= p[s[i]])
                    || (s[i] == '^'
                        && p[stC.top()] > p[s[i]])))
            {
 
                // Get and remove the top element
                // from the character stack
                t = newNode(stC.top());
                stC.pop();
 
                // Get and remove the top element
                // from the node stack
                t1 = stN.top();
                stN.pop();
 
                // Get and remove the currently top
                // element from the node stack
                t2 = stN.top();
                stN.pop();
 
                // Update the tree
                t->left = t2;
                t->right = t1;
 
                // Push the node to the node stack
                stN.push(t);
            }
 
            // Push s[i] to char stack
            stC.push(s[i]);
        }
        else if (s[i] == ')') {
            while (!stC.empty() && stC.top() != '(')
            {
                t = newNode(stC.top());
                stC.pop();
                t1 = stN.top();
                stN.pop();
                t2 = stN.top();
                stN.pop();
                t->left = t2;
                t->right = t1;
                stN.push(t);
            }
            stC.pop();
        }
    }
    t = stN.top();
    return t;
}
 
// Function to print the post order
// traversal of the tree
void postorder(nptr root)
{
    if (root)
    {
        postorder(root->left);
        postorder(root->right);
        cout << root->data;
    }
}
 
// Driver code
int main()
{
    string s = "(a^b^(c/d/e-f)^(x*y-m*n))";
    s = "(" + s;
    s += ")";
    nptr root = build(s);
   
    // Function call
    postorder(root);
 
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
 
class GFG
{
 
// Tree Structure
static class nptr
{
    char data;
    nptr left, right;
} ;
 
// Function to create new node
static nptr newNode(char c)
{
    nptr n = new nptr();
    n.data = c;
    n.left = n.right = null;
    return n;
}
 
// Function to build Expression Tree
static nptr build(String s)
{
 
    // Stack to hold nodes
    Stack stN = new Stack<>();
 
    // Stack to hold chars
    Stack stC = new Stack<>();
    nptr t, t1, t2;
 
    // Prioritising the operators
    int []p = new int[123];
    p['+'] = p['-'] = 1;
    p['/'] = p['*'] = 2;
    p['^'] = 3;
    p[')'] = 0;
 
    for (int i = 0; i < s.length(); i++)
    {
        if (s.charAt(i) == '(') {
 
            // Push '(' in char stack
            stC.add(s.charAt(i));
        }
 
        // Push the operands in node stack
        else if (Character.isAlphabetic(s.charAt(i)))
        {
            t = newNode(s.charAt(i));
            stN.add(t);
        }
        else if (p[s.charAt(i)] > 0)
        {
           
            // If an operator with lower or
            // same associativity appears
            while (
                !stC.isEmpty() && stC.peek() != '('
                && ((s.charAt(i) != '^' && p[stC.peek()] >= p[s.charAt(i)])
                    || (s.charAt(i) == '^'
                        && p[stC.peek()] > p[s.charAt(i)])))
            {
 
                // Get and remove the top element
                // from the character stack
                t = newNode(stC.peek());
                stC.pop();
 
                // Get and remove the top element
                // from the node stack
                t1 = stN.peek();
                stN.pop();
 
                // Get and remove the currently top
                // element from the node stack
                t2 = stN.peek();
                stN.pop();
 
                // Update the tree
                t.left = t2;
                t.right = t1;
 
                // Push the node to the node stack
                stN.add(t);
            }
 
            // Push s[i] to char stack
            stC.push(s.charAt(i));
        }
        else if (s.charAt(i) == ')') {
            while (!stC.isEmpty() && stC.peek() != '(')
            {
                t = newNode(stC.peek());
                stC.pop();
                t1 = stN.peek();
                stN.pop();
                t2 = stN.peek();
                stN.pop();
                t.left = t2;
                t.right = t1;
                stN.add(t);
            }
            stC.pop();
        }
    }
    t = stN.peek();
    return t;
}
 
// Function to print the post order
// traversal of the tree
static void postorder(nptr root)
{
    if (root != null)
    {
        postorder(root.left);
        postorder(root.right);
        System.out.print(root.data);
    }
}
 
// Driver code
public static void main(String[] args)
{
    String s = "(a^b^(c/d/e-f)^(x*y-m*n))";
    s = "(" + s;
    s += ")";
    nptr root = build(s);
   
    // Function call
    postorder(root);
}
}
 
// This code is contributed by aashish1995


C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
class GFG
{
 
// Tree Structure
public  class nptr
{
   public char data;
   public nptr left, right;
} ;
 
// Function to create new node
static nptr newNode(char c)
{
    nptr n = new nptr();
    n.data = c;
    n.left = n.right = null;
    return n;
}
 
// Function to build Expression Tree
static nptr build(String s)
{
 
    // Stack to hold nodes
    Stack stN = new Stack();
 
    // Stack to hold chars
    Stack stC = new Stack();
    nptr t, t1, t2;
 
    // Prioritising the operators
    int []p = new int[123];
    p['+'] = p['-'] = 1;
    p['/'] = p['*'] = 2;
    p['^'] = 3;
    p[')'] = 0;
 
    for (int i = 0; i < s.Length; i++)
    {
        if (s[i] == '(')
        {
 
            // Push '(' in char stack
            stC.Push(s[i]);
        }
 
        // Push the operands in node stack
        else if (char.IsLetter(s[i]))
        {
            t = newNode(s[i]);
            stN.Push(t);
        }
        else if (p[s[i]] > 0)
        {
           
            // If an operator with lower or
            // same associativity appears
            while (stC.Count != 0 && stC.Peek() != '('
                && ((s[i] != '^' && p[stC.Peek()] >= p[s[i]])
                    || (s[i] == '^'&& p[stC.Peek()] > p[s[i]])))
            {
 
                // Get and remove the top element
                // from the character stack
                t = newNode(stC.Peek());
                stC.Pop();
 
                // Get and remove the top element
                // from the node stack
                t1 = stN.Peek();
                stN.Pop();
 
                // Get and remove the currently top
                // element from the node stack
                t2 = stN.Peek();
                stN.Pop();
 
                // Update the tree
                t.left = t2;
                t.right = t1;
 
                // Push the node to the node stack
                stN.Push(t);
            }
 
            // Push s[i] to char stack
            stC.Push(s[i]);
        }
        else if (s[i] == ')')
        {
            while (stC.Count != 0 && stC.Peek() != '(')
            {
                t = newNode(stC.Peek());
                stC.Pop();
                t1 = stN.Peek();
                stN.Pop();
                t2 = stN.Peek();
                stN.Pop();
                t.left = t2;
                t.right = t1;
                stN.Push(t);
            }
            stC.Pop();
        }
    }
    t = stN.Peek();
    return t;
}
 
// Function to print the post order
// traversal of the tree
static void postorder(nptr root)
{
    if (root != null)
    {
        postorder(root.left);
        postorder(root.right);
        Console.Write(root.data);
    }
}
 
// Driver code
public static void Main(String[] args)
{
    String s = "(a^b^(c/d/e-f)^(x*y-m*n))";
    s = "(" + s;
    s += ")";
    nptr root = build(s);
   
    // Function call
    postorder(root);
}
}
 
// This code is contributed by aashish1995


输出
abcd/e/f-xy*mn*-^^^

时间复杂度为O(n),因为每个字符仅访问一次。
空间复杂度为O(n)为 (char_stack + node_stack) <= n

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live