您的位置:首页 > 其它

检查一颗二叉树是否是二叉查找树

2016-04-20 20:19 393 查看

中序遍历法

首先,最直观的一种算法就是进行一次中序遍历,然后将每个节点的值保存在一个数组中,然后这个数组是有序的,那么这颗树就是一个二叉查找树。

小问题

但是这个算法有一个问题,那就是对于存在重复值的二叉查找树,它并不能判断其正确性,比如:

20.left = 20;
20.right = 20;


两者在数组中看起来是一样的。但是一个允许重复值存在的二叉查找树要约定好,插入一个重复的值,它应该在左边还是右边。

那么,现在我们假设不考虑有重复值的情况,这个算法就没有问题吗? 还可以优化吗?

我们不难发现,这个算法中的数组只是被用来判断序列是否有序。我们完全可以在遍历的时候就进行判断,从而节约存储空间。

代码

static int lastPrinted = Integer.MIN_VALUE;
public static boolean isBianrySearchTree(TreeNode root) {
if(root == null){
return true;
}

// 如果左子树不是二叉搜索树,则可以直接返回false
if(!isBianrySearchTree(root.left)){
return false;
}

// 再来判断此时跟节点的情况:是否比左子树的最大值大?
if(root.val < lastPrinted){
return false;
}
// 每访问一个节点,则更新一下 lastPrinted
lastPrinted = root.val;

if(!isBianrySearchTree(root.right)){
return false;
}

// 最后全部检查完了,还没有发现问题,则返回true
return true;
}


改进后的代码的优越性非常明显。如果有1万个节点,如果用数组的话则需要长度达到10000。但是用上面的方法,只用一个int 值。

区间检查法

先将区间设为[Integer.MIN_VALUE,Integer.MAX_VALUE],然后从根节利用前序遍历的方式检查每一个节点是否在特定区间内。进入左子树的时候更新max,进入右子树的时候,更新min。

public static boolean isBinarySearchTree2(TreeNode root) {
return isBinarySearchTree2(root, Integer.MIN_VALUE,Integer.MAX_VALUE );
}

private static boolean isBinarySearchTree2(TreeNode root, int min, int max) {
if(root == null){
return true;
}

// 检查根节点是否在区间内
if(root.val > max || root.val < min){
return false;
}else{
// 检查左子树,左子树的最大值就是根节点的值。
if(!isBinarySearchTree2(root.left, min, root.val)){
return false;
}

// 检查右子树,右子树的最小值就是根节点的值
if(!isBinarySearchTree2(root.right, root.val, max)){
return false;
}
}

return true;
}


测试

public static void main(String[] args) {
/***
* 新建一个二叉树:
*
*            15
*           /  \
*          12   25
*         / \
*        9   13
* ***/
TreeNode root = new TreeNode(15);
TreeNode l = new TreeNode(12);
root.left = l;
TreeNode r = new TreeNode(25);
root.right = r;
TreeNode ll = new TreeNode(9);
TreeNode lr = new TreeNode(13);
l.left = ll;
l.right = lr;

System.out.println("方法一的判断 : "+ isBinarySearchTree(root));
System.out.println("方法二的判断 : "+ isBinarySearchTree2(root));

r.left = new TreeNode(40);
System.out.println("\n方法一的判断 : "+ isBinarySearchTree(root));
System.out.println("方法二的判断 : "+ isBinarySearchTree2(root));

}


输出

方法一的判断 : true
方法二的判断 : true

方法一的判断 : false
方法二的判断 : false
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二叉查找树