如何判断一颗二叉树是否是搜索二叉树?
搜索二叉树
每个子树头节点的左孩子比它小,右孩子比它大
经典的搜索二叉树没有重复的数
判断
将二叉树按照中序遍历,判断是否为升序
1、先将整棵树中序遍历再判断是否升序
//中序遍历
public static ArrayList<Node> traverse_medium(Node node) {
if (node == null) {
return null;
}
ArrayList<Node> list = new ArrayList<>();
traverse_medium(node.left);
//输出改为存储入集合之中
list.add(node);
traverse_medium(node.right);
return list;
}
//判断搜索二叉树
public static boolean is_bst_one(ArrayList<Node> list) {
for (int i = 0; i < list.size() - 2; i++) {
if (list.get(i).value >= list.get(i + 1).value) {//这里认为等于不可行
return false;
}
}
return true;
}
2、在中序遍历的过程中判断是否升序
(1) 使用递归的中序遍历
//判断搜索二叉树
public static boolean is_bst_two1(Node node) {
if (node == null) {
return true;//认为空二叉树是搜索二叉树
}
int preValue = Integer.MIN_VALUE;
//判断左子树是否为搜索二叉树
boolean isLeftBst = is_bst_two1(node.left);
//中序遍历的第二轮,输出改为判断
//如果左树不是搜索二叉树,那么整棵树一定不是搜索二叉树
if (!isLeftBst) {
return false;
}
if (node.value > preValue) {
preValue = node.value;//递归逐层向下找,会最先找到最左侧的节点,逐层向上比较,preValue逐层向上赋值
} else {//node.value <= preValue,不满足搜索二叉树条件
return false;
}
//在左子树为搜索二叉树的前提下,如果右子树为搜索二叉树,那么整棵树一定都是搜索二叉树
return is_bst_two1(node.right);
}
(2)不使用递归的中序遍历
//判断搜索二叉树
public static boolean is_bst_two2(Node node) {
if (node == null) {
return true;//认为空二叉树是搜索二叉树
}
int preValue = Integer.MIN_VALUE;
Stack<Node> stack = new Stack<Node>();
while (!stack.isEmpty() || node != null) {
if (node != null) {
stack.push(node);
node = node.left;//整个左子树入栈
} else {
node = stack.pop();//出栈
//输出变为比较
if (node.value <= preValue) {//不满足条件
return false;
} else {//node.value > preValue,满足条件
preValue = node.value;//preValue逐层向上
}
node = node.right;//如果右节点为null则弹出下一个,如果不为null则将右节点弹入栈
}
}
return true;
}
如何判断一颗二叉树是否是完全二叉树?
完全二叉树
二叉树从左向右依次变满(左图为满二叉树,右图为普通的完全二叉树)
判断
二叉树按宽度遍历
条件1:如果某一个子树的头节点有右孩子没有左孩子,返回false
条件2:在条件1的前提下,如果有一个节点左右孩子不双全,后续的节点都是叶节点(它右侧的所有节点都没有子节点)
//判断完全二叉树
public static boolean isCBT(Node node) {
if (node == null) {
return true;//空二叉树认为是完全二叉树
}
boolean notBoth = false;//记录是否遇到不双全的节点
Node left = null;
Node right = null;
Queue<Node> queue = new LinkedList<>();
queue.add(node);
while (!queue.isEmpty()) {
Node node0 = queue.poll();
if ((left == null && right != null)//不满足条件1:左节点null且右节点不为null
|| (notBoth && (left != null || right != null))) {//不满足条件2:遇到不双全的节点但后面的节点不为叶节点
return false;
}
if (node0.left != null) {
queue.add(node0.left);//先右节点入队列
}
if (node0.right != null) {
queue.add(node0.right);//再左节点入队列
}
if (left == null || right == null) {//不双全的节点
notBoth = true;
}
}
return true;
}
如何判断一颗二叉树是否是满二叉树?
满二叉树
相关题目
求二叉树的最大深度或节点个数
已知最大深度为max,则节点个数
二叉树的递归套路判断是否为满二叉树
这里可以先看下面的递归套路再理解如何用套路求是否为满二叉树
递归套路:返回二叉树的最大深度,节点个数
在调用的函数中判断是否满足满二叉树的条件
package binarytree;
public class IsFullBinaryTree {
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public boolean isFullBinaryTree(Node node) {
return process(node).nodeNumber == Math.pow(2,process(node).depth) - 1;//nodeNumber是否等于2的depth次方-1
}
//所需要的信息:返回二叉树的最大深度,节点个数
public static class Message {
public int depth;
public int nodeNumber;
public Message(int depth, int nodeNumber) {
this.depth = depth;
this.nodeNumber = nodeNumber;
}
}
public Message process(Node node) {
if (node == null) {
return null;
}
Message leftMessage = process(node.left);
Message rightMessage = process(node.right);
int depth = Math.max(leftMessage.depth, rightMessage.depth) + 1;//最大深度要加上当前的节点这一层
int nodeNumber = leftMessage.nodeNumber + rightMessage.nodeNumber + 1;//节点个数=左子树节点个数+右子树节点个数
return new Message(depth, nodeNumber);
}
}
如何判断一颗二叉树是否是平衡二叉树?
平衡二叉树
左子树与右子树的高度差不超过1
二叉树的递归套路
问左树要的信息:左树是否是平衡二叉树;左树的高度
问右树要的信息:右树是否是平衡二叉树;右树的高度
递归函数:返回是否为平衡二叉树,二叉树的深度
package binarytree;
public class IsBalancedBinaryTree {
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public boolean isBalancedBinaryTree(Node node) {
return process(node).isBalance;
}
//所需要的信息:返回是否为平衡二叉树,二叉树的深度
public static class Message {
public boolean isBalance;
public int depth;
public Message(boolean isBalanced, int depth) {
this.isBalance = isBalance;
this.depth = depth;
}
}
public Message process(Node node) {
if (node == null) {
return null;
}
Message leftMessage = process(node.left);//左边的信息
Message rightMessage = process(node.right);//右边的信息
int depth = Math.max(leftMessage.depth, rightMessage.depth) + 1;//最大深度要加上当前的节点这一层
boolean isBalanced = leftMessage.isBalance && rightMessage.isBalance
&& (Math.abs(leftMessage.depth - rightMessage.depth) <= 1);
//左右都为平衡二叉树并且左右子树深度差不超过1
return new Message(isBalanced, depth);
}
}
二叉树的递归套路
在文章中判断二叉树是否为完全二叉树/满二叉树/平衡二叉树等等的题型,都可以抽象出一个二叉树的递归套路
递归套路
树型DP问题(树上动态规划)可以用二叉树的递归套路来解
这里用文档注释表示具体需要写的代码
package binarytree;
public class Template {
//Node类,节点
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
//最终调用的函数,返回最后的结果
public boolean judgment(Node node) {
return true;//一般调用process函数获得Message对象,再获取Message对象里的信息
}
//Message类,信息
//所需要的信息
public static class Message {
/*
定义属性
*/
//定义构造器
public Message() {
}
}
//具体的遍历过程
public Message process(Node node){
if (node == null) {
return null;
}
Message leftMessage = process(node.left);//左边的信息
Message rightMessage = process(node.right);//右边的信息
/*
具体判断具体分析,根据左右子树的属性获取总的这颗树的属性
*/
//创建Message对象,把获取的属性赋值给新的属性,并返回
return new Message();
}
}
二叉树的递归套路解判断是否为搜索二叉树
问左树要的信息:左树是否为搜索二叉树;左树的最大值(左树max < 当前节点的值)
问右树要的信息:右树是否为搜索二叉树;右树的最小值(右树min > 当前节点的值)
递归函数:返回是否为搜索二叉树,二叉树的最大值,最小值
package binarytree;
public class IsSearchBinaryTree {
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public boolean isSearchBinaryTree(Node node) {
return process(node).isSearch;
}
//所需要的信息:返回是否为搜索二叉树,二叉树的最大值,最小值
public static class Message {
public boolean isSearch;
public int max;
public int min;
public Message(boolean isSearch, int max, int min) {
this.isSearch = isSearch;
this.max = max;
this.min = min;
}
}
public Message process(Node node){
if (node == null) {
return null;
}
Message leftMessage = process(node.left);//左边的信息
Message rightMessage = process(node.right);//右边的信息
int max = Math.max(leftMessage.max, rightMessage.max);
max = Math.max(max,node.value);//当前节点和左右节点的值比较得出最大值
int min = Math.min(leftMessage.min, rightMessage.min);
min = Math.min(min,node.value);
boolean isSearch = leftMessage.isSearch && rightMessage.isSearch
&& leftMessage.max < node.value && rightMessage.min > node.value;
//左右子树都为搜索二叉树,左子树max < 当前节点的值 < 右子树min;暂不考虑等于的情况
return new Message(isSearch,max,min);
}
}