图4-14是一个
表达式树(expression tree)
的例子。表达式树的树叶是
操作数(operand)
,如常数或变量名字,而其他的结点为
操作符(operator)
。由于这里所有的操作都是二元的,因此这棵特定的树正好是二叉树。
整个树的
中缀表达式(infix expression)为(a+(b*c)) + (((d*e)+f)*g)。
后缀表达式(sufix expression)为abc*+de*f+g*+。
前缀表达式(prefix expression)为++a*bc*+*defg。
图 4.14
构造一棵表达式树:把后缀表达式转变成表达式树。
算法思想:从前向后依次扫描后缀表达式,如果符号是操作数,那么就建立一个单结点树并将它推入栈中。如果符号是操作符,那么就从栈中弹出两棵树T1和T2(T1先弹出)并形成一棵新的树,该树的根就是操作符,它的左、右儿子分别是T2和T1。然后将指向这棵新树的指针压入栈中。
中缀表达式到后缀表达式的转换
栈不仅可以用来计算后缀表达式的值,而且还可以用来将一个标准形式的表达式(或叫作中缀式(infix)转换成后缀 式。设欲将中缀 表达式(a+(b*c))+(((d*e)+f)*g)转换成后缀表达式。正确的答案是abc*+de*f+g*+。
算法思想:
从左到右扫描中缀表达式,当读到一个操作数的时候,立即把它放到输出中。操作符不立即输出,而是先存在栈中。当读到操作符的时候,分为下面3种情况:
1)如果是'(',直接压入栈中。
2)如果是')',依次从栈中弹出操作符,将符号写出直到遇到一个(对应的)左括号,但是这个左括号只被弹出并不输出。
3)如果见到任何其他符号('+'、'*'、'('),那么从栈中弹出栈元素直到发现优先级更低的元素为止。有一个例外:除非是在处理')'的时候,否则决不从栈中移走'('。
最后,如果读到输入的末尾,将栈元素弹出直到该栈变成空栈,将符号写到输出中。
#include <iostream>
#include <stack>
#include <string>
#include <map>
using namespace std;
map<char, int> m;
char c[200];
struct Node
{
char data;
Node *left, *right;
Node(char c):data(c), left(NULL), right(NULL) {}
};
bool isOperand(char c) // decision 'c' is an operand or not
{
if( c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '1' && c <= '9')
return true;
return false;
}
Node* create_ET(string s) // create an expression tree
{
stack<Node*> st;
Node *temp;
int len = s.length();
for(int i = 0; i < len; i++)
{
if(s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/')
{
temp = new Node(s[i]);
temp->right = st.top();
st.pop();
temp->left = st.top();
st.pop();
st.push(temp);
}
else
{
temp = new Node(s[i]);
st.push(temp);
}
}
return st.top();
}
string change(string s) // convert infix expression into suffix expression
{
int len = s.length();
string temp;
char c[200];
stack<char> cs;
int i,j;
for(i = 0, j = 0; i < len; i++)
{
if( isOperand(s[i]) )
c[j++] = s[i];
else
{
switch ( s[i] )
{
case '(':
cs.push( s[i] );
break;
case ')':
while(cs.top() != '(')
{
c[j++] = cs.top();
cs.pop();
}
cs.pop();
break;
case '+':
case '-':
case '*':
case '/':
while( !cs.empty() && m[s[i]] <= m[cs.top()] )
{
c[j++] = cs.top();
cs.pop();
}
cs.push( s[i] );
break;
}
}
}
if( !cs.empty() )
{
c[j++] = cs.top();
cs.pop();
}
c[j] = '\0';
temp = c;
return temp;
}
void postorder(Node *root) // postorder traversal
{
if(root != NULL)
{
postorder(root->left);
postorder(root->right);
cout << root->data << ' ';
}
}
void preorder(Node *root) // preorder traversal
{
if(root != NULL)
{
cout << root->data << ' ';
preorder(root->left);
preorder(root->right);
}
}
int main()
{
// characterize the priority of operators
m['+'] = 1;
m['-'] = 1;
m['*'] = 2;
m['/'] = 2;
m['('] = 0;
Node *r = create_ET("abc*+de*f+g*+"); // create an expression tree
postorder(r);
cout << endl;
preorder(r);
cout << endl;
string str("(a+(b*c))+(((d*e)+f)*g)");
Node *m = create_ET( change(str) );
postorder(m);
cout << endl;
return 0;
}