用二叉树储存表达式

学习了数据结构的第三章二叉树后,实验是用二叉树来储存表达式。

首先是类的定义。

struct Node{
	char ch;	//结点存储数字或者运算符
	Node* lchild;
	Node* rchild;
};
class BinaryTree {
private:
	Node* root;
public:
	Node* getroot();	//获得根节点
	BinaryTree();	//构造函数
	void destoryTree(Node* bt);	//销毁树
	void preOrder(Node* bt);	//前序遍历
	void inOrder(Node* bt);	//中序遍历
	void postOrder(Node* bt);	//后序遍历
};

然后是类函数的实现。

Node* BinaryTree::getroot() {
	return this->root;
}
BinaryTree::BinaryTree() {
	this->root = new Node;
	root->ch = '0';
	root->lchild = nullptr;
	root->rchild = nullptr;
}
void BinaryTree::preOrder(Node* bt) {
	if (bt == nullptr)
		return;
	else {
		cout << bt->ch;
		preOrder(bt->lchild);
		preOrder(bt->rchild);
	}
}
void BinaryTree::inOrder(Node* bt) {	//用中缀形式输出表达式
	if (bt == nullptr)
		return;
	else {
		if (!isNumber(bt->ch))
			cout << "(";	//添加左括号
		inOrder(bt->lchild);
		cout << bt->ch;
		inOrder(bt->rchild);
		if (!isNumber(bt->ch))
			cout << ")";	//添加右括号
	}
}
void BinaryTree::postOrder(Node* bt) {
	if (bt == nullptr)
		return;
	else {
		postOrder(bt->lchild);
		postOrder(bt->rchild);
		cout << bt->ch;
	}
}
void BinaryTree::destoryTree(Node* bt) {
	Node* lTree = bt->lchild;
	Node* rTree = bt->rchild;
	delete bt;
	if(lTree != nullptr)
		destoryTree(lTree);
	if(rTree != nullptr)
		destoryTree(rTree);
	return;
}

然后是判断字符是否是数字的函数和判断运算符优先级的函数。

bool isNumber(char ch) {
	return (ch > 47 && ch < 58);
}
bool isPrior(char a, char b) {
	//1.任何运算符优先级高于(2.当a是乘除且b是加减时算优先级高
	return (b == '(' || ((a == '*' || a == '/') && (b == '+' || b == '-')));
}

要用二叉树储存表达式,首先需要将中缀表达式转化为逆波兰式,这里只实现了简单的功能,即数字只可以是0~9

std::queue<char> toRPN(char* array) {
	int i = 0;
	int cnt = 0;	//字符个数
	while (array[i++] != '\0')	//记录输入了几个字符
		cnt++;
	std::stack<char> stk;	//转化时用栈储存暂时数据
	std::queue<char> RPN;	//RPN队列用于储存最后的逆波兰式
	i = 0;	//重置i
	for (i = 0; i < cnt; i++) {
		if (isNumber(array[i]))	//c是数字时直接入队
			RPN.push(array[i]);
		else if (array[i] == '(')	//c是(时入栈
			stk.push(array[i]);
		else if (array[i] == ')') {	//c是)时,将()中的字符逐个出栈入队
			while (stk.top() != '(') {
				RPN.push(stk.top());
				stk.pop();
			}
			stk.pop();	//最后将(出栈
		}
		else {	//c是运算符时
			if (!stk.empty() && !isPrior(array[i], stk.top())) {	//栈不空且当前运算符优先级低时
				while (!isPrior(array[i], stk.top())) {	//循环出栈直到当前运算符优先级高于栈顶
					RPN.push(stk.top());
					stk.pop();
					if (stk.empty())	//栈空时停止出栈
						break;
				}
			}
			stk.push(array[i]);	//栈为空或当前运算符优先级高时直接入栈,否则循环后入栈
		}
	}
	while (!stk.empty()) {	//将栈中剩下的字符入队
		RPN.push(stk.top());
		stk.pop();
	}
	return RPN;
}

将toRPN返回的队列转化成二叉树:

BinaryTree creatTree(std::queue<char> RPN) {
	BinaryTree* TreeArray = new BinaryTree[RPN.size()];	//把每个字符储存为一棵只有根的树
	int cnt = RPN.size();	//字符数
	std::stack<BinaryTree> NodeStk;	//结点栈
	for (int i = 0; i < cnt; i++) {
		TreeArray[i].getroot()->ch = RPN.front();	//出队字符赋给当前结点
		if (!isNumber(RPN.front())) {	//c是数字时直接入栈,否则进行如下操作
			//逆波兰式的第一个数字是左操作数,第二个数字是右操作数
			TreeArray[i].getroot()->rchild = NodeStk.top().getroot();	//栈顶的结点作为右孩子
			NodeStk.pop();
			TreeArray[i].getroot()->lchild = NodeStk.top().getroot();	//然后作为左孩子
			NodeStk.pop();
		}
		NodeStk.push(TreeArray[i]);	//所有循环后栈中只剩一个结点
		RPN.pop();
	}
	BinaryTree tree = NodeStk.top();	//将最后的结点作为根结点构造树
	NodeStk.pop();
	return tree;
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值