March.29.2022——二叉树的相关概念及实现判断(一)
1.如何判断一棵树是搜索二叉树:
- 对于每一颗子树左边的树都比他自己小 右边比自己大
判断搜索二叉树方法:
中序遍历 后该二叉树不会降序;
解法一:代码实现
- 左树为搜索二叉树,左树上的最小值必须要大于我 返回值:是否为搜索二叉树,和最大值,最小值
- 右树为搜索二叉树,右树上的最大时要小于我 返回值:是否为搜索二叉树,和最小值,最大值
- //默认左树给我一个信息,得到三个返回值
- //默认右树给我一个信息,得到三个返回值
- //得到自己的三个返回值信息 整个递归才能链接起来
public static class ReturData(){
//默认左树给我一个信息,得到三个返回值
//默认右树给我一个信息,得到三个返回值
//得到自己的三个返回值信息 整个递归才能链接起来
public boolean isBST;
public int min;
public int max;
//构造函数
public ReturData(boolean is,int mi,int ma){
isBST = is;
min = mi;
max = ma;
}
}
public static ReturData process(Node x){
if(x == null){
return ;
}
//默认左树给我一个信息,得到三个返回值
//默认右树给我一个信息,得到三个返回值
ReturData leftdata = process(x.left);
ReturData rightdata = process(x.right);
int min = x.value;
int max = x.value;
//如果左边的节点不为空 得到与左节点比较厚的最小值
if(leftdata != null){
min = Math.min(min,leftdata.min);
max = Math.max(max,leftdata.max);
}
//如果右边的节点不为空 得到与右节点比较厚的最小值
if(rightdata != null){
min = Math.min(min,rightdata.min);
max = Math.max(max,rightdata.max);
}
boolean isBST = true;//这句话是什么意思呢?
if (leftdata != null &&(!leftdata.isBST || leftdata.max >= x.value)){
return false;
}
if (rightdata != null &&(!rightdata.isBST || rightdata.min <= x.value)){
return false;
}
//从boolean开始 有第二种解法:
boolean isBST = false;
if(
(leftdata != null?(leftdata.isBST && leftdata.max < x.value) : true)
&&
(rightdata != null?(rightdata.isBST && rightdata.min > x.value) : true)
){
isBST = true;
}
2.如何判断一棵树是完全二叉树?
概念:
什么是完全二叉树?
完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^(h-1) 个节点。
方法:宽度优先遍历——使用队列
- 任何一个节点,如果有右节点没有左节点,则直接return false;
- 在条件1不违规的情况下,如果遇到了第一个左右子不全的节点,那遍历后面的节点时,后续皆为叶节点;
//判断是否为完全二叉树 20220329
public static boolean isCBT(Node head){
if(head == null){
return true;
}
LinkedList<Node> queue = new LinkedList<>();
boolean leaf = false;
Node l = null;
Node r = null;
queue.add(head);
while (!queue.isEmpty()){
head = queue.poll();//从队列中弹出一个还在
l = head.left;
r = head.right;
if(//如果遇到了不双全的节点之后,这个节点居然不为空,不为叶节点(有左孩子或者左孩子)
(leaf && ( l!=null || r != null))
||
(l == null || r != null)//有右边的孩子没有左边的孩子直接返回false
){
return false;
}
if ( l != null){
queue.add(l);
}
if ( r != null){
queue.add(r);
}//如果左右孩子不为空,就将叶节点标记为true
if ( l == null || r == null){
leaf = true;//一旦改为true 就不会改为false了
}
}
return true;
}
3.如何判断一棵树是否为满二叉树
概念:
满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。
解法:(笨笨的麻烦的解法)
- 先求二叉树的最大深度 再求二叉树的节点个数
- 深度 L和 个数N 满足一个数学关系(N = 2的L次方-1)如果满足则return true
代码实现
public static boolean isF(Node head){
if (head == null){
return true;
}
Info data = f(head);
return data.nodes == (1<<data.height-1);
}
//递归信息体中定义了两个参数 第一为二叉树的高度 第二为二叉树的个数
public static class Info{
public int height;//二叉树的高度
public int nodes;//二叉树的节点个数
public Info(int h,int n){
height = h;
nodes =n;
}
}
public static Info f(Node x){
if(x == null){
return new Info(0,0);
}
Info leftData = f(x.left);
Info rightData = f(x.right);
int height = Math.max(leftData.height,rightData.height)+1;
int nodes = Math.max(leftData.nodes,rightData.nodes)+1;
return new Info(height,nodes);
}
4.如何判断一棵树是否为平衡二叉树
概念
平衡二叉搜索树:又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
解题思路
判断条件:这三个条件必须同时满足
-
左树为平衡二叉树
-
右树为二叉树
-
左高和右高的差不为1
我们需要得到这样的信息:
左树是否为平衡二叉树?高度是多少?
右树是否为平衡二叉树?高度是多少?
可以看出,这道题适合使用递归的方法!
解题思路
public static boolean isBalanced(Node head){
return process(head).isBalanced;
}
//定义递归函数的返回值
public static class ReturnType{
public boolean isBalanced;
public int height;
//构造函数
public ReturnType(boolean isB,int hei){
isBalanced = isB;
height = hei;
}
}
//x也需要返回两个值
//上面用ReturnType类 做来做process类的返回信息 这样就能递归从下往上知道每棵树是否平衡
public static ReturnType process(Node x){
if(x == null){//空树的时候也需要有返回值
return new ReturnType(true,0);
}
//这里括号内的内容先当黑盒处理
ReturnType leftdata = process(x.left);
ReturnType rightdata = process(x.right);
int height = Math.max(leftdata.height,rightdata.height)+1;//这里说实话不是特别明白
//上面提到的三个条件 左树为平衡树 右树为平衡树 左右两个树的高度差为1
boolean isbalanced = leftdata.isBalanced && rightdata.isBalanced && Math.abs(leftdata.height-rightdata.height)<2;
return new ReturnType(isbalanced,height);
}