二叉查找树(BST)---java实现

一、定义

二叉查找树(BST)是一颗二叉树,其每个节点的值都比左孩子的任意节点大,比右孩子的任意节点小。

二、数据结构

public class BinarySearchTree<T extends Comparable<? super T>>  {

    private TreeNode<T> root;

    public BinarySearchTree(TreeNode<T> root) {
        this.root = root;
    }
}

class TreeNode<T>{
    T data;
    TreeNode lchild;
    TreeNode rchild;

    public TreeNode(T data) {
        this(data,null,null);
    }

    public TreeNode(T data, TreeNode lchild, TreeNode rchild) {
        this.data = data;
        this.lchild = lchild;
        this.rchild = rchild;
    }


}

三、contains方法

如果该树存在数据X则返回true,否则返回false。
我们只需要从根节点开始遍历,如果当前节点小于X,则向左递归,否则向右递归,直到找到X或到达树的最后。

 public boolean contains(T x){
        return  contains(x,root);
    }
    private boolean contains(T x, TreeNode<T> root) {
        if (root==null){
            return false;
        }
        int result=x.compareTo(root.data);
        if (result<0){
            return contains(x,root.lchild);
        }else if (result>0){
            return contains(x,root.rchild);
        }else {
            return true;
        }

    }

四、查找最小值和最大值

一颗二叉查找树,其最小值一定是按左子树递归找到,直到树底
1.如果根节点为空,则返回空
2.如果左子树为空,则返回根节点
3.否则从左孩子开始,继续从1递归。

 public TreeNode<T> findMax(TreeNode<T> root){
        if (root==null){
            return null;
        }
        while (root.rchild!=null){
            root=root.rchild;
        }
        return root;
    }

查找最大值则相反,从根节点向右子树循环查找。

public TreeNode<T> findMax(TreeNode<T> root){
        if (root==null){
            return null;
        }
        while (root.rchild!=null){
            root=root.rchild;
        }
        return root;
    }

五、插入一个节点

同样可以使用contains那种递归的方式。
如果找到X,则节点已存在,什么都不做;否则就插入到遍历路径上的最后一个节点。

public TreeNode<T> insert(T x){
        if (x==null){
            throw new IllegalArgumentException("参数为空");
        }
        return insert(x,root);
    }
    private TreeNode<T> insert(T x,TreeNode<T> t){
    	//当前节点为空,构建一个新的节点插入x
        if (t==null){
            return new TreeNode<>(x);
        }
        int result=x.compareTo(t.data);
        if (result<0){
        	//向左递归
            t.lchild=insert(x,t.lchild);
        }else if (result>0){
     	   //向右递归
            t.rchild=insert(x,t.rchild);
        }
        return t;
    }

六、删除一个节点

删除节点X大致可分为三种情况:

  1. 如果X是叶子节点,则直接删除
  2. 如果X有一个孩子,则将那个孩子放在当前节点位置
  3. 如果X有两个孩子,则找到右孩子中最小的一个节点Y,放到待删除节点X的位置,这样X的左孩子们仍然比它小,现在只需要用同样的方式删除右孩子的Y即可。
 public void remove(T x){
        if (x==null){
            return;
        }
        remove(x,root);
    }

    /**
     * 删除一个节点
     * 1.如果是叶子节点,则直接删除
     * 2.如果有一个孩子,让当前节点等于那个孩子
     * 3.如果有两个孩子,让当前节点的值等于右孩子中最小的一个节点的值,然后再同样的方法删除右孩子最小值的节点
     * @param x
     * @param root
     * @return
     */
    private TreeNode<T> remove(T x,TreeNode<T>root){
        if (root==null){
            return null;
        }

        int result=x.compareTo(root.data);
        if (result<0){
            root.lchild=remove(x,root.lchild);
        }else if (result>0){
            root.rchild=remove(x,root.rchild);
        }else if (root.lchild!=null&&root.rchild!=null){ //找到待删除节点,且有两个孩子
        	//让当前节点值等于右孩子最小的节点值
            root.data= (T) findMin(root.rchild).data;
            //在右孩子中删除上一步找到的最小的值
            root.rchild=remove(root.data,root.rchild);
        }else {
            root=root.lchild==null?root.rchild:null;
        }
        return root;
    }

求节点的高度就很简单了:

 public int height(TreeNode<T> root){
        if (root==null){
            return -1;
        }
        return 1+Math.max(height(root.lchild),height(root.rchild));
    }

总结:
使用二叉查找树的运行时间取决于树的形态,而树的形态又取决于数据被插入的顺序。因此最好的情况下是一颗完全二叉树;但最坏情况下,搜索路径上有N个节点,即左右节点都在一条路径下排开。

最坏情况下运行时间的增长数量级:
查找: N
插入: N
平均情况下:
查找命中:1.39lgN
插入: 1.39lgN
支持有序性相关操作

发布了75 篇原创文章 · 获赞 13 · 访问量 8369

猜你喜欢

转载自blog.csdn.net/weixin_43696529/article/details/104697184
今日推荐