概念
平衡二叉树,就是指二叉树中每个节点其左右孩子子树的高度,不能超过1。
二叉树递归过程的再理解
二叉树最基本的遍历,前中后序遍历,最简单的就是用递归实现。
再次看二叉树的递归过程,可以看到,其实,每个节点都被扫描了三次:
第一次,从根节点是向下递归的时候,扫描到了。
第二次,当左孩子子树递归返回时,扫描到了。
第三次,当右孩子子树递归返回时,扫描到了。
二叉树递归过程的第二个理解,就是,递归本身就是分而治之的思想,因此,每一个节点,都是要重复以上三步的,先是本身扫描,然后,左孩子返回,右孩子返回。
因此,递归过程,就是每一个节点都执行相同的过程,因此,我们可以直接只考虑一个节点的细节,就能推出整个递归。在这个过程中,每个节点需要接收子树返回的相同的数据结构,同时向上返回相同的数据结构。
因此,二叉树的递归过程,需要我们设计的地方,就是这个数据结构,这个数据结构,就是每个节点能从下面递归返回时拿到的数据,和向上返回时的数据。
这个数据结构需要能满足所有运算过程。
然后我们只需要着眼于一个节点的那三次被扫描时,拿到的数据和向上返回的数据,递归过程就能轻松被设计出来。
用递归解决二叉树问题的思路:
一、先宏观分析题目要求,完成题目要求需要什么数据。
二、设计递归传递的数据结构。
三、着眼于一个具体节点,仔细分析三次扫描时,需要的具体数据,只要一个节点能实现接收数据并返回上级,整个递归就实现了。
平衡二叉树的递归实现
一、先宏观分析题目要求,完成题目要求需要什么数据。
判断一个树是否是平衡二叉树,那么,就需要每个节点的左右孩子子树的高度,同时,还需要每个孩子子树本身是否是平衡二叉树,因为题目要求就是只要有一个不是平衡的,整棵树就不是平衡的。
二、设计递归传递的数据结构。
isB:左右子树是否平衡
height:左右子树的高度
public class ReturnData {
public boolean isB;
public int height;
public ReturnData(boolean isB, int height) {
this.isB = isB;
this.height = height;
}
}
三、着眼于一个具体节点,仔细分析三次扫描时,需要的具体数据,只要一个节点能实现接收数据并返回上级,整个递归就实现了。
分析一下,判断平衡二叉树的数据,都是从子树来的,因此,第一次扫描其实没啥用,不需要什么操作。但是,也不是所有递归第一次扫描都不需要,比如前序遍历时,节点第一次被遍历到,就要打印。
那么此时着眼于一个具体节点,拿到一个具体节点。第二次和第三次扫描时,能从子树那里拿到子树的高度,和子树是否是平衡二叉树。先判断本身是否为空,然后判断子树是否是平衡二叉树,如果不是,直接继续向上返回不是,否则,判断左右子树高度差是否大于1,然后继续向上返回就行了。
代码:
public static boolean isB(TreeNode node){
return process(node).isB;
}
public static ReturnData process(TreeNode node){
if(node==null){
return new ReturnData(true,0);
}
ReturnData left = process(node.left);
if(!left.isB){
return left;
}
ReturnData right = process(node.right);
if(!right.isB){
return right;
}
if(Math.abs(left.height-right.height)>1){
return new ReturnData(false,0);
}else {
return new ReturnData(true,Math.max(left.height,right.height)+1);
}
}