JAVA学习-数据结构-TreeSet-二叉搜索树

标题写的是TreeSet,但是在此之前我先需要实现一个红黑树。
为此,这里写一些篇幅实现搜索树。包括二叉搜索树、AVL、红黑树。
每个树都实现增加删除等功能。
这篇先讲二叉搜索树。
二叉搜索树的基本结构就是一颗二叉树。它的特点就是对于一个节点s,它的左子树的所有节点的key都小于s节点的key值,它的右子树的所有节点的key值都大于s的key值。
注意:s节点是任意的,也就是说,对于任意一个节点s都需要满足这个条件。

在实现二叉树中,删除操作是最难的。我也是去网上看了一些人的解释才弄明白一点。我理解到的要点就是:删除一个节点,该节点有以下三种情况:
1)无孩子,是一个叶子节点; 2)只有一个孩子; 3)有两个孩子。
(这里的孩子说的是直接后代,也就是说这个孩子是什么情况不讨论)
然后对于情况1)直接删除就行,需要处理它的父节点;情况2)将它的父节点指向它的孩子;情况3)从他的所有子代中找一个前驱或者后继节点进行替换,然后删除前驱(这个可能会比较难理解)

前驱和后继的概念就是将这颗二叉树用前序遍历进行输出,前驱就是这个节点的直接前面节点,后继就是这个节点的直接后面的节点。(我这里是找他的前驱节点,也就是右子树中最小值)
前驱(右子树(保证比他大)最小值(直接前驱))
后继(左子树(保证比他小)最大值(直接后继))

将该节点指向它的前驱,然后在它的右子树中删除树中最小值。维持二叉搜索树的特点
代码:

public class HBSTree<K extends Comparable<K>, V> {
    private TreeNode root;

    private final class TreeNode{
        private K key;
        private V val;
        private TreeNode lChild;
        private TreeNode rChild;

        TreeNode(K key, V val){
            this.key = key;
            this.val = val;
            lChild = null;
            rChild = null;
        }
    }

    HBSTree(){
        root = null;
    }

    public void insert(K key, V val){
        if(key == null) return ;
        if(val == null) return ;
        root = insert(root, key, val);
    }
    private TreeNode insert(TreeNode treeNode, K key, V val){
        if(treeNode == null)treeNode = new TreeNode(key, val);

        int cmp = key.compareTo(treeNode.key);
        if      (cmp < 0)   treeNode.lChild = insert(treeNode.lChild, key, val);
        else if (cmp > 0)   treeNode.rChild = insert(treeNode.rChild, key, val);
        else                treeNode.val = val;
        return treeNode;
    }

    public boolean contains(K key){
        if(key == null) return false;
        return get(root, key) != null;
    }

    public V get(K key){
        TreeNode treeNode = get(root, key);
        if(treeNode == null) return null;
        return treeNode.val;
    }
    private TreeNode get(TreeNode treeNode, K key){
        if(treeNode == null) return null;
        int cmp = key.compareTo(treeNode.key);
        if      (cmp < 0)   return get(treeNode.lChild, key);
        else if (cmp > 0)   return get(treeNode.rChild, key);
        else                return treeNode;
    }

    public K minKey(){
        if(root == null) return null;
        return minKey(root).key;
    }
    /**
     * recursive way to implement minKey
     * private TreeNode minKey(TreeNode treeNode){
     *   if(treeNode.lChild == null) return treeNode;
     *   return minKey(treeNode.lChild);
     *  }
     */
    private TreeNode minKey(TreeNode treeNode){
        if(treeNode == null) return null;
        while (treeNode.lChild != null) treeNode = treeNode.lChild;
        return treeNode;
    }

    public K maxKey(){
        if(root == null) return null;
        return maxKey(root).key;
    }
    /**
     * recursive to implement maxKey
     * private TreeNode maxKey(TreeNode treeNode){
     *         if(treeNode.rChild == null) return treeNode;
     *         return maxKey(treeNode.rChild);
     *  }
     */
    private TreeNode maxKey(TreeNode treeNode){
        if(treeNode == null) return null;
        while (treeNode.rChild != null) treeNode = treeNode.rChild;
        return treeNode;
    }

    public void deleteMin(){
        if(root == null) return ;
        root = deleteMin(root);
    }
    private TreeNode deleteMin(TreeNode treeNode){
        if(treeNode.lChild == null) return treeNode.rChild;
        treeNode.lChild = deleteMin(treeNode.lChild);
        return treeNode;
    }

    public void deleteMax(){
        if(root == null) return ;
        root = deleteMax(root);
    }
    private TreeNode deleteMax(TreeNode treeNode){
        if(treeNode.rChild == null) return treeNode.lChild;
        treeNode.rChild = deleteMax(treeNode.rChild);
        return treeNode;
    }

    public void remove(K key){
        if(key == null) return ;
        root = remove(root, key);
    }
    private TreeNode remove(TreeNode treeNode, K key){
        if(treeNode == null) return null;

        int cmp = key.compareTo(treeNode.key);
        if      (cmp < 0) return remove(treeNode.lChild, key);
        else if (cmp > 0) return remove(treeNode.rChild, key);
        else {
            if(treeNode.rChild == null) return treeNode.lChild;
            if(treeNode.lChild == null) return treeNode.rChild;
            TreeNode node = treeNode;
            treeNode = minKey(node.rChild);
            treeNode.rChild = deleteMin(node.rChild);
            treeNode.lChild = node.lChild;
        }return treeNode;
    }
}

最后的最后:代码很多是用递归实现。不得不承认,实现二叉树的某些方法时,的确用递归很方便而且代码简单。但是有些时候最好还是尽力去消除递归。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值