4.2.2 一个例子——表达式树

图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;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章