Java数据结构(二)二叉查找树

一、描述:

二叉查找树是二叉树的一种,但它要求一个节点的左子节点小于该节点,右子节点大于该节点,因此二叉查找树里存储的值必须是可比较的。

二、代码实现:

以下是一些暴露的public方法,大多数都调用私有方法实现。
另外还有一个隐藏的嵌套节点类。

public class BinarySearchTree<T extends Comparable<? super T>> {
    //嵌套的节点类,外部无法访问
    private static class BinaryNode<E>{
        private E e;
        private BinaryNode<E> left;
        private BinaryNode<E> right;
        private BinaryNode(E e,BinaryNode<E> left,BinaryNode<E> right) {
            this.e = e;
            this.left = left;
            this.right = right;
        }
        private BinaryNode(E e) {
            this(e,null,null);
        }
    }
    //树的根节点
    private BinaryNode<T> root;
    public boolean contains(T t) {
        return contains(t,root);
    }
    public T findMin() {
        return findMin(root).e;
    }
    public T findMax() {
        return findMax(root).e;
    }
    public void insert(T t) {
        root = insert(t,root);
    }
    public void remove(T t) {
        remove(t,root);
    }
    public void printTree() {
        System.out.println("root:"+root.e);
        printTree(root);
    }
    public boolean isEmpty() {
        return root==null;
    }
    ......
}

私有方法:findMin与findMax
查找最大值与最小值,只需要找到深度最大的右子节点和左子节点即可即可

    private BinaryNode<T> findMin(BinaryNode<T> node) {
        if(node==null)
            return null;
        //左子节点不为空则继续从左子节点找最小值
        if(node.left!=null)
            return findMin(node.left);
        //左子节点为空,则当前值最小
        return node;
    }
    private BinaryNode<T> findMax(BinaryNode<T> node){
        if(node==null)
            return null;
        //右子节点不为空继续找右子节点,最右的子节点最大
        if(node.right!=null)
            return findMax(node.right);
        //右子节点为空,当前值最大
        return node;
    }

私有方法:insert
实现插入操作只需要与当前节点比较,小的往左继续找,大的往右继续找,递归找到最深处插入即可,重复值将不做操作。

    private BinaryNode<T> insert(T t,BinaryNode<T> node) {
        //当前节点为空,已经到最深处,可创建节点插入
        if(node==null)
            return new BinaryNode<T>(t);
        int res = t.compareTo(node.e);
        if(res<0)//向左找更深处的节点
            node.left = insert(t,node.left);
        else if(res>0)//向右找最深处的节点
            node.right = insert(t,node.right);
        //插入值与当前值相同,直接返回
        return node;
    }

私有方法:remove
remove方法相对复杂,当移除的节点只有左子树或只有右子树时,可以直接用左子树或右子树代替移除的节点,但有两颗子树时,需要找到右子树中的最深的左子节点(即右子树中的最小值)代替当前值。

    private BinaryNode<T> remove(T t,BinaryNode<T> node){
        if(node==null)//节点为空,无法移除,直接返回空
            return null;
        int res = t.compareTo(node.e);
        if(res<0)//移除值比当前值小,继续向深处移除
            node.left = remove(t,node.left);
        else if(res>0)//移除值比当前值大,继续向深处移除
            node.right = remove(t,node.right);
        //找到可移除节点,但有两颗子树
        else if(node.left!=null&&node.right!=null) {
            //将当前值替换为右子树中的最小值
            node.e = findMin(node.right).e;
            //右子树的最小值已经使用,移除右子树的最小值
            remove(node.e,node.right);
        }else {
            //找到可移除点,且只有一颗子树或没有子树,左子树为空时用右子树替换当前节点,
            //没有子树时用右子树替换当前节点(右子树此时也为空)
            //左子树不为空,用左子树替换当前节点
            node = node.left==null?node.right:node.left;
        }
        return node;
    }

私有方法:printTree
这个方法靠喜好实现吧,二叉树怎么打印出来都感觉很乱

    private void printTree(BinaryNode<T> node) {
        //当前节点为空,直接返回
        if(node==null)
            return;
        //打印当前节点值(用n标识当前节点)
        System.out.print("n:"+node.e);
        //打印左子节点和右子节点(分别yongl和r标识)
        if(node.left!=null) {
            System.out.print(" l:"+node.left.e);
        }
        if(node.right!=null) {
            System.out.print(" r:"+node.right.e);
        }
        //当前节点及子节点打印完换行
        System.out.println();
        //分别将左右子节点当做当前节点打印其子节点
        printTree(node.left);
        printTree(node.right);
    }

私有方法:contains
采用遍历树的方式找到树的最深处,有相同值返回true

private boolean contains(T t,BinaryNode<T> node) {
        if(t!=null) {
            //和当前值比较,小则查找左子树,大则查找右子树,相同返回true
            int i = t.compareTo(node.e);
            if(i<0)
                contains(t, node.left);
            else if(i>0)
                contains(t,node.right);
            else
                return true;
        }
        return false;
    }

以上就是二叉查找树的基本实现,主要采用递归实现,也可替换成循环。

猜你喜欢

转载自blog.csdn.net/qq_38071004/article/details/80927957