平衡二叉树
平衡二叉树:任何一个节点,左子树和右子树的高度差不能超过1。
递归遍历会来到某一个节点3次,这样想办法搜集左子树和右子数上的信息,然后信息整合做判断看看整棵树符不符合标准。
考察以每颗节点的树都是平衡的那么整棵树才是平衡二叉树,任何破坏标准的那么整个树就是不标准的。
这样的话,走到A这个节点怎么判断以A为头节点的树是平衡的?
1.左树是否平衡
2.右树是否平衡
3.左树和右树的高度
4.二者的高度差
那么这个递归函数的返回值就应该是子数的(是否平衡,高度)
先分析问题存在的各个情况的可能性,然后收集各个子过程的信息往上层返回。
public class isBalance {
public static class Node{
int value;
Node left;
Node right;
public Node(int data) {
this.value = data;
}
}
public static class ReturnData{
public boolean isB;
public int h;
public ReturnData(boolean isB, int h) {
this.isB = isB;
this.h = h;
}
}
public static ReturnData process(Node head) {
if (head == null) {
return new ReturnData(true, 0);
}
ReturnData leftData = process(head.left); //左
if (leftData.isB) {
return new ReturnData(false, 0);
}
ReturnData rightData = process(head.right); //右
if (rightData.isB) {
return new ReturnData(false, 0);
}
if (Math.abs(leftData.h - rightData.h) > 1) { //整棵
return new ReturnData(false, 0);
}
return new ReturnData(true, Math.max(leftData.h , rightData.h) + 1);
}
public static boolean isB(Node head) {
return process(head).isB;
}
}
高度套路化套路:
列出可能性
整理出返回值的类型
递归函数按照同样的类型收集子数的信息整合子树的信息加工出我的信息往上层返回
搜索二叉树
搜索二叉树:对于任意一个子树来说左子树比他小,右子树比他大。
就是二叉树的中序遍历后的结果是升序的那么就是搜素二叉树。
通常情况下搜索二叉树不含有重复节点。
利用中序遍历改成搜索二叉树
//BST
public static boolean isBST(Node head) {
int preNodeValue = Integer.MIN_VALUE;
if (head != null) {
Stack<Node> stack = new Stack<Node>();
while (!stack.isEmpty() || head != null) {
if (head != null) {
stack.push(head);
head = head.left; //不停向左移动
} else {
head = stack.pop(); //弹出当前并向右走
if (preNodeValue > head.value) { //和前一个弹出的数比较
return false;
} else {
preNodeValue = head.value;
head = head.right;
}
}
}
}
return true;
}
完全二叉树
二叉树按层遍历
一个节点有四种情况
满足一下情况才是完全二叉树
1.如果一个节点有右孩子没有左孩子一定不是完全二叉树
2.如果一个节点不是左右孩子都全,这样的话他后面遇到的所有的节点都必须是叶节点
//CBT
public static boolean isCBT(Node head) {
if (head == null) {
return true;
}
Queue<Node> queue = new LinkedList<Node>();
boolean leaf = false; //后续节点都是叶节点?
Node l = null;
Node r = null;
queue.offer(head);
while (!queue.isEmpty()) {
head = queue.poll(); //当前节点 +左右孩子
l = head.left;
r = head.right;
if ((leaf && (l != null || r != null)) //后续节点都是叶节点你还有孩子?
||
(l == null && r != null)) { //没有左孩子有右孩子
return false;
}
if (l != null) { //先加左在加右
queue.offer(l);
}
if (r != null) {
queue.offer(r);
}
if (l == null || r == null) { //只有左孩子或者没有孩子的情况 后续节点都得是叶子节点 开启判断
leaf = true;
}
}
return true;
}