二叉树所有基本操作

概述

二叉树(Binary Tree)是n (n>0)个结点所构成的集合,它或为空树( n=0);或为非空树。对于非空树T满足:

1)有且仅有一个称为根的结点;

2)除根结点以外,其余结点分为两个互不相交的子集T1和T2,分别称为T的左子树和右子树,且T1和T2本身都是二叉树。

1.初始化

此处对于二叉树的初始化需要利用到递归的特性,'#'代表的是空节点,这将不会再建立新的子树

如下图,若要存储该树,则需要输入123##4##56### ,最后一个#代表的是5节点的右子树为空

typedef struct Bnode
{
	char data;
	Bnode* lchild, * rchild;
}Bnode, * BTree;

void initBTree(BTree& T)
{
	char ch;
	cin >> ch;
	if (ch == '#')
	{
		T = NULL;
	}
	else
	{
		T = new Bnode; //建立新的节点
		T->data = ch;
		initBTree(T->lchild); //建立左子树
		initBTree(T->rchild); //建立右子树
	}

2.递归先序

按照根的访问顺序不同,根在前面称为先序遍历(DLR),根在中间称为中序遍历(LDR),根在最后称为后序遍历(LRD)。

算法步骤:

先序遍历是指先访问根,然后先序遍历左子树,再先序遍历右子树,即 DLR。

void recursion_F(BTree& T)
{
	if (T == nullptr)
	{
		return;
	}

	cout << T->data << " ";
	recursion_F(T->lchild);
	recursion_F(T->rchild);
}

3.递归中序

和先序思想一致,不过是先访问左子树,再根,再右子树.

void recursion_M(BTree& T)
{
	if (T == NULL)
	{
		return;
	}

	recursion_M(T->lchild);
	cout << T->data << " ";
	recursion_M(T->rchild);
}

4.递归后序

先左再右再根

void recursion_L(BTree& T)
{
	if (T == NULL)
	{
		return;
	}

	recursion_L(T->lchild);
	recursion_L(T->rchild);
	cout << T->data << " ";
}

5.层次遍历

思想:

根节点先入队,如果队列不为空,则该根节点的孩子节点全部入队,没有就算了,首先入的是左孩子,再右孩子.判断队列不为空,继续出队,该左孩子出队后,其左孩子的左孩子与右孩子入队,如果没有就算了,如此反复,知道队列为空结束.

bool level_traverse(BTree T)
{
	BTree e;  //保留节点的数据
	if (T == NULL)
	{
		return false;
	}
	queue<BTree>Q;
	Q.push(T);
	while (!Q.empty())
	{
		e = Q.front();
		Q.pop();
		cout << e->data << " ";
		if (e->lchild != NULL)
		{
			Q.push(e->lchild);
		}
		if (e->rchild != NULL)
		{
			Q.push(e->rchild);
		}
	}
	return true;
}

6.树的深度

思想:

对于人来说,树的深度就是数一数树的层数,上图的深度就为3,可是计算机却不能如此计算,拿一个最简单的二叉树举例.

如果节点的度数为0,那么深度为0+1,这就是为什么当节点为空要返回0的原因,该根节点的左子树深度为1,右子树深度为2,比较哪个大,谁大就+1 那么该值就是树的深度

 

 

int Depth(BTree T)
{
	int m, n;
	if (T == NULL)
	{
		return 0;
	}
	else
	{
		m = Depth(T->lchild);//左子树深度
		n = Depth(T->rchild);//右子树深度
		if (m > n)
		{
			return m + 1;
		}
		else
		{
			return n + 1;
		}
	}
}

7.叶子节点

利用递归特性找到树的最底层(叶子节点),判断是否为叶子节点的方法就是看他的左右子树是否为空,是就记录下这是个叶子节点返回1,给上一次递归的代码

int Leaf_Node(BTree T)
{
	if (T == NULL)
	{
		return 0;
	}
	else
	{
		if (T->lchild == NULL && T->rchild == NULL)
		{
			return 1;
		}
		else
		{
			return Leaf_Node(T->lchild) + Leaf_Node(T->rchild);
		}
	}
}

8.节点总数

举一个简单的例子

左孩子的左右子树都为空,所以左孩子这棵树的节点个数为0(左)+0(右)+1,剩下来的复杂树就交给递归好了

 

int Calculate_BT_Node(BTree T)
{
	if (T == NULL)
	{
		return 0;
	}
	else
	{
		return Calculate_BT_Node(T->lchild) + Calculate_BT_Node(T->rchild) + 1;
	}
}

9.先序序列与中序遍历还原二叉树

想要写出代码,首先需要自己了解怎样还原才行

1.根据先序找到根节点

2.在中序的根节点左边为左子树,右边为右子树

3.找到左子树的根左右

4.找到右子树的根左右

 

BTree F_M_CreatBTree(char* pre, char* mid, int len)
{
	if (len == 0)//当序列长度为0,说明已经还原完成
	{
		return NULL;
	}
	char ch = pre[0];  记录根节点
	int index = 0;     记录根节点在中序的位置
	while (mid[index] != ch)
	{
		index++;
	}

	BTree T = new Bnode; // 找到了根节点,创建根节点
	T->data = ch;
	T->lchild = F_M_CreatBTree(pre + 1, mid, index); //左子树的递归
	T->rchild = F_M_CreatBTree(pre + index + 1, mid + index + 1, len - index - 1);//右子树的递归

	return T;
}

10后序序列与中序序列还原二叉树

和9是基本一致不过多赘述,自己画个图就理解了

BTree L_M_CreatBTree(char* last, char* mid, int len)
{
	if (len == 0)
	{
		return NULL;
	}
	char ch = last[len - 1];
	int index = 0;
	while (mid[index] != ch)
	{
		index++;
	}
	BTree T = new Bnode;
	T->data = ch;
	T->lchild = L_M_CreatBTree(last, mid, index);
	T->rchild = L_M_CreatBTree(last + index, mid + index + 1, len - index - 1);

	return T;
}

完整代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include <queue>
using namespace std;

typedef struct Bnode
{
	char data;
	Bnode* lchild, * rchild;
}Bnode, * BTree;

void initBTree(BTree& T)
{
	char ch;
	cin >> ch;
	if (ch == '#')
	{
		T = NULL;
	}
	else
	{
		T = new Bnode;
		T->data = ch;
		initBTree(T->lchild);
		initBTree(T->rchild);
	}
}

void recursion_F(BTree& T)
{
	if (T == nullptr)
	{
		return;
	}

	cout << T->data << " ";
	recursion_F(T->lchild);
	recursion_F(T->rchild);
}

void recursion_M(BTree& T)
{
	if (T == NULL)
	{
		return;
	}

	recursion_M(T->lchild);
	cout << T->data << " ";
	recursion_M(T->rchild);
}

void recursion_L(BTree& T)
{
	if (T == NULL)
	{
		return;
	}

	recursion_L(T->lchild);
	recursion_L(T->rchild);
	cout << T->data << " ";
}

bool level_traverse(BTree T)
{
	BTree e;
	if (T == NULL)
	{
		return false;
	}
	queue<BTree>Q;
	Q.push(T);
	while (!Q.empty())
	{
		e = Q.front();
		Q.pop();
		cout << e->data << " ";
		if (e->lchild != NULL)
		{
			Q.push(e->lchild);
		}
		if (e->rchild != NULL)
		{
			Q.push(e->rchild);
		}
	}
	return true;
}

BTree F_M_CreatBTree(char* pre, char* mid, int len)
{
	if (len == 0)
	{
		return NULL;
	}
	char ch = pre[0];
	int index = 0;
	while (mid[index] != ch)
	{
		index++;
	}

	BTree T = new Bnode;
	T->data = ch;
	T->lchild = F_M_CreatBTree(pre + 1, mid, index);
	T->rchild = F_M_CreatBTree(pre + index + 1, mid + index + 1, len - index - 1);

	return T;
}

void F_M_Test(BTree& T)
{
	int n = 0;
	char pre[100], mid[100];
	cout << "请输入二叉树有多少元素" << endl;
	cin >> n;
	cout << "请输入先序序列" << endl;
	for (int i = 0; i < n; i++)
	{
		cin >> pre[i];
	}
	cout << "请输入中序序列" << endl;
	for (int i = 0; i < n; i++)
	{
		cin >> mid[i];
	}
	T = F_M_CreatBTree(pre, mid, n);
	cout << "还原后的二叉树后序序列为:" << endl;
	recursion_L(T);
}

BTree L_M_CreatBTree(char* last, char* mid, int len)
{
	if (len == 0)
	{
		return NULL;
	}
	char ch = last[len - 1];
	int index = 0;
	while (mid[index] != ch)
	{
		index++;
	}
	BTree T = new Bnode;
	T->data = ch;
	T->lchild = L_M_CreatBTree(last, mid, index);
	T->rchild = L_M_CreatBTree(last + index, mid + index + 1, len - index - 1);

	return T;
}

void L_M_Test(BTree& T)
{
	int n = 0;
	char last[100], mid[100];
	cout << "请输入有多少元素" << endl;
	cin >> n;
	cout << "请输入后序序列" << endl;
	for (int i = 0; i < n; i++)
	{
		cin >> last[i];
	}
	cout << "请输入中序序列" << endl;
	for (int i = 0; i < n; i++)
	{
		cin >> mid[i];
	}
	T = L_M_CreatBTree(last, mid, n);
	cout << "还原后的二叉树先序序列为:" << endl;
	recursion_F(T);
}

int Depth(BTree T)
{
	int m, n;
	if (T == NULL)
	{
		return 0;
	}
	else
	{
		m = Depth(T->lchild);
		n = Depth(T->rchild);
		if (m > n)
		{
			return m + 1;
		}
		else
		{
			return n + 1;
		}
	}
}

void Depth_Test(BTree T)
{
	int ret = Depth(T);
	cout << "树深度为:" << endl << ret << endl;
}

int Leaf_Node(BTree T)
{
	if (T == NULL)
	{
		return 0;
	}
	else
	{
		if (T->lchild == NULL && T->rchild == NULL)
		{
			return 1;
		}
		else
		{
			return Leaf_Node(T->lchild) + Leaf_Node(T->rchild);
		}
	}
}

void Leaf_Node_Test(BTree T)
{
	int ret = Leaf_Node(T);
	cout << "叶子数为:" << endl << ret << endl;
}

int Calculate_BT_Node(BTree T)
{
	if (T == NULL)
	{
		return 0;
	}
	else
	{
		return Calculate_BT_Node(T->lchild) + Calculate_BT_Node(T->rchild) + 1;
	}
}

void Calculate_BT_Node_Test(BTree T)
{
	int ret = Calculate_BT_Node(T);
	cout << "节点总数为:" << endl << ret << endl;
}

void show_menu()
{
	cout << "1.先序遍历" << endl;
	cout << "2.中序遍历" << endl;
	cout << "3.后序遍历" << endl;
	cout << "4.层次遍历" << endl;
	cout << "5.计算二叉树深度" << endl;
	cout << "6.计算二叉树叶子数" << endl;
	cout << "7.计算二叉树节点总数" << endl;
	cout << "8.先序序列与中序遍历还原二叉树" << endl;
	cout << "9.后序序列与中序序列还原二叉树" << endl;
	cout << "------------------------------------" << endl;
	cout << "请输入二叉树,#表示无节点" << endl;
}

int main()
{
	show_menu();
	BTree T;
	initBTree(T);
	int select = 0;
	

	while (true)
	{
		cin >> select;
		switch (select)
		{
		case 1:
			recursion_F(T);
			cout << endl;
			break;
		case 2:
			recursion_M(T);
			cout << endl;
			break;
		case 3:
			recursion_L(T);
			cout << endl;
			break;
		case 4:
			level_traverse(T);
			break;
		case 5:
			Depth_Test(T);
			break;
		case 6:
			Leaf_Node_Test(T);
			break;
		case 7:
			Calculate_BT_Node_Test(T);
			break;
		case 8:
			F_M_Test(T);
			break;
		case 9:
			L_M_Test(T);
		default:
			break;
		}
	}

	system("pause");
	return EXIT_SUCCESS;
}

 

 

  • 24
    点赞
  • 135
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值