用二叉树实现计算器

#include <iostream>
#include <string>
#include <sstream>
#include <stack>
#include <cmath>
using namespace std;



bool IsOperator(string mystring)   //判断字符串是否是运算符
{
	if (mystring == "-" || mystring == "+" || mystring == "*" || mystring == "/")
		return true;
	else
		return false;
}

bool IsOperator(char ops)  //判断一个字符是否是运算符
{
	if (ops == '+' || ops == '-' || ops == '*' || ops == '/' || ops == '(' || ops == ')')
		return true;
	else
		return false;
}

bool IsOperand(char ch)   //判断是否是数字
{
	if (((ch >= '0') && (ch <= '9')) || (ch == '.'))
		return true;
	else
		return false;
}

bool judge(string exp)   //判断输入是否正确
{
	char check;
	int error = 0, lb = 0, rb = 0, numofoperand = 0, numofoperator = 0;
	for (int m = 0; m<exp.size(); m++)
	{
		check = exp[m];
		if (IsOperand(check))
		{
			if (check == '.')//判断浮点型数据是否正确
			{
				if (!(exp[m - 1] >= '0'&&exp[m - 1] <= '9') && (exp[m + 1] >= '0'&&exp[m + 1] <= '9'))
				{
					error++;
					cout << "浮点型数据输入有误!!!" << endl;
				}
			}
			numofoperand++;
		}
		else if (IsOperator(check))
		{
			if (check == ')')
			{
				rb++;
				if (rb>lb)
				{
					error++;
					cout << "右括号不可能大于左括号!!!" << endl;
				}
				if (IsOperator(exp[m + 1]) && (exp[m + 1] == '+' || exp[m + 1] == '-' || exp[m + 1] == '*' || exp[m + 1] == '/' || exp[m + 1] == ')'))
				{
					numofoperator++;
					m++;
					if (exp[m] == ')')
						rb++;
				}
				else if (IsOperator(exp[m + 1]) || IsOperand(exp[m + 1]))
				{
					error++;
					cout << "右括号后不可能直接跟数据或左括号!!!" << endl;
				}
			}
			else if (check == '(')
			{
				lb++;
				if (IsOperator(exp[m + 1]) && exp[m + 1] == '(' || exp[m + 1] == '-')//左括号右边只能是数字或者"-"号
				{
					m++;
					m++;
					lb++;
				}
				else if (IsOperator(exp[m + 1]))
				{
					error++;
					cout << "左括号后运算符只能跟左括号!!!" << endl;
				}
			}
			else
			{
				numofoperator++;
				if (IsOperator(exp[m + 1]) && exp[m + 1] == '(')
				{
					m++;
					lb++;

				}
				else if (IsOperator(exp[m + 1]))
				{
					error++;
					cout << "非括号的运算符不能直接接非括号运算符!!!" << endl;
				}
			}
		}
		else
		{
			error++;
			cout << check << "为非法字符!!!" << endl;
		}
	}
	if ((error == 0) && (lb == rb) && (numofoperand != 0) && (numofoperator != 0))
		return true;
	else
		return false;
}
bool   addition(char   OperatorA, char   OperatorB)         //A和B的优先级相同时返回TRUE.   
{
	if (OperatorA == OperatorB || (OperatorA == '*'&&OperatorB == '/') || (OperatorA == '/'&&OperatorB == '*') || (OperatorA == '+'&&OperatorB == '-') || (OperatorA == '-'&&OperatorB == '+'))
		return   true;
	else
		return   false;
}

bool TakesPrecedence(char OperatorA, char OperatorB)  //按照优先级用if从最优至最后从上至下排列,从而达到比较A与B的优先级
{
	if (OperatorA == '(')
		return false;
	else if (OperatorB == '(')
		return false;
	else if (OperatorB == ')')
		return true;
	else   if (addition(OperatorA, OperatorB))
		return false;
	else if ((OperatorA == '*') || (OperatorA == '/'))
		return true;
	else if ((OperatorB == '*') || (OperatorB == '/'))
		return false;
	else   if ((OperatorA == '+') || (OperatorA == '-'))
		return   true;
	else
		return true;
}

//****************************************************************************//

class BinNode{
public:
	string data;
	BinNode *left_child;
	BinNode *right_child;
	BinNode(string k)    //构造函数
	{
		data = k;
		left_child = NULL;
		right_child = NULL;
	}
};



class binarytree//树的类
{
public:
	BinNode *root;         //根节点
	binarytree(void){ root = NULL; }   //构造函数
	void print(void){ print(root); }
	void print(BinNode *p)
	{
		if (p != NULL)
		{
			print(p->left_child);
			print(p->right_child);
			cout << p->data << " ";
		}
	}
	void evaluate(void){ evaluate(root); }
	bool evaluate(BinNode *prt)  //计算二叉树一个节点
	{
		if (IsOperator(prt->data) && !IsOperator(prt->left_child->data) && !IsOperator(prt->right_child->data))//计算二叉树结点的值并存入新的二叉树结点
		{
			float num = 0;
			float num1 = atof(prt->left_child->data.c_str());
			float num2 = atof(prt->right_child->data.c_str());

			if (prt->data == "+")
				num = num1 + num2;
			else if (prt->data == "-")
				num = num1 - num2;
			else if (prt->data == "*")
				num = num1*num2;
			else if (prt->data == "/")
			{
				if (num2 == 0.0)
				{
					cout << "除数为零!!!运算出错";
					return 0;
				}
				else
					num = num1 / num2;
			}

			stringstream bob;
			bob << num;
			string suzzy(bob.str());
			prt->data = suzzy;
			prt->left_child = NULL;
			prt->right_child = NULL;
		}
		else if (prt->left_child == NULL&&prt->right_child == NULL);
		else
		{
			evaluate(prt->left_child);
			evaluate(prt->right_child);
			evaluate(prt);
		}
		return 1;
	}
	void clear_help(void)
	{
		clear_help(root);
	}
	void clear_help(BinNode *rt)
	{
		if (rt != NULL)
		{
			clear_help(rt->left_child);
			clear_help(rt->right_child);
			delete rt;
		}
	}
};

BinNode *build_node(string x)//创建一个临时结点
{
	BinNode *new_node;
	new_node = new BinNode(x);
	return (new_node);
}

void copy(BinNode *&r1, BinNode* r2)//这里将单个的子树连接起来
{
	if (r2 == NULL)
		r1 = NULL;
	else
	{
		r1 = build_node(r2->data);
		copy(r1->left_child, r2->left_child);
		copy(r1->right_child, r2->right_child);
	}
}
//*******************************************************************************************

int main()
{
	binarytree etree;//创建树
	stack<binarytree> NodeStack;//创建栈
	stack<char> OpStack;
	string exp;//声明字符串
	char choice = 'y';//choice为选择是否继续运行程序的判断
	char c;//为下面创建二叉树进行取字符
	while (choice == 'y' || choice == 'Y')
	{
		cout << "请输入一个有效的表达式:" << endl;
		getline(cin, exp);
		cout << "     " << endl << "-----------------------------" << endl;

		if (judge(exp))//如果判断出表达式没有错误,则进行创建二叉树并计算
		{
			cout << "表达式格式正确" << endl;
			for (int i = 0; i<exp.size(); i++)
			{
				c = exp[i];
				if (i == 0 && c == '-') //若开始为负,则把零压入运算数栈,把'-'压入运算符栈
				{
					binarytree   temp;
					temp.root = build_node("0");
					NodeStack.push(temp);
					OpStack.push('-');
				}
				else
				if (IsOperand(c))//若是操作数,则判断下一位是不是操作数,并且将整个数据创建一个子树并压栈
				{
					string tempstring = "";
					tempstring = tempstring + c;
					while (i + 1<exp.size() && IsOperand(exp[i + 1]))   //当当前位置的下一位也是操作数时,将整个数字放在一个临时数据串中
					{
						tempstring += exp[++i];
					}
					binarytree temp;//为这个数据创建一个子树
					temp.root = build_node(tempstring);
					NodeStack.push(temp);//将子树的根节点指针压栈
				}
				else if (c == '+' || c == '-' || c == '/' || c == '*')//如果是操作符
				{
					if (OpStack.empty())//如果栈空,则直接压栈
						OpStack.push(c);
					else if (OpStack.top() == '(')//如果栈顶是左括号,则压栈
						OpStack.push(c);
					else if (TakesPrecedence(c, OpStack.top()))//判断栈顶字符和当前字符的优先级,当c优先级高或者个优先级相同时,将c压栈
						OpStack.push(c);
					else//其他普通情况
					{
						while (!OpStack.empty() && (TakesPrecedence(OpStack.top(), c) || addition(OpStack.top(), c)))//这里将在一般情况下,对已经压栈的操作数和操作符进行创建子树处理,并将当前字符压栈
						{
							binarytree temp_tree;
							string thisstring = "";
							thisstring = thisstring + OpStack.top();//取栈顶进行计算字符串
							OpStack.pop();
							etree.root = build_node(thisstring);//当前树的根为栈顶计算出的字符串
							copy(temp_tree.root, NodeStack.top().root);//子树的根节点放在临时树结点上
							NodeStack.pop();
							etree.root->right_child = temp_tree.root;//将临时结点放入新建子树的右孩子结点上,可以将个子树连接起来
							temp_tree.root = NULL;//置空临时树结点
							copy(temp_tree.root, NodeStack.top().root);//重复上面的步骤连接左孩子
							etree.root->left_child = temp_tree.root;
							NodeStack.pop();
							temp_tree.root = NULL;
							copy(temp_tree.root, etree.root);
							NodeStack.push(temp_tree);
							etree.root = NULL;
						}
						OpStack.push(c);
					}
				}
				else if (c == '(')    //若中间遇到括号,则判断下一位是否为'-'
				{
					OpStack.push(c);
					if (exp[i + 1] == '-')
					{
						binarytree   temp;
						temp.root = build_node("0");
						NodeStack.push(temp);
						OpStack.push('-');
						i++;
					}
				}
				else if (c == ')')//如果遇到右括号,则创建子树,直到与左括号匹配成功,这里和前一步骤的操作基本相同
				{
					while (OpStack.top() != '(')
					{
						binarytree temp_tree;
						string thisstring = "";
						thisstring = thisstring + OpStack.top();
						OpStack.pop();
						etree.root = build_node(thisstring);
						copy(temp_tree.root, NodeStack.top().root);
						NodeStack.pop();
						etree.root->right_child = temp_tree.root;
						temp_tree.root = NULL;
						copy(temp_tree.root, NodeStack.top().root);
						etree.root->left_child = temp_tree.root;
						NodeStack.pop();
						temp_tree.root = NULL;
						copy(temp_tree.root, etree.root);
						NodeStack.push(temp_tree);
						etree.root = NULL;
					}
					OpStack.pop();
				}
			}
			while (!OpStack.empty())//如果栈非空,则继续进行出栈、判断、计算,直到栈空,栈中的结果为最终的计算结果
			{
				binarytree temp_tree;
				string thisstring = "";
				thisstring = thisstring + OpStack.top();
				OpStack.pop();
				etree.root = build_node(thisstring);
				copy(temp_tree.root, NodeStack.top().root);
				NodeStack.pop();
				etree.root->right_child = temp_tree.root;
				temp_tree.root = NULL;
				copy(temp_tree.root, NodeStack.top().root);
				etree.root->left_child = temp_tree.root;
				NodeStack.pop();
				temp_tree.root = NULL;
				copy(temp_tree.root, etree.root);
				NodeStack.push(temp_tree);
				if (!OpStack.empty())
					etree.root = NULL;
			}
			//cout<<"Postfix traversal:";
			//etree.print();
			//cout<<endl;
			etree.evaluate();
			cout << "表达式计算结果:" << exp << "=" << etree.root->data << endl;
			cout << "------------------------------------------------" << endl;
			cout << endl << "是否继续计算下一个表达式<y/n>:";
			cin >> choice;
			getchar();
		}
		else
		{
			cout << "**************************" << endl;
			cout << "错误:表达式有误" << endl;
			cout << endl << "是否继续计算下一个表达式<y/n>:";
			cin >> choice;
			getchar();
		}
	}
	return 0;
}


  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值