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




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