中綴 後綴表達式求值

一.中綴轉後綴

1.遇到操作數:直接輸出(添加到後綴表達式中)
2.棧爲空時,遇到運算符,直接入棧
3.遇到左括號:將其入棧
4.遇到右括號:執行出棧操作,並將出棧的元素輸出,直到彈出棧的是左括號,左括號不輸出。
5.遇到其他運算符:例如加減乘除:彈出所有優先級大於或者等於該運算符的棧頂元素,然後將該運算符入棧。
6.最終將棧中的元素依次出棧,輸出。

二.由後綴表達式得到表達式樹


三.對表達式樹的根節點調用cal()虛函數就能算出表達式的值


代碼

#include<iostream>
#include<string>
#include<map>
#include<stack>

using namespace std;

map<char, int> m{
					{'*', 3}, {'/', 3},
					{'+', 4}, {'-', 4},
					{'(', 99}
				};//定義優先級 

class node
{
	public:
		virtual double cal() const = 0;
		virtual ~node () {}
};
 
class numnode : public node
{
	public:
		numnode(double d):number(d){}
		virtual double cal() const;
	private:
		double number;
};

class binarynode : public node
{
	protected:
		node* _left;
		node* _right;
	public:
		binarynode(node* left, node* right):_left(left),_right(right){}
		~binarynode();
};

class addnode : public binarynode
{
	public:
		addnode(node* left, node* right):binarynode(left, right){};
		virtual double cal() const;
		
};

class mutinode : public binarynode
{
	public:
		mutinode(node* left, node* right):binarynode(left, right){};
		virtual double cal() const;
};

inline double numnode::cal() const
{
	return number;
}
binarynode::~binarynode() 
{
	delete _left;
	delete _right;
}
double addnode::cal() const
{
	return _left->cal() + _right->cal();
}
double mutinode::cal() const
{
	return _left->cal() * _right->cal();
}

string suffix(const string& str) //得到後綴表達式
{
	stack<char> sta;
	string ret;
	
	for(int i=0; i<str.size(); i++)
	{
		if( str[i]=='.' || (str[i]>='0' && str[i]<='9') )
		{
			ret += str[i];
		}
		else
		{
			if(ret.back() != ' ')ret += " " ;
			if( sta.empty() || str[i]=='(' )
				sta.push(str[i]);
			else if(str[i] == ')')
			{
				while(sta.top()!='(')
				{
					ret.push_back(sta.top());
					ret.push_back(' '); 
					sta.pop();
				}
				sta.pop();
			}
			else 
			{
				while( !sta.empty() && m[str[i]]>=m[sta.top()] )
				{
					ret = ret + sta.top()+" ";
					sta.pop();
				}
				sta.push(str[i]);
			}
		}
		//cout<<i+1<<" "<<ret<<endl;
	}
	ret += " ";//確保每個數後邊都有個空格 
	while(!sta.empty())
	{
		ret = ret + sta.top()+" ";
		sta.pop();
	}
	return ret;
}

node* suffix_tree(const string& str)//生成後綴表達式樹
{
	stack<node*> sta;
	string temp;
	node* left;
	node* right;
	for(int i=0; i<str.size(); i++)
	{
		//cout<<i<<endl;
		if( str[i]=='.' || (str[i]>='0' && str[i]<='9') )
		{
			temp += str[i];//cout<<"temp"<<temp<<endl;
		}
		else if(str[i]==' ' && str[i-1]>='0' && str[i-1]<='9' )
		{
			double d = stod(temp);
			node *pnode = new numnode(d);
			sta.push(pnode);
			temp = "";
		}
		else if(str[i]==' ')
			continue;
		else switch(str[i])
		{
			case '+':
				right = sta.top();
				sta.pop();
				left = sta.top();
				sta.pop();
				sta.push(new addnode(left,right));
				break;
			case '*':
				right = sta.top();
				sta.pop();
				left = sta.top();
				sta.pop();
				sta.push(new mutinode(left,right));
				break;
		}
	}
	return sta.top();
}

int main()
{
	string temp = "11.0+22*33+(44.0*55+66)*77";
	cout<<"11.0+22*33+(44.0*55+66)*77的後綴表達式:";//11.0 22 33 * + 44.0 55 * 66 + 77 * +
	string sur = suffix(temp);
	cout<<sur<<endl;
	
	node* root = suffix_tree(sur);
	double x = root->cal();
	cout << x << endl;//192159
	
	delete root;
}


還有一種不面向對象的。

一.中綴轉後綴

二.由後綴直接得到結果

#include<iostream>
#include<string>
#include<map>
#include<stack>

using namespace std;

map<char, int> m{
					{'*', 3}, {'/', 3},
					{'+', 4}, {'-', 4},
					{'(', 99}
				};

string suffix(const string& str)
{
	stack<char> sta;
	string ret;
	
	for(int i=0; i<str.size(); i++)
	{
		if(str[i]>='0' && str[i]<='9')
		{
			ret += str[i];
		}
		else
		{
			if(ret.back() != ' ')ret += " " ;
			if( sta.empty() || str[i]=='(' )
				sta.push(str[i]);
			else if(str[i] == ')')
			{
				while(sta.top()!='(')
				{
					ret = ret + sta.top()+" ";
					sta.pop();
				}
				sta.pop();
			}
			else 
			{
				while( !sta.empty() && m[str[i]]>=m[sta.top()] )
				{
					ret = ret + sta.top()+" ";
					sta.pop();
				}
				sta.push(str[i]);
			}
		}
		//cout<<i+1<<" "<<ret<<endl;
	}
	ret += " ";//確保每個數後邊都有個空格 
	while(!sta.empty())
	{
		ret = ret + sta.top()+" ";
		sta.pop();
	}
	return ret;
}

int cal(const string &str)
{
	stack<int> sta;
	string temp;
	int left = 0;
	int right = 0;
	for(int i=0; i<str.size(); i++)
	{
		//cout<<i<<endl;
		if(str[i]>='0' && str[i]<='9')
		{
			temp += str[i];//cout<<"temp"<<temp<<endl;
		}
		else if(str[i]==' ' && str[i-1]>='0' && str[i-1]<='9' )
		{
			sta.push(stoi(temp));
			temp = "";
		}
		else if(str[i]==' ')
			continue;
		else switch(str[i])
		{
			case '+':
				right = sta.top();//cout<<"right"<<right<<endl;
				sta.pop();
				left = sta.top();//cout<<"left"<<left<<endl;
				sta.pop();
				sta.push(left+right);//cout<<"jia"<<sta.top() <<endl;
				break;
			case '*':
				right = sta.top();//cout<<"right"<<right<<endl;
				sta.pop();
				left = sta.top();//cout<<"left"<<left<<endl;
				sta.pop();
				sta.push(left*right);//cout<<"cheng"<<sta.top() <<endl;
				break;
		}
	}
	return sta.top();
}

int main()
{
	string temp = "11+22*33+(44*55+66)*77";
	cout<<"11+22*33+(44*55+66)*77的後綴表達式:";//11 22 33 *+ 44 55 *66 + 77 *+
	string sur = suffix(temp);
	cout<<sur<<endl;
	
	cout<<"表達式的和:";
	int sum = cal(sur);
	cout<<sum<<endl;
}

參考:http://www.cnblogs.com/Solstice/archive/2012/07/06/learncpp.html
http://www.relisoft.com/book/lang/poly/3tree.html

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