二叉树,树的基础

目录

树的基础

二叉树(Binary Tree)

二叉搜索树BST

平衡搜索树

递归创建二叉树(前序)

二叉树递归遍历(深度)

创建完全二叉树(前序)

二叉树非递归遍历(深度)

二叉树的层序遍历


树的基础

构建最小堆没补充,大家可以搜一下

树:Tree。

路径:从根到叶子,例如A->C->F。

路径长度:边的数目。

度:孩子数目。

二叉树(Binary Tree)

性质:

(1)k层的二叉树总结点最多为2^{k}-1个。

(2)k层的二叉树总叶子节点最多2^{k-1}个。

  前两条结论基于满二叉树。

(3)任意二叉树中度为0的节点总比度为2的节点多一个。

总节点数=度0节点+度1节点+度2节点。

总节点数=度0节点*0+度1节点*1+度2节点*2+1。

度0节点=度2节点+1。

(4)n个节点的完全二叉树{log_{2}}^{n}+1层。

完全二叉树:树中只允许最后一层有空缺,并且其空缺方式从右向左连续空缺。

例:完全二叉树叶子节点有124个,总结点最多有多少个:n0=124,n2=123,n1要么为0要么为1,得248。

第四条结论是2^{k-1}-1<n<2^{k}-1得出的层数。

(5)一颗完全二叉树按照从上到下,从左到右的顺序从1开始编号,编号为i的节点如果满足2i<=n,则有左孩子,如果满足2i+1<=n,则有右孩子,父亲节点编号为1~n/2。

二叉搜索树BST

树中任意一个父亲节点都要满足,值大于整棵左子树,小于整颗右子树。

优化让BST分布均匀,就引出了平衡搜索树。

平衡搜索树

二叉平衡搜索树:AVL树,树中任意节点左右子树高度差不超过1。

红黑树:RBT,由颜色定的平衡。

B/B+树:多路平衡搜索树。

递归创建二叉树(前序)

用0来做标记,这种方法有个弊端,有一个数不能用比如这个0.

#include<iostream>
using namespace std;
typedef struct Tree
{
	int val;
	struct Tree* left;
	struct Tree* right;
}BinaryTree;
void PreorderTraversal(BinaryTree* Ptree)
{
	if (Ptree == NULL)return;
	printf("%d ", Ptree->val);
	PreorderTraversal(Ptree->left);
	PreorderTraversal(Ptree->right);
}
void CreateBinaryTree(BinaryTree** Root)
{
	int num;
	cin >> num;
	if (num == 0)return;
	*Root= (BinaryTree*)malloc(sizeof(BinaryTree));
	(*Root)->val = num;
	(*Root)->left = NULL;
	(*Root)->right = NULL;
	CreateBinaryTree(&(*Root)->left);
	CreateBinaryTree(&(*Root)->right);
}
int main()
{
	BinaryTree* Root = NULL;
	CreateBinaryTree(&Root);
	PreorderTraversal(Root);
	return 0;
}

二叉树递归遍历(深度)

前序:根 左 右

中序:左 根 右

后序: 左 右 根

前:BFAGDMCQRN

中:AFGMDBCRQN

后:AMDGFRNQCB

前序递归遍历:(1)打印当前父亲节点(2)处理左子树(3)处理右子树,终止条件树为空。

中后略。

代码里就直接创建个固定的二叉树,来看看前中后序遍历。

#include<iostream>
using namespace std;
typedef struct Tree
{
	int val;
	struct Tree* left;
	struct Tree* right;
}BinaryTree;
BinaryTree* Create()
{
	BinaryTree* Root = NULL;
	Root = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->val = 1;

	Root->left= (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->left->val = 2;

	Root->left->left = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->left->left->val = 4;
	Root->left->left->left = NULL;
	Root->left->left->right = NULL;

	Root->left->right = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->left->right->val = 5;
	Root->left->right->left = NULL;
	Root->left->right->right = NULL;

	Root->right = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->right->val = 3;
	Root->right->left = NULL;
	Root->right->right = NULL;
	return Root;
}
void PreorderTraversal(BinaryTree* Ptree)
{
	if (Ptree == NULL)return;
	printf("%d ", Ptree->val);
	PreorderTraversal(Ptree->left);
	PreorderTraversal(Ptree->right);
}
void InorderTraversal(BinaryTree* Ptree)
{
	if (Ptree == NULL)return;
	InorderTraversal(Ptree->left);
	printf("%d ", Ptree->val);
    InorderTraversal(Ptree->right);
}
void LastorderTraversal(BinaryTree* Ptree)
{
	if (Ptree == NULL)return;
	LastorderTraversal(Ptree->left);
	LastorderTraversal(Ptree->right);
	printf("%d ", Ptree->val);
}
int main()
{
	BinaryTree* ptree = Create();
	PreorderTraversal(ptree);
	puts("");
	InorderTraversal(ptree);
	puts("");
	LastorderTraversal(ptree);
	puts("");
	return 0;
}

创建完全二叉树(前序)

步骤:

(1)当前节点数组的申请

(2)数据向数组赋值

(3)指针关联(0~n/2)

#include<iostream>
using namespace std;
typedef struct Tree
{
	int val;
	struct Tree* left;
	struct Tree* right;
}BinaryTree;
void PreorderTraversal(BinaryTree* Ptree)
{
	if (Ptree == NULL)return;
	printf("%d ", Ptree->val);
	PreorderTraversal(Ptree->left);
	PreorderTraversal(Ptree->right);
}
BinaryTree* CreateCBT(int arr[], int len)
{
	if (arr == NULL || len <= 0)return NULL;
	//节点数组申请
	BinaryTree* ptree = (BinaryTree*)malloc(sizeof(BinaryTree) * len);
	for (int i = 0; i < len; i++)
	{
		ptree[i].val = arr[i];
		ptree[i].left = NULL;
		ptree[i].right = NULL;
	}
	//左右关系关联
	for (int i = 0; i < len / 2; i++)
	{
		if (2 * i + 1 <= len - 1)ptree[i].left = &(ptree[2 * i + 1]);
		if (2 * i + 2 <= len - 1)ptree[i].right = &(ptree[2 * i + 2]);
	}
	return ptree;
}
int main()
{
	BinaryTree* Root = NULL;
	int arr[] = { 1,2,3,4,5,6,7,8,9 };
	Root = CreateCBT(arr, sizeof(arr) / sizeof(arr[0]));
	PreorderTraversal(Root);
	return 0;
}

二叉树非递归遍历(深度)

(1)首先我们要借助栈

(2)处理:对根非空就打印保存,对左子树非空就打印保存,对左子树非空就打印保存,pop掉

(3)无节点等待处理结束

 过程图:

前序:打印保存根节点,并往左找直到为空。

挨个出栈判断有没有右节点,2有右节点,右节点入栈并打印,然后往左找,直到为空重复上面操作。

3打印出栈,3往右找为空,栈空了,结束。

中序和前序一样,只不过不在如入栈时就打印,而是打印栈顶值,pop前打印。

后序:右子在跟上面标记一下,其余的和前序一样,然后需要判断一下右侧情况,右侧为空,或者处理过那就print,未处理就处理右子树。

#include<iostream>
#include<stack>
using namespace std;
typedef struct Tree
{
	int val;
	struct Tree* left;
	struct Tree* right;
}BinaryTree;
BinaryTree* Create()
{
	BinaryTree* Root = NULL;
	Root = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->val = 1;

	Root->left = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->left->val = 2;

	Root->left->left = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->left->left->val = 4;
	Root->left->left->left = NULL;
	Root->left->left->right = NULL;

	Root->left->right = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->left->right->val = 5;
	Root->left->right->left = NULL;
	Root->left->right->right = NULL;

	Root->right = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->right->val = 3;
	Root->right->left = NULL;
	Root->right->right = NULL;
	return Root;
}
void Per(BinaryTree* Root)
{
	stack<BinaryTree*>s;
	while (1) {
		while (Root)
		{
			cout << Root->val << " ";
			s.push(Root);
			Root = Root->left;
		}
		if (s.empty())break;
		Root = s.top();
		s.pop();
		Root = Root->right;
	}
	cout << endl;
}
void Indx(BinaryTree* Root)
{
	stack<BinaryTree*>s;
	while (1) {
		while (Root)
		{
			s.push(Root);
			Root = Root->left;
		}
		if (s.empty())break;
		Root = s.top();
		cout << Root->val << " ";
		s.pop();
		Root = Root->right;
	}
	cout << endl;
}
void Last(BinaryTree* Root)
{
	stack<BinaryTree*>s;
	BinaryTree* mark = NULL;
	while (1) {
		while (Root)
		{
			s.push(Root);
			Root = Root->left;
		}
		if (s.empty())break;
		if (s.top()->right == NULL || s.top()->right == mark)
		{
			//不赋空一直卡再那了就
			Root = NULL;
			cout << s.top()->val << " ";
			mark = s.top();
			s.pop();
		}
		else
		{
			Root = s.top()->right;
		}
	}
	cout << endl;
}
int main()
{
	BinaryTree* Root = Create();
	Per(Root);
	Indx(Root);
	Last(Root);
	return 0;
}

二叉树的层序遍历

首先我们要借助队列来存储等待处理元素。

步骤:

(1)创建队列。

(2)根节点入队。

(3)处理:1.弹出,打印。2.非空左右节点入队等待处理。

#include<iostream>
#include<queue>
using namespace std;
typedef struct Tree
{
	int val;
	struct Tree* left;
	struct Tree* right;
}BinaryTree;
BinaryTree* Create()
{
	BinaryTree* Root = NULL;
	Root = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->val = 1;

	Root->left = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->left->val = 2;

	Root->left->left = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->left->left->val = 4;
	Root->left->left->left = NULL;
	Root->left->left->right = NULL;

	Root->left->right = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->left->right->val = 5;
	Root->left->right->left = NULL;
	Root->left->right->right = NULL;

	Root->right = (BinaryTree*)malloc(sizeof(BinaryTree));
	Root->right->val = 3;
	Root->right->left = NULL;
	Root->right->right = NULL;
	return Root;
}
void leve(BinaryTree* Root)
{
	if (Root == NULL)return;
	queue<BinaryTree*>q;
	//根入队
	q.push(Root);
	while (!q.empty())
	{
		Root = q.front();
		cout << Root->val << " ";
		q.pop();
		//非空左右入队
		if (Root->left != NULL)
		{
			q.push(Root->left);
		}
		if (Root->right != NULL)
		{
			q.push(Root->right);
		}
	}
}
int main()
{
	BinaryTree* Root = NULL;
	Root=Create();
	leve(Root);
	return 0;
}
  • 29
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值