【数据结构】搜索树 与 Java集合框架中的Set,Map

这篇具有很好参考价值的文章主要介绍了【数据结构】搜索树 与 Java集合框架中的Set,Map。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作者主页:paper jie_博客

本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。

本文录入于《JAVA数据结构》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将javaSE基础知识一网打尽,希望可以帮到读者们哦。

其他专栏:《算法详解》《C语言》《javaSE》等

内容分享:本期将会分享java数据结构中的二叉搜索树与Java集合中的Set和Map

目录

什么是搜索树

搜索树的模拟实现

查找功能

代码实现

画图分析

新增功能

具体代码

画图分析

删除功能

具体代码

画图分析

搜索树的性能

搜索树与Java类集合的关系

Set和Map

概念

模型

Map

Map.Entry,v>

Map的常用方法

TreeMap和HashMap的比较

Set

Set的常用方法

TreeSet和HashMap的比较


什么是搜索树

搜索树又名二叉搜索树,它是一颗完全二叉树,且:

左树不为空的话,则左子树上的所有节点的值都小于根节点的值

右树不为空的话,则右子树上的所有节点的值都大于根节点的值

它的左右子树也是搜索树

【数据结构】搜索树 与 Java集合框架中的Set,Map,# JAVA数据结构,JAVA,数据结构,1024程序员节,java

搜索树的模拟实现

查找功能

实现这个功能就可以利用它的性质,比根节点的小的数在左边,比根节点大的数在右边,通过遍历的方式一直查找,要是遇到了null,代表就没有这个数。

代码实现

//查找元素
    //查找复杂度:O(logN)
    //最坏情况:O(N)
    public boolean search(int node) {
        if(root == null) {
            return false;
        }
        TreeNode cur = root;
        while(cur != null) {
            if(node < cur.val) {
                cur = cur.left;
            }else if(node > cur.val) {
                cur = cur.right;
            }else {
                return true;
            }
        }
        return false;
    }

画图分析

【数据结构】搜索树 与 Java集合框架中的Set,Map,# JAVA数据结构,JAVA,数据结构,1024程序员节,java

新增功能

新增节点,我们就分两种情况,一种没有节点,一种有节点,但大致开始用cur遍历找到需要插入的位置,再用一个prev记住cur的前一个节点。且相同是不需要添加的。当cur等于null的时候,就用prev来判断它大于key,就将新增节点放在它的左边不然就放在右边

具体代码

//新增元素
    public boolean push(int node) {
        if(root == null) {
            root = new TreeNode(node);
            return true;
        }

        TreeNode cur = root;
        TreeNode prve = null;

        while(cur != null) {
            if(node < cur.val) {
                prve  = cur;
                cur = cur.left;
            }else if(node > cur.val){
                prve = cur;
                cur = cur.right;
            }else {
                return false;
            }
        }
        TreeNode treeNode = new TreeNode(node);
        if(prve.val > node) {
            prve.left = treeNode;
        }else {
            prve.right = treeNode;
        }
        return true;
    }

画图分析

【数据结构】搜索树 与 Java集合框架中的Set,Map,# JAVA数据结构,JAVA,数据结构,1024程序员节,java

删除功能

删除就比较复杂一点,得分几种情况,而这几种情况中又得细分:

当需要删除的节点左边没有元素

1 需要删除的是头节点

2 需要删除的在父节点的左边

3 需要删除的节点在父节点的右边

【数据结构】搜索树 与 Java集合框架中的Set,Map,# JAVA数据结构,JAVA,数据结构,1024程序员节,java

当需要删删出的节点右边没有元素

1 需要删除的是头节点

2 需要删除的在父节点的左边

3 需要删除的节点在父节点的右边

【数据结构】搜索树 与 Java集合框架中的Set,Map,# JAVA数据结构,JAVA,数据结构,1024程序员节,java

当需要删除的节点两边都有元素

这里是比较难处理的,我们不能直接删除这个结点,这里我们使用替换法:找到删除节点右边的最小节点,将最小节点的值赋值给需要删除的那个元素,再将最小节点删除,在删除这个最小节点的时候我们也要考虑:

它的左边有没有元素,它的右边有没有元素,还是左右都没有元素

【数据结构】搜索树 与 Java集合框架中的Set,Map,# JAVA数据结构,JAVA,数据结构,1024程序员节,java

具体代码

//删除元素
    public boolean poll(int key) {
        TreeNode cur = root;
        TreeNode parent = null;
        while(cur != null) {
            if(key < cur.val) {
                parent = cur;
                cur = cur.left;
            }else if(key > cur.val) {
                parent = cur;
                cur = cur.right;
            }else {
                removeNode(cur, parent);
                return true;
            }
        }
        return false;
    }
    private void removeNode(TreeNode cur, TreeNode parent) {
        //删除节点左边为空
        if(cur.left == null) {
            if(cur == root) {
                root = root.right;
            }else if(parent.left == cur) {
                parent.left = cur.right;
            }else {
                parent.right = cur.right;
            }
            //删除节点右边为空
        }else if(cur.right == null) {
            if(root == cur) {
                root = root.left;
            }else if(parent.left == cur) {
                parent.left = cur.left;
            }else {
                parent.right = cur.left;
            }
            //都不为空
        }else {
            TreeNode xparent = cur;
            TreeNode x = cur.right;
            while(x.left != null) {
                xparent = x;
                x = x.left;
            }
            cur.val = x.val;
            if(xparent.left == x) {
                xparent.left = x.right;
            }else {
                xparent.right = x.right;
            }
        }

    }
}

画图分析

【数据结构】搜索树 与 Java集合框架中的Set,Map,# JAVA数据结构,JAVA,数据结构,1024程序员节,java

搜索树的性能

这里我们可以把查找的效率看做整个搜索树的性能,因为不管是新增和删除都是需要查找的嘛。

对于搜索树,我们知道,它就是一颗二叉树,所以比较的次数就是树的深度。但是所有情况都是这样嘛,这里会因为一个数据集合,如果他们数据插入的次序不一样,则会得到不一样的数据结构,比如下图:

【数据结构】搜索树 与 Java集合框架中的Set,Map,# JAVA数据结构,JAVA,数据结构,1024程序员节,java

这里我们就知道了,在最坏情况下搜索树会退化成一个链表所以:

最好情况时间复杂度:O(logN)

最坏情况时间复杂度:O(N)

搜索树与Java类集合的关系

Java中的TreeMap和TreeSet就是利用搜索树实现的,但是呢它们底层使用的是搜索树的进化再进化版红黑树(搜索树 - LAV树 - 红黑树 ),LAV树就是对搜索树的改进,遇到链表情况下它就是翻转这个链表,让他变成一个高度平衡的搜索树,而红黑树是在这个基础加上颜色一节红黑树性质的验证进一步的提高了它的效率。

Set和Map

概念

Map和Set是一种专门用来进行搜索的容器或者数据结构,它的搜索效率和实现它们的子类有关。一般比较简单的搜索方式有:

直接遍历,复杂度为O(N),效率比较底下

二分查找,复杂度为O(logN),但它麻烦的是必须是有序的

而这些搜索方式只适合静态的搜索,但对于区间这种插入和删除的操作他们就不行了,这种就属于动态搜索方式。Map和Set就是用来针对这种的动态查找的集合容器

模型

这集合中,一般把搜索的数据称为关键字Key和关键字的对应值Value,这两个称为键值对,一般有两种模型:

纯Key模型,即只需要一个数据,比如:

查找手机里面有没有这个联系人

Key-Value模型,比如:

查找这个篇文章里面这个词出现了几次 (词,出现的次数)

Map就是Key-Value模型,Set是纯Key模型

Map接口下继承了HashMap和TreeMap两个类,而Set接口下继承了TreeSet和HashSet两个类

TreeMap和TreeSet底层是红黑树,而HashMap和HashSet底层是哈希表

【数据结构】搜索树 与 Java集合框架中的Set,Map,# JAVA数据结构,JAVA,数据结构,1024程序员节,java

Map

Map是一个接口,它没有和其他几个类一样继承Collection,它存储的是<K,V>键值对,且K是唯一·的,V可以重复

Map.Entry<K,V>

Map.Entry<K,V>在Map中是一个内存类, 它是用来Map内部实现存放<K,V>键值对映射关系的,它还提供了Key,value的设置和Key的比较方式:

方法 解释
K getKey() 返回Entry中的Key
K getValue() 返回Entry中的Value
K setValue(V value)

设置Entry中的value

这里要注意它没有提供设置Key的方法

Map的常用方法

【数据结构】搜索树 与 Java集合框架中的Set,Map,# JAVA数据结构,JAVA,数据结构,1024程序员节,java

注意事项:

1 Map是一个接口,它不可以实例化对象,要实例化只能实例化它的子类TreeMap或者HashMap

2 Map中存放键值对里的Key是唯一的,value是可以重复的

3 在TreeMap中插入键值对时,Key不能为空,否则就会抛NullPointerExecption异常,value可以为空。但是HashMap的Key和value都可以为空

4 Map中的Key是可以分离出来的,存储到Set中来进行访问(因为Key不能重合)

5 Map中的value也可以分离出来,存放到Collection的任何一个子集合中,但是value可能会重合 

6 Map中的键值对Key不能直接修改,value可以修改,如果要修改Key,只能先将Key先删除,再来插入

TreeMap和HashMap的比较

Map底层结构 TreeMap HashMap
底层结构 红黑树 哈希桶
时间复杂度 O(logN) O(1)
是否有序 有序 无序
线程安全 不安全 不安全
插入/删除/添加的区别 需要进行数据间的比较 直接通过计算哈希函数来确定地址
应用场景 在需要有序的场景下 不关心是否有序,更需要效率的场景下
比较和重写 Key必须是可以比较的,不可以为null 自定义类型需要重写哈希Code方法和equals方法

使用栗子:

HashMap:

public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("猪八戒", 500);
        map.put("孙悟空", 550);
        map.put("唐僧", 40);
        map.put("沙和尚", 100);
        map.put("白龙马", 300);
        System.out.println(map.get("猪八戒"));
        System.out.println(map.remove("八戒"));
        System.out.println(map.get("猪八戒"));
        Set<Map.Entry<String, Integer>> set = map.entrySet();
        for(Map.Entry<String, Integer> entry : set) {
            System.out.println(entry);
        }
        System.out.println(map.containsKey("猪八戒"));

    }

TreeMap:

public static void TestMap() {
        Map<String, String> m = new TreeMap<>();
// put(key, value):插入key-value的键值对
// 如果key不存在,会将key-value的键值对插入到map中,返回null
        m.put("林冲", "豹子头");
        m.put("鲁智深", "花和尚");
        m.put("武松", "行者");
        m.put("宋江", "及时雨");
        String str = m.put("李逵", "黑旋风");
        System.out.println(m.size());
        System.out.println(m);
// put(key,value): 注意key不能为空,但是value可以为空
// key如果为空,会抛出空指针异常
// m.put(null, "花名");
        str = m.put("无名", null);
        System.out.println(m.size());
// put(key, value):
// 如果key存在,会使用value替换原来key所对应的value,返回旧value
        str = m.put("李逵", "铁牛");
// get(key): 返回key所对应的value
// 如果key存在,返回key所对应的value
// 如果key不存在,返回null
        System.out.println(m.get("鲁智深"));
        System.out.println(m.get("史进"));
//GetOrDefault(): 如果key存在,返回与key所对应的value,如果key不存在,返回一个默认值
        System.out.println(m.getOrDefault("李逵", "铁牛"));
        System.out.println(m.getOrDefault("史进", "九纹龙"));
        System.out.println(m.size());
//containKey(key):检测key是否包含在Map中,时间复杂度:O(logN)
// 按照红黑树的性质来进行查找
// 找到返回true,否则返回false
        System.out.println(m.containsKey("林冲"));
        System.out.println(m.containsKey("史进"));
// containValue(value): 检测value是否包含在Map中,时间复杂度: O(N)
// 找到返回true,否则返回false
        System.out.println(m.containsValue("豹子头"));
        System.out.println(m.containsValue("九纹龙"));
// 打印所有的key
// keySet是将map中的key防止在Set中返回的
        for (String s : m.keySet()) {
            System.out.print(s + " ");
        }
        System.out.println();
// 打印所有的value
// values()是将map中的value放在collect的一个集合中返回的
        for (String s : m.values()) {
            System.out.print(s + " ");
        }
        System.out.println();
// 打印所有的键值对
// entrySet(): 将Map中的键值对放在Set中返回了
        for (Map.Entry<String, String> entry : m.entrySet()) {
            System.out.println(entry.getKey() + "--->" + entry.getValue());
        }
        System.out.println();
    }

Set

Set和Map的不同点就在于Set是继承于Collection接口类的,Set只存储了Key。

Set的常用方法

【数据结构】搜索树 与 Java集合框架中的Set,Map,# JAVA数据结构,JAVA,数据结构,1024程序员节,java

注意事项:

1 Set是继承Collection的一个接口

2 Set只存储Key,且要求Key是唯一的

3 TreeSet的底层是使用了Map来实现的,其使用Key与Object的一个默认对象作为键值对插入到Map中

4 Set的最大特点就是去重

5 实现Set接口的常用类有TreeSet和HashSet,还有一个LinkedSet,它是在HashSet上维护了一个双向链表来记入插入元素的次序

6 Set中的Key不能修改,如果要修改的话,呀先将原来的删除,再重新插入

7 TreeSeet中不能插入null的Key,但HashSet可以

TreeSet和HashMap的比较

Set底层结构 TreeSet

HashSet

底层结构 红黑树 哈希桶
复杂度 O(logN) O(1)
是否有序 有序 无序
线程安全 不安全 不安全
插入/删除/查找区别 使用红黑树的性质来插入和删除的 使用哈希函数来计算插入和删除的地址
比较和重写 Key必须可以比较,不能为null 自定义类型需要重写equals方法和HashCode方法
应用场景 需要Key有序场景下 需要更高的时间性能

栗子:

public static void TestSet2(){
        Set<String> s = new TreeSet<>();
// add(key): 如果key不存在,则插入,返回ture
// 如果key存在,返回false
        boolean isIn = s.add("apple");
        s.add("orange");
        s.add("peach");
        s.add("banana");
        System.out.println(s.size());
        System.out.println(s);
        isIn = s.add("apple");
// add(key): key如果是空,抛出空指针异常
//s.add(null);
// contains(key): 如果key存在,返回true,否则返回false
        System.out.println(s.contains("apple"));
        System.out.println(s.contains("watermelen"));
// remove(key): key存在,删除成功返回true
// key不存在,删除失败返回false
// key为空,抛出空指针异常
        s.remove("apple");
        System.out.println(s);
        s.remove("watermelen");
        System.out.println(s);
        Iterator<String> it = s.iterator();
        while(it.hasNext()){
            System.out.print(it.next() + " ");
        } 
        System.out.println();
    }

这里文章中我们提到的HashMap和HashSet的底层 - 哈希桶,下一篇文章就会介绍,期待一下吧文章来源地址https://www.toymoban.com/news/detail-715138.html

到了这里,关于【数据结构】搜索树 与 Java集合框架中的Set,Map的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】 初识集合框架

    这里博主将简单介绍一下集合框架,想要详细了解的可以点击下方链接进行查看 java集合官方教程 Java 集合框架 Java Collection Framework ,又被称为容器 container ,是定义在 java.util 包下的一组接口 interfaces 和其实现类 classes 。 其主要表现为将多个元素 element 置于一个单元中,用于

    2024年02月13日
    浏览(40)
  • 集合框架及背后的数据结构

    大家好,我是晓星航。今天为大家带来的是 集合框架及背后的数据结构 的讲解!😀 官方教程 Java 集合框架 Java Collection Framework ,又被称为容器 container ,是定义在 java.util 包下的一组接口 interfaces 和其实现类 classes 。 其主要表现为将多个元素 element 置于一个单元中,用于对

    2024年01月18日
    浏览(46)
  • 集合中的数据结构

    栈 先进后出 入口跟出口在同一侧 队列 先进先出 入口跟出口在不同的一层 数组 查询快、增删慢 查询快是因为数组的地址是连续的,我们通过数组的首地址就可以找到数组,之后通过数组的下标就可以访问数组的每一个元素。 增删慢是因为数组的长度是固定的,我们增加或

    2024年02月15日
    浏览(40)
  • Java学数据结构(3)——树Tree & B树 & 红黑树 & Java标准库中的集合Set与映射Map & 使用多个映射Map的案例

    1.B树,阶M,数据树叶上,根的儿子数在2和M之间,除根外,非树叶节点儿子为M/2和M之间; 2.B树的插入引起分裂,B树的删除,引起合并和领养; 3.红黑树,根是黑的,红色节点的儿子必须是黑的,所有路径的黑色节点数相同; 4.红黑树的插入,颜色翻转,单旋转,插入节点定

    2024年02月11日
    浏览(80)
  • 【数据结构前置知识】初识集合框架和时间,空间复杂度

    Java 集合框架 Java Collection Framework ,又被称为容器 container ,是定义在 java.util 包下的一组接口 interfaces 和其实现类 classes 。 其主要表现为将多个元素 element 置于一个单元中,用于对这些元素进行快速、便捷的存储 store 、检索 retrieve 、管理 manipulate ,即平时我们俗称的增删查

    2024年02月09日
    浏览(38)
  • Java 数据结构集合

    详细请转到@pdai的博客 1.1 数组 (Array) 数组的优点: 存取速度快 数组的缺点: 事先必须知道数组的长度 插入删除元素很慢 空间通常是有限制的 需要大块连续的内存块 插入删除元素的效率很低 源码分析: 1、底层数据结构是Object 2、构造函数包括无参构造和有参数构造,有参构

    2024年01月24日
    浏览(44)
  • springboot第49集:【思维导图】多线程,常用类与基础API,集合框架,泛型,数据结构源码...

    多线程创建方式一:继承Thread类 多线程创建方式二:实现Runnable接口 jdk5.0新增两种创建多线程的方式 image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png 优先级 image.png image.png image.png image.png image.png image.png 线程安全问题 image.p

    2024年01月21日
    浏览(48)
  • 【算法与数据结构】700、LeetCode二叉搜索树中的搜索

    所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。    思路分析 :二叉搜索树(Binary Search Tree, BST)的性质:所有左子树节点键值 中间节点键值 所有右子树节点键值,并且左右子树都是二叉搜索树。那么我们根据此性质,对比目标值和中间节点,如

    2024年02月10日
    浏览(41)
  • JAVA数据结构篇--13线程安全的Set 集合

    前言:java 中用于存放不重复元素的set 集合,其中无序的HashSet,以及有序的LinkedHashSet和TreeSet 都是非线程安全的,那么多线程环境下,我们要存放不重复的元素,需要使用哪种集合进行数据存取; 1 使用: 2 过程: 2.1 放入获取元素: Collections.synchronizedSet:通过使用synchron

    2024年02月16日
    浏览(41)
  • 数据结构(Java实现)-集合与时间和空间复杂度

    什么是集合框架 Java 集合框架 Java Collection Framework ,又被称为容器 container ,是定义在 java.util 包下的一组接口 interfaces 和其实现类 classes 。 什么是数据结构 数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的 集合。 容器

    2024年02月12日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包