树的中缀表达式求值

 本段代码的功能包括:

1、用不同的前序遍历创建二叉树。

2、分别用递归或借助栈实现二叉树的前、中、后序遍历。

3、二叉树的深度、广度遍历。

4、判断一棵树是否是完全二叉树、满二叉树

5、用不同方法求所有根结点到树叶的路径、树叶到根结点的路径

6、求树的树宽、树深(树高)

7、求树的最长路径

8、输出所有叶子结点

9、计算二叉树零度、一度、二度结点的数量

10、将数的中缀表达式转化为后缀表达示,并求解树的中缀表达式

C++实现树的前中后序遍历、广度、深度优先遍历、求叶子结点、一度、二度结点数量、判断是否是完全、满二叉树、交换左右结点、求解所有根结点到树叶的路径、求最大宽度、高度、树深、求最长路径、输出所有叶子结点icon-default.png?t=LA92https://mp.csdn.net/mp_blog/creation/editor/121463277

/*
测试树:
ABC00DE0G00F00H..
ABS00C00DE00FG0H00I00
ABD00E00CF000 完全二叉树  ABD00E00CF00G00满二叉树
abcd00e00f00ig00h00
abd00e00cf00g00
123-1-14-1-156-1-18-1-1

1 2 3 0 0 5 0 0 6 7 0 0 9 0 0
*/

#include<iostream>
#include<stack> 
#include<queue> 
#define OK 1
#define maxsize 100
using namespace std;

//定义一棵树的结构体包括根结点、左孩子,右孩子(字符树)
typedef struct Tnode {
	char data;
	string combine_data;	//结点数据域(数值,可大于9),用于树的表达式求值
	struct Tnode* lchild, * rchild;
}*Btree;

//数字树
typedef struct node {
	int data;
	struct node* lchild, * rchild;
}*Bntree;

void Instruct_char(Btree T);
void Create_Tree(Btree T);
void Calculate_Tree(Btree T);
void Traverse(Btree T);
void Estimate(Btree T);
void Path(Btree T);
void Calculate_Node(Btree T);
void Swap_child(Btree T);
void Build(Btree& T);
void CreateTree(Btree& T, char ch[], int& index);

int  Tree_Width_recursion(Btree T);
int Tree_Width(Btree T);
int Tree_Depth_recursion(Btree T);
int Tree_Depth(Btree T);

void PreOrder(Btree T);
void PreOrder_recursion(Btree T);
void InOrder(Btree T);
void InOrder_recursion(Btree T);
void PostOrder(Btree T);
void PostOrder_recursion(Btree T);
void  postOrder_visit(Btree T);

void Breadth_First_Search(Btree T);
void Depth_First_Search(Btree T);
void Sequence_traverse(Btree T);
void Depth_First_Search(Btree T);

bool isComplete_Tree(Btree T);
bool isFullBinaryTree(Btree T);

void  Every_path_recursion(Btree T, char  E_path[], int  len);
void AllPath(Btree T);
void  All_path_root_leaf(Btree T, int pos);

void One_Longest_Path(Btree T);
void Find_First_Longest_Path(Btree T);
void Print_First_Longest_Path(Btree T);

void Sum_node(Btree T, int& zero, int& one, int& two);
int getAllNode(Btree T);
void PrintLeaves(Btree T);

void swap(Btree& T1, Btree& T2);
void Node_Swap(Btree& T);
void Clear();

Btree Inquire_node(Btree T, char n);

Bntree Create_Number_Tree();
void Instruct_number();
void CreateBiTree(Bntree* T);
void Index();

void Func();
int main()
{
	Btree T = nullptr;
	Bntree T1 = nullptr;
	Index();
	return 0;
}

void Clear()
{
	cin.clear();
	cin.ignore(1, EOF);
	cout << endl;
	system("cls");//清屏函数
}

void Index()
{
	Btree T=nullptr;
	int choice = 0;
	cout << "请选择:\n1、字符树\n2、数字树\n3、树的中缀表达式求值\n";
	while (cin >> choice && choice != 0)
	{
		switch (choice)
		{
		case 1:Instruct_char(T); break;
		case 2:Instruct_number(); break;
		case 3:Func(); break;
		default:cout << "输错啦,请重新输入..." << endl;
		}
	}
}

void Instruct_number()
{
	Bntree T;
	int choice = 0;
	cout << "请选择:\n1、“-1为空的树创建\n2、以零为空的树的创建\n3、返回主菜单\n";
	while (cin >> choice)
	{
		switch (choice)
		{
		case 1:Create_Number_Tree(); cout << "创建成功" << endl; Index();
		case 2:CreateBiTree(&T); cout << "创建成功" << endl; Index();
		case 3:Index(); break;
		default:cout << "输错啦,请重新输入..." << endl;
		}
	}
}

void Instruct_char(Btree T)
{
	int choice = 0;
	Clear();
	cout << "-------------------------欢迎来到树专题学习栏目-------------------\n";
	printf("请选择你想要的操作\n1、创建二叉树\n2、求树高树宽\n3、遍历输出\n4、关于树的判断\n5、\n6、路径查询\n7、求解各种结点数量\n8、交换左右孩子\n、返回主菜单");
	while (cin >> choice && choice != 0)
	{
		switch (choice)
		{
		case 1:Create_Tree(T); break;
		case 2:Calculate_Tree(T); break;
		case 3:Traverse(T); break;
		case 4:Estimate(T); break;
		
		case 6:Path(T); break;
		case 7:Calculate_Node(T); break;
		case 8:Swap_child(T); break;
		default:cout << "输错啦,请重新输入...\n" << endl;
			break;
		}
	}
	Clear();
}
void Create_Tree(Btree T)
{
	int choice = 0;
	char ch[maxsize];
	int index = 0;
	Clear();
	printf("请选择您想要进行的操作\n1、前序创建树之char数组法\n2、直接用char\n3、前序创建数字树(用-1区分是否为空)\n4、创建数字树(用0区分是否为空)\n");
	while (cin >> choice && choice != 0)
	{
		cout << "请输入前序遍历的树字符串" << endl;
		switch (choice)
		{
		case 1: Build(T); cout << "创建成功" << endl; Instruct_char(T);
		case 2:CreateTree(T, ch, index); cout << "创建成功" << endl; Instruct_char(T);
		case 3: Create_Number_Tree(); cout << "创建成功" << endl; Instruct_char(T);
		default:cout << "输错了,请重新输入...\n" << endl; break;
		}
	}
}

void Calculate_Tree(Btree T)
{
	Clear();
	int choice = 0;
	cout << "请选择:\n1、求树宽\n2、求树高\n3、返回次级页面\n4、返回主菜单\n";
	while (cin >> choice && choice != 0)
	{
		cout << "请继续输入选项" << endl;
		switch (choice)
		{
		case 1:cout << "递归求树宽:" << endl; cout << Tree_Width_recursion(T) << endl; cout << "层次遍历求树宽:" << endl; cout << Tree_Width(T) << endl; break;
		case 2:cout << "递归求树深:" << endl; cout << Tree_Depth_recursion(T) << endl; cout << "层次遍历求树深:" << endl; cout << Tree_Depth(T) << endl; break;
		case 3:Instruct_char(T);
		case 4:Index();
		default:cout << "输错啦,请重新输入...\n" << endl; break;
		}
	}
}

void Traverse(Btree T)
{
	Clear();
	int choice = 0;
	Clear();
	printf("1、前序遍历\n2、中序遍历\n3、后序遍历\n4、广度优先遍历\n5、深度优先遍历\n6、返回次级页面\n7、返回主菜单\n");
	while (cin >> choice && choice != 0)
	{
		cout << "请输入选项..." << endl;;
		switch (choice)
		{
		case 1:cout << "前序递归遍历" << endl; PreOrder_recursion(T); cout << endl; cout << "前序非递归使用栈遍历" << endl; PreOrder(T); cout << endl; break;
		case 2:cout << "中序递归遍历" << endl; InOrder_recursion(T); cout << endl; cout << "中序非递归使用栈遍历" << endl; InOrder(T); cout << endl; break;
		case 3:cout << "后序递归遍历" << endl; PostOrder_recursion(T); cout << endl; cout << "后序非递归使用栈遍历" << endl; PostOrder(T); cout << endl;
			cout << "访问标记法结果为:" << endl; postOrder_visit(T); break;
		case 4:cout << "广度优先遍历结果为:" << endl; Breadth_First_Search(T); cout << endl; cout << "层序遍历结果为:" << endl; Sequence_traverse(T); cout << endl; break;
		case 5:cout << "深度优先搜索结果为:" << endl; Depth_First_Search(T); break;
		case 6:Instruct_char(T);
		case 7:Index();
		default:cout << "输错啦,请重新输入..." << endl;
			break;
		}
	}
}

void Estimate(Btree T)
{
	Clear();
	int choice = 0;
	cout << "1、是否为完全二叉树\n2、是否为满二叉树\n3、返回次级页面\n4、返回主菜单" << endl;
	while (cin >> choice && choice != 0)
	{
		cout << "请输入" << endl;
		switch (choice)
		{
		case 1:cout << "是否为完全二叉树" << " " << isComplete_Tree(T) << endl; break;
		case 2:cout << "是否为满二叉树" << " " << isFullBinaryTree(T) << endl; break;
		case 3:Instruct_char(T);
		case 4:Index();
		default:cout << "输错啦,请重新输入..." << endl;
			break;
		}
	}
}

void Path(Btree T)
{
	Clear();
	int choice = 0;
	char E_path[maxsize];
	int len = 0;
	int pos = 0;
	char data = '0';
	cout << "请选择:1、所有叶子结点到根结点的路径\n2、最长路径\n3、查询结点\n4、返回次级页面\n5、返回主菜单\n";
	while (cin >> choice && choice != 0)
	{
		cout << "请输入..." << endl;
		switch (choice)
		{
		case 1:cout << "递归求所有叶子结点到根结点的路径" << endl; Every_path_recursion(T, E_path, len); cout << endl;
			cout << "非递归法" << endl; AllPath(T); break; cout << endl; cout << "从根结点开始到树叶的所有路径:" << endl;
			cout << "根结点到所有树叶的路径:" << endl; All_path_root_leaf(T, pos); cout << endl; break;
		case 2:cout << "其中一条最长路径:" << endl; One_Longest_Path(T); cout << endl;
			cout << "第一条最长路径:" << endl; Find_First_Longest_Path(T); Print_First_Longest_Path(T); cout << endl; break;
		case 3:cout << "输入您要查询的结点:" << endl; Inquire_node(T, data); cout << "查询结果" << Inquire_node(T, data) << endl;
		case 4:Instruct_char(T);
		case 5:Index();
		default:cout << "输错啦,请重新输入" << endl; break;
		}
	}
}

void Calculate_Node(Btree T)
{
	Clear();
	int choice = 0;
	int zero = 0, one = 0, two = 0;
	cout << "请选择:\n1、零度、一度、二度结点数量\n2、所有叶子结点数量\n3、输出所有树叶\n4、返回次级页面\n5、返回主菜单\n";
	while (cin >> choice && choice != 0)
	{
		switch (choice)
		{
		case 1:cout << "各种结点的数量" << endl; Sum_node(T, zero, one, two); cout << endl; break;
		case 2:cout << "所有结点的数量:" << endl; getAllNode(T); cout << endl; break;
		case 3:cout << "输出所有叶子结点:" << endl; PrintLeaves(T); cout << endl; break;
		case 4:Instruct_char(T);
		case 5:Index();
		default:cout << "输错啦,请重新输入..." << endl; break;
		}
	}
}

void Swap_child(Btree T)
{
	Clear();
	int choice = 0;
	Btree T1 = nullptr;
	Btree T2 = nullptr;
	swap(T1, T2);
	Node_Swap(T);
	cout << "请选择:1、查看交换后的前序遍历结果\n2、返回次级页面\n3、返回主菜单" << endl;
	cin >> choice;
	while (choice)
	{
		switch (choice)
		{
		case 1:PreOrder_recursion(T); break;
		case 2:Instruct_char(T);
		case 3:Index();
		default:cout << "输错啦,请重新输入..." << endl; break;
		}
	}
}
/*-----------------------------------------*/
//前序遍历创建树char
void Build(Btree& T) {
	char ch;
	cin >> ch;
	if (ch == '0') T = NULL;
	else {
		T = (Tnode*)malloc(sizeof(Tnode));
		T->data = ch;
		Build(T->lchild);
		Build(T->rchild);
	}
}
//前序遍历创建树,使用char数组
void  CreateTree(Btree& T, char chars[], int& i) {
	cin >> chars[i];
	if (chars[i] == '0') {
		T = NULL;
	}
	else {
		T = new Tnode;
		T->data = chars[i];
		CreateTree(T->lchild, chars, ++i);  //递归构建左子树
		CreateTree(T->rchild, chars, ++i);  //递归构建右子树
	}
}

Bntree Create_Number_Tree()
{
	Bntree T;
	int data = 0;
	cin >> data;
	if (data == -1) T = NULL;
	else
	{
		T = new node;
		T->data = data;
		T->lchild = Create_Number_Tree();
		T->rchild = Create_Number_Tree();
	}
	return T;
}
void CreateBiTree(Bntree* T)
{
	int data;
	scanf_s("%d", &data);
	if (data == 0)
		*T = NULL;
	else
	{
		*T = (Bntree)malloc(sizeof(node));
		if (!*T)
			exit(1);
		(*T)->data = data;  //生成根结点
		CreateBiTree(&(*T)->lchild);//构造左子树
		CreateBiTree(&(*T)->rchild);//构造右子树
	}
}

/*---------------------------------------*/
//前序递归 遍历
void PreOrder_recursion(Btree T) {
	if (T != NULL) {
		cout << T->data << " ";
		PreOrder_recursion(T->lchild);
		PreOrder_recursion(T->rchild);
	}
}

//前序遍历非递归版本 
//由于整个左子树被访问完才能访问右子树,故需要借助栈来保存当前子树的根节点 
void PreOrder(Btree T) {
	stack<Tnode*> S;//开辟一个栈 
	Btree p = T;//迭代指针 开始指向root 
	while (p || !S.empty()) { //只要还有结点 
		if (p) { //如果当前结点不空 
			cout << p->data << " "; //则打印当前结点 因为是先序,遇到新结点就打印 
			S.push(p);//当前结点入栈 
			p = p->lchild;//访问其左子树,向左访问结点 
		}
		else {
			p = S.top();//如果当前结点是空的,就退回到上一个结点 
			S.pop();//退栈 
			p = p->rchild;//访问其右子树 
		}
	}
}
/*----------------------------------------*/
//中序递归 遍历
void InOrder_recursion(Btree T) {
	if (T != NULL) {
		InOrder_recursion(T->lchild);
		cout << T->data << " ";
		InOrder_recursion(T->rchild);
	}
}

//中序非递归遍历  左 中 右
//根节点必须在左结点访问之后再访问,而根节点又是先于左子节点被遍历到,故要设置一个栈来保存 
void InOrder(Btree T) {
	stack<Tnode*> S;//开辟一个栈 
	Btree p = T;//迭代器 
	while (p || !S.empty()) { //如果还有结点 
		if (p) {//如果当前结点不为空 
			S.push(p);// 不要急于访问根节点,先压栈。 
			p = p->lchild;//访问左子树 
		}
		else {//如果当前节点是空的。则需要退回到上一个结点 
			p = S.top();
			S.pop();//退到该子树的根节点立即访问 
			cout << p->data << " ";
			p = p->rchild;//继续访问右子树  
		}
	}
}
/*---------------------------------------------*/
//后序递归 遍历
void PostOrder_recursion(Btree T) {
	if (T != NULL) {
		PostOrder_recursion(T->lchild);
		PostOrder_recursion(T->rchild);
		cout << T->data << " ";
	}
}

//后序遍历非递归 双栈法
//由于是左 右 中,因此入栈次序是中右左,
//先看根节点,再看右孩子,再看左孩子 
void PostOrder(Btree T) {
	stack<Tnode*> S; //遍历栈 
	stack<Tnode*> result; //结果栈 
	Btree p = T;//迭代器 
	while (p || !S.empty()) {
		if (p) { //如果当前结点不为空 
			S.push(p);//结点入栈 
			result.push(p);//结点入结果栈 
			p = p->rchild;//看其右孩子结点 
		}
		else { //如果当前结点为空 ,退到上一个结点 
			p = S.top();
			S.pop();//退栈 
			p = p->lchild;//找其左孩子结点 
		}
	}
	//输出后序序列 
	while (!result.empty()) {
		p = result.top();
		result.pop();
		cout << p->data << " ";
	}
}

// 后序遍历  访问标记法
void postOrder_visit(Btree T) {
	stack<Tnode*> S; //开辟一个栈 
	Tnode* p = T; //迭代器 
	Tnode* r = NULL; //保存最近访问过的结点 
	while (p || !S.empty()) {
		if (p) { //如果当前结点不为空 则走到该子树的最左边 

			S.push(p);
			p = p->lchild;
		}
		else { //若为空,退到上一个结点 
			p = S.top();
			if (p->rchild && p->rchild != r) { //如果存在右子树并且右子树没有被访问过 
				p = p->rchild;//那么就转向右子树继续 
				S.push(p); // 保存子树根节点 
				p = p->lchild; //继续向左访问左子树 
			}
			else {
				p = S.top();
				S.pop();//没有右子树那就可以访问根节点了 
				cout << p->data << " ";
				r = p; //标记r为最近访问的结点
				p = NULL; //当前结点置为空 ,因为这棵子树的根节点都访问完了说明这颗子树就全部访问完了,就等待退回上一个子树根节点 
			}
		}
	}
}


/*-------------------------------------*/
//层次遍历(广度遍历)求树宽度
//在层次遍历基础上。增加对每一层结点数的统计,维护max 
int Tree_Width(Btree T) {
	int level = 0;
	if (!T) return 0;
	queue<Tnode*> Q;
	Tnode* last = T; //记录每层最后一个结点,第一层最后一个节点就是根节点 
	Tnode* front = nullptr, * rear = nullptr;//记录队首结点 队尾结点 
	int ans = 0;//记录最大宽度 
	int cur = 0;//记录当前层的宽度 
	Q.push(T);//根节点入队 
	while (!Q.empty()) {
		front = Q.front();//取队首 
		Q.pop();//队首弹出 
		cur++;
		if (front->lchild) {
			Q.push(front->lchild);//如果有左孩子那么左孩子入队 
			rear = front->lchild;
		}
		if (front->rchild) {
			Q.push(front->rchild);//如果有右孩子那么右孩子入队 
			rear = front->rchild;
		}
		if (front == last) {//如果当前结点是该层最后一个结点 
			//cout<<front->data<<" ?? "<<rear->data<<endl; 
			level++;//那么层数+1 ,到达下一层 
			last = rear;//更新last,下一层的最后一个结点必然是最后入队的那个结点

			//到达每层最后一个结点时就知道了这一层的总的结点数
			//维护最大值即可 
			ans = max(ans, cur);
			cur = 0;
		}
	}
	return ans;
}

//递归遍历求树的宽度
//相当于先序遍历一遍然后把每个结点所在的层数记录下来 
//每访问一个新结点就把该层的count加上1,最终得到所有层的宽度 
void Tree_Width_recursion(Btree T, int level, int count[]) {
	if (T == NULL) return; //如果子树树根为空就不要再统计下去 
	count[level]++;//树在第level层的宽度+1 
	Tree_Width_recursion(T->lchild, level + 1, count);
	Tree_Width_recursion(T->rchild, level + 1, count);
}

int Tree_Width_recursion(Btree T) {
	int count[200] = { 0 };
	int maxx = 0;
	Tree_Width_recursion(T, 0, count);
	for (int i = 0; i < 200; i++) {
		maxx = max(maxx, count[i]);
	}
	return maxx;
}
/*--------------------------*/

//递归求树高 
int Tree_Depth_recursion(Btree T) {
	if (T == NULL) return 0;

	int rightTree = Tree_Depth_recursion(T->rchild);
	int leftTree = Tree_Depth_recursion(T->lchild);

	return (rightTree > leftTree) ? (rightTree + 1) : (leftTree + 1);
}

int Depth(Btree T)/* 再来一个求树深度的算法 */
{
	if (T == NULL)
		return 0;
	return 1 + (Depth(T->lchild) > Depth(T->rchild) ? Depth(T->lchild) : Depth(T->rchild));
	//选择左右孩子深度高的然后加上根节点这一层就是深度了
}

//层序(广度遍历)遍历求树高
int Tree_Depth(Btree T) {
	int level = 0;
	if (!T) return 0;
	queue<Tnode*> Q;
	Tnode* last = T; //记录每层最后一个结点,第一层最后一个节点就是根节点 
	Tnode* front = nullptr, * rear = nullptr;//记录队首结点 队尾结点 

	Q.push(T);//根节点入队 
	while (!Q.empty()) {
		front = Q.front();//取队首 
		Q.pop();//队首弹出 
		if (front->lchild) {
			Q.push(front->lchild);//如果有左孩子那么左孩子入队 
			rear = front->lchild;
		}
		if (front->rchild) {
			Q.push(front->rchild);//如果有右孩子那么右孩子入队 
			rear = front->rchild;
		}
		if (front == last) {//如果当前结点是该层最后一个结点 
			//cout<<front->data<<" ?? "<<rear->data<<endl; 
			level++;//那么层数+1 ,到达下一层 
			last = rear;//更新last,下一层的最后一个结点必然是最后入队的那个结点 
		}
	}
	return level;
}

/*******************************************************************************************************/
//深度优先遍历
void  Depth_First_Search(Btree root) {
	stack<Tnode*> nodeStack;  //使用C++的STL标准模板库
	nodeStack.push(root);
	Tnode* node;
	while (!nodeStack.empty()) {
		node = nodeStack.top();
		cout << node->data;//遍历根结点
		nodeStack.pop();
		if (node->rchild) {
			nodeStack.push(node->rchild);  //先将右子树压栈
		}
		if (node->lchild) {
			nodeStack.push(node->lchild);  //再将左子树压栈
		}
	}
}

//广度优先遍历
void  Breadth_First_Search(Btree root) {
	queue<Tnode*> nodeQueue;  //使用C++的STL标准模板库
	nodeQueue.push(root);
	Tnode* node;
	while (!nodeQueue.empty()) {
		node = nodeQueue.front();
		nodeQueue.pop();
		cout << node->data;//遍历根结点
		if (node->lchild) {
			nodeQueue.push(node->lchild);  //先将左子树入队
		}
		if (node->rchild) {
			nodeQueue.push(node->rchild);  //再将右子树入队
		}
	}
}

//层序遍历 队列 
void Sequence_traverse(Btree T) {
	queue<Tnode*> Q;
	Tnode* p = T;
	Q.push(T);
	while (!Q.empty()) {
		p = Q.front();
		Q.pop();
		cout << p->data << " ";
		if (p->lchild) Q.push(p->lchild);
		if (p->rchild) Q.push(p->rchild);
	}
}

/***************************************************************************************************/
/*---------------------------------------*/
//判断时否是完全二叉树
//利用性质 完全二叉树与满二叉树在层次遍历上的联系和区别,前者是后者序列的一部分 

bool isComplete_Tree(Btree T) {
	queue<Tnode*> Q;//Q中存储层次遍历序列 
	Tnode* p;
	if (!T) return true;//空树也当成完全二叉树 它是满二叉树
	Q.push(T);//首结点入队 
	while (!Q.empty()) { //如果Q不空 
		p = Q.front(); // 取出队首 
		Q.pop();
		if (p) { //如果当前结点不空,将其左右孩子入队,不管孩子空不空 
			Q.push(p->lchild);
			Q.push(p->rchild);
		}
		else { //如果当前结点为空,那么之后的序列不能有不空的结点,因为层次遍历ABCD.E显然是非法的 
			while (!Q.empty()) {
				p = Q.front();
				Q.pop();
				if (p) return false;
			}
		}
	}
	return true;
}

bool isFullBinaryTree(Btree T) {
	if (T == NULL) return true;
	typedef std::pair<Btree, int> PTI;        //pair的第二个模版参数用于记录层数
	queue<PTI> q;
	q.push(PTI(T, 1));
	PTI curnode;
	int prevdeepth = 0;
	//用flag标识第一次出现叶子结点,其后的所有结点应该是叶子结点
	int flag = false;
	while (!q.empty()) {
		curnode = q.front();
		q.pop();
		if ((curnode.first->lchild == NULL && curnode.first->rchild != NULL)  //只有右孩子
			||
			curnode.first->lchild != NULL && curnode.first->rchild == NULL)  //只有左孩子
			return false;
		if (flag) {
			if (curnode.first->lchild == NULL && curnode.first->rchild == NULL)
				;
			else
				return false;                         //叶子结点后续结点有非叶子结点
		}
		else {
			if (curnode.first->lchild == NULL && curnode.first->rchild == NULL) {
				if (curnode.second > prevdeepth) {     //每一层的第一个结点一定大于前一结点的层数
					flag = true;
				}
				else {                    //如果层数不大于前一结点层数,那一定是同一层
					return false;
				}
			}
			else {
				q.push(PTI(curnode.first->lchild, curnode.second + 1));
				q.push(PTI(curnode.first->rchild, curnode.second + 1));
			}
		}
		prevdeepth = curnode.second;
	}
	return true;
}
//查询
/*-----------------*/

/*查找元素X所在的结点*/
Btree Inquire_node(Btree T, char x)
{
	if (!T) return NULL;
	if (x == T->data) return T;
	return Inquire_node(T->lchild, x) != NULL ? Inquire_node(T->lchild, x) : Inquire_node(T->rchild, x);
}
/*----------------------*/
//递归求解所有叶子结点到根结点的路径
void Every_path_recursion(Btree T, char E_path[], int len)
{
	if (T)
	{
		if (T->rchild == NULL && T->rchild == NULL)
		{
			cout << T->data;
			for (int i = len - 1; i >= 0; i--)
				cout << E_path[i];
			cout << endl;
		}
		else
		{
			E_path[len] = T->data;
			len++;
			Every_path_recursion(T->lchild, E_path, len);
			Every_path_recursion(T->rchild, E_path, len);
			len--;
		}
	}
}

//非递归求所有路径(树叶到根结点)
void AllPath(Btree T)
{
	struct node
	{
		int parent;
		Btree node;
	}qu[100];
	Btree q;
	int front, rear, p;
	front = rear = -1;
	rear++;
	qu[rear].node = T;
	qu[rear].parent = -1;
	while (front != rear)
	{
		front++;
		q = qu[front].node;
		if (q->lchild == NULL && q->rchild == NULL)
		{
			p = front;
			while (qu[p].parent != -1)
			{
				cout << qu[p].node->data << "->";
				p = qu[p].parent;
			}
			cout << qu[p].node->data << endl;
		}
		if (q->lchild != NULL)
		{
			rear++;
			qu[rear].node = q->lchild;
			qu[rear].parent = front;
		}
		if (q->rchild != NULL)
		{
			rear++;
			qu[rear].node = q->rchild;
			qu[rear].parent = front;
		}
	}
}
//递归求解所有树根到树叶的路径
//存储所有的路径
//递归实现输出从根节点到叶子结束的所有路径

vector<char> path1(10, '0');
void All_path_root_leaf(Btree T, int pos)
{
	if (T == NULL)
		return;
	path1[pos] = T->data;
	if (T->rchild == NULL && T->lchild == NULL)
	{
		auto it = path1.begin();
		auto end = find(path1.begin(), path1.end(), '0');
		while (it != end)
		{
			cout << *it++ << " ";
		}
		cout << endl;
	}
	else
	{
		if (T->data != NULL)
		{
			All_path_root_leaf(T->lchild, pos + 1);
		}
		if (T->rchild != NULL)
		{
			All_path_root_leaf(T->rchild, pos + 1);
		}
	}
	path1[pos] = '0';
}

vector<char> path;
void Find_First_Longest_Path(Btree T)
{
	path.push_back(T->data);
	if (T->lchild == NULL && T->rchild == NULL)
		return;
	else if (Depth(T->lchild) >= Depth(T->rchild))
		Find_First_Longest_Path(T->lchild);
	else
		Find_First_Longest_Path(T->rchild);
}

void Print_First_Longest_Path(Btree T)
{
	vector<char>::iterator it;
	for (it = path.begin(); it != path.end(); it++)
		cout << *it << " ";
	path.clear();
}

void One_Longest_Path(Btree T)//其中一条
{
	if (T != NULL)//在T不为空的情况下
	{
		if (Depth(T->lchild) > Depth(T->rchild))//判断往左走还是往右走
		{
			One_Longest_Path(T->lchild);
			cout << T->data;
		}
		else
		{
			One_Longest_Path(T->rchild);
			cout << T->data;
		}
	}
}
/*-----------------*/
//求解树的所有叶子
void PrintLeaves(Btree T)
{
	if (T)
	{
		if (!T->rchild && !T->lchild)  //如果BT节点是叶子
			cout << T->data << " ";
		PrintLeaves(T->rchild);
		PrintLeaves(T->lchild);
	}
}
/*-----------------*/
//统计二叉树的各个结点数量
void Sum_node(Btree T, int& zero, int& one, int& two)
{
	if (T)
	{
		if (T->rchild != NULL && T->lchild != NULL)	two++;
		else if (T->rchild == NULL && T->lchild == NULL)	zero++;
		else one++;
		Sum_node(T->rchild, zero, one, two);
		Sum_node(T->lchild, zero, one, two);
	}
}
//求解二叉树的所有结点个数

int getAllNode(Btree T)
{
	if (NULL == T)
		return 0;

	return 1 + getAllNode(T->lchild) + getAllNode(T->rchild);
}

/*--------------*/
//交换树的左右孩子
void swap(Btree& T1, Btree& T2)
{
	Btree t;
	t = T1;
	T1 = T2;
	T2 = t;
}

void Node_Swap(Btree& T)
{
	if (T)
	{
		if (T->rchild != NULL && T->lchild != NULL)
		{
			swap(T->rchild, T->lchild);
		}
		else if (T->lchild != NULL && T->rchild == NULL)
		{
			T->rchild = T->lchild;
			T->lchild = NULL;
		}
		else if (T->lchild == NULL && T->rchild != NULL)
		{
			T->lchild = T->rchild;
			T->rchild = NULL;
		}
		else
		{
			;//空操作
		}
		Node_Swap(T->lchild);
		Node_Swap(T->rchild);
	}
	else
	{
		;//空操作
	}
}

void inOrder(Bntree T)
{
	if (T != NULL)
	{
		if ((T->data == '*' || T->data == '/') && (T->lchild->data == '+' || T->lchild->data == '-') && (T->rchild->data == '-' || T->rchild->data == '+'))//左右两边都需要加括号
		{
			cout << "(";
			inOrder(T->lchild);
			cout << ")";
			cout << T->data;
			cout << "(";
			inOrder(T->rchild);
			cout << ")";
		}
		else if ((T->data == '*' || T->data == '/') && (T->lchild->data == '+' || T->lchild->data == '-' || T->rchild->data == '-' || T->rchild->data == '+'))
		{
			inOrder(T->lchild);
			cout << T->data;
			cout << "(";
			inOrder(T->rchild);
			cout << ")";
		}
		else
		{
			inOrder(T->lchild);
			cout << T->data;
			inOrder(T->rchild);
		}
	}
}
/*-----------------------------------------树的中缀表达式求值---------------------------------------------*/
typedef struct StackNode
{
	Btree data_tree;	//存储的是二叉树
	char data_op;	//存储的是符号
	StackNode* next;
}*LinkStack;
//栈的初始化 
int InitStack(LinkStack& S)
{
	S = NULL;
	return 1;
}
//二叉树入栈
int Push_tree(LinkStack& S, Btree e)
{
	LinkStack p = new StackNode;
	p->data_tree = e;
	p->next = S;
	S = p;
	return 1;
}
//字符(运算符号)入栈
int Push_op(LinkStack& S, char e)
{
	LinkStack p = new StackNode;
	p->data_op = e;
	p->next = S;
	S = p;
	return 1;
}
//二叉树出栈
int Pop_tree(LinkStack& S, Btree& T1)
{
	if (S == NULL)	return 0;
	LinkStack p = S;
	T1 = p->data_tree;
	S = S->next;
	delete p;
	return 1;
}
//字符(运算符号)出栈
int Pop_op(LinkStack& S, char& ch)
{
	if (S == NULL)	return 0;
	LinkStack p = S;
	ch = p->data_op;
	S = S->next;
	delete p;
	return 1;
}

//取栈顶元素
char GetTop_op(LinkStack S)
{
	if (S != NULL)	return S->data_op;
	else return ' ';
}
Btree GetTop_tree(LinkStack S)
{
	if (S != NULL)	return S->data_tree;
	else return NULL;
}
/*------------------------------表达式树的创建算法------------------------------*/
//创建以T为根结点的二叉树(存储符号)
void CreateExpTree(Btree& T, Btree a, Btree b, char theta)//a是左孩子,b是右孩子,theta是数据域
{
	Btree L = new Tnode;
	L->data = theta;
	L->lchild = a;
	L->rchild = b;
	T = L;
}
//创建以T为根结点的二叉树(存储数值,可大于9)
//a是左孩子,b是右孩子,theta是数据域
void CreateExpTree_str(Btree& T, Btree a, Btree b, string theta)
{
	Btree L = new Tnode;
	L->combine_data = theta;
	L->lchild = a;
	L->rchild = b;
	T = L;
}
//比较运算符的优先级
//top是栈顶元素,ch是需要比较的元素
char Precede(char top, char ch)
{
	if (ch == ')' && top == '(')	return '=';
	else if (ch == ')')	return '>';
	if (top == ' ' || top == '(' || ch == '(') return '<';
	if (ch == '=')	return '>';
	if (top == '+' || top == '-') {
		if (ch == '+' || ch == '-')    return '>';
		else if (ch == '/' || ch == '*')	return '<';
	}
	else if (top == '*' || top == '/')    return '>';
}
//创建表达式树
//expt栈(根结点),optr栈(运算符)
void InitExpTree(char ep[], LinkStack& expt, LinkStack& optr)
{
	int n = strlen(ep);
	int i = 0;
	Btree T = NULL;	//树根
	Btree T1 = NULL;	//左子树
	Btree T2 = NULL;	//右子树
	char ch = ' ';	//弹出的符号
	string combine_str = "";	//存储数值,可大于9
	while (i != n)
	{
		if (ep[i] >= '0' && ep[i] <= '9') {		//数值(二叉树),进入expt栈中
			combine_str += ep[i];
			if (ep[i + 1] >= '0' && ep[i + 1] <= '9') {	//下一位仍是数字,需连接
				i++;
				continue;
			}
			CreateExpTree_str(T, NULL, NULL, combine_str);
			combine_str = "";	//建完数值的二叉树后string要置空
			Push_tree(expt, T);
			i++;
		}
		else {
			switch (Precede(GetTop_op(optr), ep[i]))		//比较优先级
			{
			case '<':
				Push_op(optr, ep[i]);
				i++;
				break;
			case '>':
				Pop_op(optr, ch);	//弹出上一个字符
				Pop_tree(expt, T1);	//弹出上两个数值(二叉树)
				Pop_tree(expt, T2);
				CreateExpTree(T, T2, T1, ch);	//以data_tree为根,连接T1和T2两颗子树
				Push_tree(expt, T);		//最后把T放进expt栈中
				break;
			case '=':
				Pop_op(optr, ch);
				i++;
				break;
			default:
				break;
			}
		}
	}
}
//表达式树的后序遍历
void PostOrder_get(Btree T)
{
	if (T)
	{
		PostOrder_get(T->lchild);
		PostOrder_get(T->rchild);
		if (T->lchild == NULL && T->rchild == NULL) {
			cout << T->combine_data << " ";
		}
		else cout << T->data << " ";
	}
}
/*-----------------------------表达式树的求值-------------------------------*/
//根据当前结点运算符的例子那个进行相应运算
double GetValue(char data, double lvalue, double rvalue)
{
	switch (data)
	{
	case '+':
		return lvalue + rvalue;
		break;
	case '-':
		return lvalue - rvalue;
		break;
	case '*':
		return lvalue * rvalue;
		break;
	case '/':
		return lvalue / rvalue;
		break;
	default:
		break;
	}
}
//把string字符转换成数值
double change(string str)
{
	int n = str.length(), m = str.length();
	double sum = 0;
	for (int i = 0; i < n; i++)
	{
		sum += (str[i] - '0') * pow(10, m - 1);
		m--;
	}
	return sum;
}
//遍历表达式树求表达式的值
double EvaluateExpTree(Btree T)
{
	double lvalue = 0, rvalue = 0;	//存放叶子结点的数据域初始为0
	if (T->lchild == NULL && T->rchild == NULL)
		return change(T->combine_data);	//return T->data - '0';
	else {
		lvalue = EvaluateExpTree(T->lchild);	//相当于后序遍历二叉树
		rvalue = EvaluateExpTree(T->rchild);
		return GetValue(T->data, lvalue, rvalue);
	}
}

void Func()
{
	Clear();
	//char ep[] = "3+4*(6-1)-8/2#";	//"(18-2)*(13-7)+4/2#";
	char s[maxsize];
	int i = 0;
	cout << "请输入表达式 ..." << endl;
	while (cin >> s && s != "=")
	{
		if (s[0] == '0')
			Index();
		LinkStack expt;
		InitStack(expt);	//初始化expt栈(根结点)
		LinkStack optr;
		InitStack(optr);	//初始化optr栈(运算符)
		InitExpTree(s, expt, optr);	//构建表达式树
		Btree T = NULL;
		Pop_tree(expt, T);	//获取最后建好的二叉树

		cout << "初始的中缀表达式: " << s << endl;	 //初始中缀表达式

		cout << "后序遍历: ";
		PostOrder_get(T);		//后序遍历结果
		cout << endl;
		cout << "表达式求值后的结果: " << EvaluateExpTree(T) << endl;	//表达式树求值结果
		i++;
		if (i > 0)
			cout << "请继续输入表达式求值或输入 0 返回主菜单..." << endl;
	}
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值