代码随想录算法训练营第26天|二叉树的总结与思考

二叉树专题总结

一、公式总结

1. 二叉树

  1. 非空二叉树的叶子节点等于度为2的节点数+1,即 n 0 = n 2 + 1 n_{0}=n_{2}+1 n0=n2+1
  2. 非空二叉树的第n层至多有 2 n − 1 2^{n-1} 2n1个节点
  3. 高度为k的二叉树至多有 2 k − 1 2^{k}-1 2k1个节点
  4. 具有N个节点的二叉树的高度是 l o g 2 ⌊ ( N + 1 ) ⌋ log_{2}\left \lfloor \left ( N+1 \right ) \right \rfloor log2(N+1)层或者是 l o g 2 ⌊ ( N ) ⌋ + 1 log_{2}\left \lfloor \left ( N \right ) \right \rfloor+1 log2(N)+1
  5. 非空二叉树节点的性质: N = n 0 + n 1 + n 2 N=n_{0}+n_{1}+n_{2} N=n0+n1+n2

2. 满二叉树

满二叉树就是每一层的节点都放满了

  1. 叶子只能出现在最下一层。出现在其它层就不可能达成平衡。
  2. 非叶子结点的度一定是2。
  3. 在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多

3. 完全二叉树

完全二叉树除了最后一层节点数都满,且最后一层的节点为左排列。

  1. 叶子结点只能出现在最下层和次下层。
  2. 最下层的叶子结点集中在树的左部。
  3. 倒数第二层若存在叶子结点,一定在右部连续位置。
  4. 如果结点度为1,则该结点只有左孩子,即没有右子树。
  5. 同样结点数目的二叉树,完全二叉树深度最小。
  6. 注:满二叉树一定是完全二叉树,但反过来不一定成立。

二、二叉树的遍历

二叉树

1. 前序遍历

前序遍历的顺序是,中左右,即按照树的结构,先遍历二叉树的根节点,然后依次遍历左子树和右子树
结果为:ABDECF

代码

//递归
void traversal(TreeNode* cur,vector<int>& res)
{
	if(cur==NULL)	return;
	res.push_back(cur->val);
	traversal(root->left,res);
	traversal(root->right,res);
}

//统一迭代法
vector<int>preTraversal(TreeNode* root)
{
	vector<int>result;
	stack<TreeNide*>st;
	if(root==NULL) return result;
	st.push(root->val);
	while(!st.empty())
	{
		TreeNode* cur=st.top();
		if(cur!=NULL)
		{
			st.pop();
			if(cur->right)	st.push(cur->right);
			if(cur->left)	st.push(cur->left);
			st.push(cur);
			st.push(NULL);
		}
		else{
			st.pop();
			cur=st.top();
			st.pop();
			result.push_back(cur->val);
		}
	}
	return result;
}

2. 中序遍历

中序遍历的顺序是,左中右,即按照树的结构,先遍历二叉树的左子树,然后遍历根节点,最后遍历右子树
结果为:DBEAFC

代码:

//递归
void traversal(TreeNode* root,vector<int> result)
{
	if(root==NULL)	return;
	if(root->left)	traversal(root->left,result);
	result.push_back(root->val);
	if(root->right) traversal(root->right,result);
	
}
//统一迭代法
vector<int> inTraversal(TreeNode* root)
{
	vector<int> result;
	stack<TreeNide*>st;
	if(root!=NULL) st.push(root);
	while(!st.empty())
	{
		TreeNode* cur=st.top();
		if(cur!=NULL)
		{
			st.pop();
			if(cur->right)	st.push(cur->right);
			st.push(cur);
			st.push(NULL);
			if(cur->left) st.push(cur->left);
		}
		else{
			st.pop();
			cur=st.top();
			result.push_back(cur->val);
			st.pop();
		}
	}
	return result;
}

3. 后序遍历

后序遍历的顺序是,左右中,即按照树的结构,先遍历二叉树的左子树,然后依次遍历右子树,最后遍历根节点
结果为:DEBFCA

void traversal(TreeNode* root,vector<int>& result)
{
	if(root==NULL)	return ;
	if(root->left)	traversal(root->left,result);
	if(root->right)	traversal(root->right,result);
	result.push_back(root->val);
}

vector<int> inTraversal(TreeNode* root)
{
	vector<int> result;
	stack<TreeNide*>st;
	if(root!=NULL) st.push(root);
	while(!st.empty())
	{
		TreeNode* cur=st.top();
		if(cur!=NULL)
		{
			st.pop();
			st.push(cur);
			st.push(NULL);
			if(cur->right)	st.push(cur->right);
			if(cur->left) st.push(cur->left);
		}
		else{
			st.pop();
			cur=st.top();
			result.push_back(cur->val);
			st.pop();
		}
	}
	return result;
}

4. 层序遍历

层序遍历的就是按照一层一层的往下遍历即可。
遍历结果:ABCDEF

代码

//借助队列
vector<vector<int>> levelOrder(TreeNode* root)
{
	vector<vector<int>> result;
	queue<TreeNode*> que;
	if(root!=NULL)	que.push(root);
	while(!que.empty())
	{
		int size=que.size();
		vector<int> res;
		for(int i=0;i<size;i++)
		{
			TreeNode* node=que.front();
			que.pop();
			res.push_back(node->val);
			if(node->left) 	que.push(node->left);
			if(node->right) que.push(node->right);
		}
		result.push_back(res);
	}
	return result;			
}

三、二叉搜索树

二叉搜索树(BST,Binary Search Tree),也称二叉排序树或二叉查找树。
二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:

  1. 非空左子树的所有键值小于其根结点的键值。
  2. 非空右子树的所有键值大于其根结点的键值。
  3. 左、右子树都是二叉搜索树

其最重要重要的就是,二叉搜索树的中序遍历结果是一个有序数组

1. 二叉搜索树的搜索

注意是二叉搜索树的搜索,不是遍历。
对于二叉搜索树的搜索,我们要注意使用二叉树的特性,即左孩子的值小于根节点的值小于右孩子的值。借助这一点,我们在搜索二叉树时,便可以很方便的根据值的大小,直接搜索了,而不用依次遍历每一个节点。
力扣题目号为:700,28

2. 二叉搜索树的遍历

二叉搜索树的遍历一定要善于使用其有序性这个特点,使用中序遍历的方法,记住在递归中是左中右的顺序。
很多题都是基于二叉树的遍历上的。力扣题号为:98、530、501等

3. 二叉搜索树的删除修剪

对于二叉搜索树的节点删除,对于我本人来说,第一次见到的时候也是有点恐慌,因为,想到对于树的重建,需要对二叉搜索树做较为复杂的删除和添加操作。然而实际上,对于二叉搜索树的删除节点操作并不需要那么复杂,我们只需要在返回节点的时候,返回有用的节点就行,该节点将会自动的连接到相应的地方即可,对于需要删除的节点,并不需要删除,而是直接跳过即可。
力扣题号:450、669

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值