检查一颗二叉树是否是二叉查找树
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