树形结构
->是一种非线性的数据结构
-> 树型结构中,子树之间不能有交集
-> 一颗具有N个节点的树,有N-1条边
->根节点
![](https://i-blog.csdnimg.cn/blog_migrate/c5f76c23361ce37d3ea7098484a57d2b.png)
-> 节点的度:一个节点含有子树的个数
树的度:一棵树中,所有节点度的最大值
叶子节点/终端节点:度为0
节点的层次:从根节点开始,根节点所在为第一层
树的高度/深度:树中结点的最大层
2、二叉树
概念:
二叉树不存在度大于2的节点
2.两种特殊的二叉树
(1)满二叉树
一棵二叉树,每层的节点数都达到了最大。
如果有k层,那么第k层上的节点数:2^(k-1),整棵树的节点数:2^k-1;
![](https://i-blog.csdnimg.cn/blog_migrate/df6d41b8c4a357580e1cbab47170531c.png)
(2)完全二叉树
![](https://i-blog.csdnimg.cn/blog_migrate/225fe98b68a192669e0c56c6da5f3a5e.png)
3.二叉树的性质
(1)若根节点为第一层,则一棵二叉树第k层上最多有2^(k-1)个节点;
(2)若只有根节点的二叉树的深度为1,那么深度为k的二叉树的最大节点总数:2^k-1;
(3)对于任意一棵二叉树,叶节点的个数为n0,度为2的节点个数为n2,则有:n0=n2+1;
(4)具有N个节点的二叉树的深度:log2(N+1)向上取整;
(5)将根节点编号为0,
已知父亲节点为i,那么左孩子序号:2*i+1;右孩子序号:2*i+2
已知孩子节点为i,那么父亲节点:(i-1)/2;
4.二叉树的遍历
(1)前序遍历
根——>左——>右
![](https://i-blog.csdnimg.cn/blog_migrate/564000875ad3f0bc215dfbca70279998.png)
(2)中序遍历
左——>根——>右
![](https://i-blog.csdnimg.cn/blog_migrate/99ea5997aeb9a03b29fff5b99e4cd8b8.png)
(3)后序遍历
左——>右——>根
![](https://i-blog.csdnimg.cn/blog_migrate/af75690acc1b2769ebedf498b910c62c.png)
(4)层序遍历
从左到右,从上往下
![](https://i-blog.csdnimg.cn/blog_migrate/218fca3e74a0f30f2a022c29f75d6c52.png)
练习题:
1.已知前序,中序,求后序
eg:
![](https://i-blog.csdnimg.cn/blog_migrate/26f98c12fd82233dd27c56dd1a71f4dc.png)
2.已知中序、后序,求前序
![](https://i-blog.csdnimg.cn/blog_migrate/7f30e6f9fe4a685451204e367de0d8fa.png)
5.代码实现二叉树的遍历
(1)前序遍历
void preOrder(TreeNode root){
if(root == null) return;
System.out.print(root.val + " " );
preOrder(root.left);
preOrder(root.right);
}
(2)中序遍历
void MidOrder(TreeNode root){
if(root == null) return;
MidOrder(root.left);
System.out.print(root.val + " " );
MidOrder(root.right);
}
(3)后序遍历
void PostOrder(TreeNode root){
if(root == null) return;
PostOrder(root.left);
PostOrder(root.right);
System.out.print(root.val + " " );
}
3、二叉树的基本操作
(1)计算树中节点的个数
//法1:
int size1(TreeNode root){
if(root === null) return 0;
return size1(root.left)+size1(root.right)+1;
}
//法2
public int size = 0;
void size2(TreeNode root){
if(root === null) return 0;
size++;
size2(root.left);
size2(root.right);
}
![](https://i-blog.csdnimg.cn/blog_migrate/0b2ca6366e1e5ee55fa04ce7121e56ca.png)
(2)获取叶子节点的个数
//法1
int getLeafSize(TreeNode root){
if(root == null) return 0;
if(root.left == null && root.right == null){
return 1;
}
return getLeafSize(root.left)+getLeafSize(root.right);
}
//法2
public int leafSize = 0;
void getLeafSize2(TreeNode root){
if(root == null) return;
if(root.left == null && root.right == null){
leafSize++;
}
getLeafSize2(root.left);
getLeafSize2(root.right);
}
(3)求第k层的节点个数
int getKNodeCount(TreeNode root,int k){
if(root == null) return 0;
if(k == 1){
return 1;
}
return getKNodeCount(root.left,k-1)+getKNodeCount(root.right,k-1);
}
(4)求二叉树的高度
int GetHeight(TreeNode root){
if(root == null) return 0;
int LeftHeight = GetHeight(root.left);
int RightHeight = GetHeight(root.right);
return (LeftHeight > RightHeight ? LeftHeight : RightHeight )+1;
}
(5)查找当前是否存在要找的节点
TreeNode find(TreeNode root,int key){
if(root == null) return null;
if(root.val == key){
return root;
}
TreeNode ret1 = find(root.left);
if(ret1 != null){
return ret1;
}
TreeNode ret2 = find(root.right);
if(ret2 != null){
return ret2;
}
return null;
}
![](https://i-blog.csdnimg.cn/blog_migrate/4fcc08af9e4d20bcdfce406ffa953d38.png)