【数据结构】Map和Set(1)

在这里插入图片描述
🧧🧧🧧🧧🧧个人主页🎈🎈🎈🎈🎈
🧧🧧🧧🧧🧧数据结构专栏🎈🎈🎈🎈🎈
🧧🧧🧧🧧🧧【数据结构】常见的排序算法🎈🎈🎈🎈🎈

1.前言

Map与Set的底层有两种结构实现,一种是搜索树(TreeMap与TreeSet),还有一个就是哈希表(HashMaP与HashSet),接下来我们先了解搜索树这个底层结构。
在这里插入图片描述

2.搜索树

2.1概念

二叉搜索树又称二叉排序树,它或者是一棵空树,搜索二叉树具备这样性质:
1)根结点的左边的结点都比根结点小
2)根结点的右边的结点都比根结点大
3)通过中序遍历来遍历这个二叉搜索树是一个升序的数据集合
搜索二叉树:
在这里插入图片描述

2.2查询操作

2.2.1 基本思路:
1.将要查询的值先于根结点比较,与根结点不相等,则判断该元素与根结点的大小。
2.根结点 > 该元素 则该元素在根结点的左边
3.根结点 < 该元素 则该元素在根结点的右边
4.遇到null则遍历结束

2.2.2绘图分析
在这里插入图片描述
2.2.3代码实现

/**
     *寻找key元素
     * @param key
     * @return
     */
    public boolean search(int key) {
        TreeNode cur = root;
        while(cur != null) {
            //1.判断根结点
            if(cur.val == key) {
                return true;
            } else if(cur.val > key) {
                //2.根结点大于key
                cur = cur.left;
            } else {
                //3.根结点小于key
                    cur = cur.right;
                }
            }
        return false;
        }

2.3插入操作

2.3.1基本思路:
1)插入的元素要满足中序遍历之后是一个升序的集合
2)插入的元素只能在搜索二叉树的叶子结点 进行插入
3) 通过一个指针来遍历要插入的位置的同时再让一个指针标记插入位置的父节点

遍历的过程:
1)root == null 直接插入
2)root != null 判断与根结点的大小关系
root.val > val 插入root左边
root.val < val 插入root右边
2.2.2绘图分析
在这里插入图片描述
2.2.3代码实现

/**
     * 插入元素
      */
    public void insert(int val) {
        //1.root == null
        if(root == null) {
          root = new TreeNode(val);
            return;
        }
            //2.root != null
            TreeNode cur = root;
            TreeNode parent = null;
            while(cur != null) {
                if(cur.val < val) {
                    //1.根结点小于key
                    parent = cur;
                    cur = cur.right;
                } else {
                    //2.根结点大于key
                    parent = cur;
                    cur = cur.left;
                }
            }
            //说明cur为空,元素插入parent结点的其中两侧
            TreeNode node =  new TreeNode(val);
            if(parent.val < val) {
                parent.right = node;
            } else {
                parent.left = node;
            }
        }

2.4删除操作

删除操作是最复杂也是最难的一个操作,我们以cur指针来标记删除结点,parent指针标记删除结点的父结点,我们对删除操作分为三种情况:
1.cur.left == null
2.cur.right == null
3.cur.left != null && cur.right != null
我们先画一棵搜索二叉树,这里我们删20这个结点为例子:
在这里插入图片描述
1.cur.left == null
在这里插入图片描述
2.cur.right == null
在这里插入图片描述
3.cur.left != null && cur.right != null
在这里插入图片描述
代码实现:

 public boolean remove(int val) {
        TreeNode cur = root;
        TreeNode parent = null;
        while(cur != null) {
            if(cur.val < val) {
                parent = cur;
                cur = cur.right;
            } else if(cur.val >val){
                parent = cur;
                cur = cur.left;
            } else {
                return removeNode(parent,cur);
            }
        }
        return false;
    }
    private boolean removeNode(TreeNode parent,TreeNode cur) {
        //1.cur.left == null
        if(cur.left == null) {
            if(cur == root) {
               cur.right = root;
            } else {
                if(cur == parent.right) {
                    parent.right = cur.right;
                }
                if(cur == parent.left) {
                    parent.left = cur.right;
                }
            }
        }
        //2.cur.right == null
        if(cur.right == null) {
            if(cur == root) {
                cur.left = root;
            } else {
                if(cur == parent.left) {
                    parent.left = cur.left;
                }
                if(cur == parent.right) {
                    parent.right = cur.left;
                }
            }
        }
        //3.cur.left !=null && cur.right != null
        TreeNode child = cur.right;
        TreeNode p = null;//p为child的父亲结点
        while(child.left != null) {
            p = child;
            child = child.left;
        }
        //找到最小值,将最小值赋值给cur
        cur.val = child.val;

        //最小值的父亲结点的左节点是否等于最小值结点
        if(p.left == child) {
            p.left = child.right;
        } else {
            p.right = child.right;
        }

        return true;
    }

2.5性能分析

插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。
对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。
但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:
在这里插入图片描述
最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:以2为底的log(N)
最差情况下,二叉搜索树退化为单支树,其平均比较次数为:N/2

关于Map与Set先分享到这,后面的内容更加精彩,请各位看官慢慢期待。

  • 72
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 87
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

《黑巧克力》

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值