给定一个表示中缀符号的字符串。任务是将其转换为表达式树。
表达式树是一种二叉树,其中操作数由叶节点表示,运算符由中间节点表示。任何节点都不能有一个子节点。
表达式树的构建
该算法遵循调车码与后缀到表达式树转换的组合。
考虑以下行:
((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