Java集合详解6:这次,从头到尾带你解读Java中的红黑树

【JAVA】红黑树 详解 红黑树 详解 阅读详情

《Java集合详解系列》是我在完成夯实Java基础篇的系列博客后准备开始写的新系列。

这些文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看

https://github.com/h2pl/Java-Tutorial

喜欢的话麻烦点下Star、fork哈

文章首发于我的个人博客:

www.how2playlife.com

什么是红黑树

首先,什么是红黑树呢? 红黑树是一种“平衡的”二叉查找树,它是一种经典高效的算法,能够保证在最坏的情况下动态集合操作的时间为O(lgn)。红黑树每个节点包含5个域,分别为color,key,left,right和p。 color是在每个节点上增加的一个存储位表示节点的颜色,可以是RED或者BLACK。key为结点中的value值,left,right为该结点的左右孩子指针,没有的话为NIL,p是一个指针,是指向该节的父节点。如下图(来自维基百科)表示就是一颗红黑树,NIL为指向外结点的指针。(外结点视为没有key的结点)

       红黑树有什么性质呢?一般称为红黑性质,有以下五点:

     1)每个结点或者是红的或者是黑的;

     2)根结点是黑的;

     3)每个叶结点(NIL)是黑的;

     4)如果一个结点是红的,则它的两个孩子都是黑的;

     5)对每个结点,从该结点到其他其子孙结点的所有路径上包含相同数目的黑结点。

       为了后面的分析,我们还得知道以下知识点。

    (1)黑高度:从某个结点x出发(不包括该结点)到达一个叶结点的任意一条路径上,黑色结点的个数称为该结点x的黑高度。

    (2)一颗有n个内结点的红黑树的高度至多为2lg(n 1)。   (内结点视为红黑树中带关键字的结点)

    (3)包含n个内部节点的红黑树的高度是 O(log(n))。

定义

红黑树是特殊的二叉查找树,又名R-B树(RED-BLACK-TREE),由于红黑树是特殊的二叉查找树,即红黑树具有了二叉查找树的特性,而且红黑树还具有以下特性:

  • 1.每个节点要么是黑色要么是红色
  • 2.根节点是黑色
  • 3.每个叶子节点是黑色,并且为空节点(还有另外一种说法就是,每个叶子结点都带有两个空的黑色结点(被称为黑哨兵),如果一个结点n的只有一个左孩子,那么n的右孩子是一个黑哨兵;如果结点n只有一个右孩子,那么n的左孩子是一个黑哨兵。)
  • 4.如果一个节点是红色,则它的子节点必须是黑色
  • 5.从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

有几点需要注意的是:

1.特性3中指定红黑树的每个叶子节点都是空节点,但是在Java实现中红黑树将使用null代表空节点,因此遍历红黑树时看不到黑色的叶子节点,反而见到的叶子节点是红色的

2.特性4保证了从根节点到叶子节点的最长路径的长度不会超过任何其他路径的两倍,例如黑色高度为3的红黑树,其最短路径(路径指的是根节点到叶子节点)是2(黑节点-黑节点-黑节点),其最长路径为4(黑节点-红节点-黑节点-红节点-黑节点)。

实践

红黑树操作

插入操作

首先红黑树在插入节点的时,我们设定插入节点的颜色为红色,如果插入的是黑色节点,必然会违背特性5,即改变了红黑树的黑高度,如下插入红色结点又存在着几种情况:

1.黑父

如图所示,这种情况不会破坏红黑树的特性,即不需要任何处理

2.红父

当其父亲为红色时又会存在以下的情况

  • 红叔

红叔的情况,其实相对来说比较简单的,如下图所示,只需要通过修改父、叔的颜色为黑色,祖的颜色为红色,而且回去递归的检查祖节点即可

  • 黑叔

黑叔的情况有如下几种,这几种情况下是不能够通过修改颜色达到平衡的效果,因此会通过旋转的操作,红黑树种有两种旋转操作,左旋和右旋(现在存在的疑问,什么时候使用到左旋,什么时候使用到右旋)

  • Case 1:[先右旋,在改变颜色(根节点必须为黑色,其两个子节点为红色,叔节点不用改变)],如下图所示,注意省略黑哨兵节点
    

    

    

    
  • Case 2:[先左旋变成Case1中的情况,再右旋,最后改变颜色(根节点必须为黑色,其两个子节点为红色,叔节点不用改变)],如下图所示,注意省略黑哨兵节点
    

    

    
  • Case 3:[先左旋,最后改变颜色(根节点必须为黑色,其两个子节点为红色,叔节点不用改变)],如下图所示,注意省略黑哨兵节点
    

    

    


    
  • Case 4:[先右旋变成Case 3的情况,再左旋,最后改变颜色(根节点必须为黑色,其两个子节点为红色,叔节点不用改变)],如下图所示,注意省略黑哨兵节点
    

    

    


    

以上就是红黑树新增节点所有可能的操作,下面会介绍红黑树中的删除操作

删除操作

删除操作相比于插入操作情况更加复杂,删除一个节点可以大致分为三种情况:

  • 1.删除的节点没有孩子节点,即当前节点为叶子节点,这种可以直接删除
  • 2.删除的节点有一个孩子节点,这种需要删除当前节点,并使用其孩子节点顶替上来
  • 3.删除的节点有两个孩子节点,这种需要先找到其后继节点(树中大于节点的最小的元素);然后将其后继节点的内容复制到该节点上,其后继节点就相当于该节点的替身, 需要注意的是其后继节点一定不会有两个孩子节点(这点应该很好理解,如果后继节点有左孩子节点,那么当前的后继节点肯定不是最小的,说明后继节点只能存在没有孩子节点或者只有一个右孩子节点),即这样就将问题转换成为1,2中的方式。

在讲述修复操作之前,首先需要明白几点,

1.对于红黑树而言,单支节点的情况只有如下图所示的一种情况,即为当前节点为黑色,其孩子节点为红色,(1.假设当前节点为红色,其两个孩子节点必须为黑色,2.若有孙子节点,则必为黑色,导致黑子数量不等,而红黑树不平衡)

2.由于红黑树是特殊的二叉查找树,它的删除和二叉查找树类型,真正的删除点即为删除点A的中序遍历的后继(前继也可以),通过红黑树的特性可知这个后继必然最多只能有一个孩子,其这个孩子节点必然是右孩子节点,从而为单支情况(即这个后继节点只能有一个红色孩子或没有孩子)

下面将详细介绍,在执行删除节点操作之后,将通过修复操作使得红黑树达到平衡的情况。

  • Case 1:被删除的节点为红色,则这节点必定为叶子节点(首先这里的被删除的节点指的是真正删除的节点,通过上文得知的真正删除的节点要么是节点本身,要么是其后继节点,若是节点本身则必须为叶子节点,不为叶子节点的话其会有左右孩子,则真正删除的是其右孩子树上的最小值,若是后继节点,也必须为叶子节点,若不是则其也会有左右孩子,从而和2中相违背),这种情况下删除红色叶节点就可以了,不用进行其他的操作了。

  • Case 2:被删除的节点是黑色,其子节点是红色,将其子节点顶替上来并改变其颜色为黑色,如下图所示

  • Case 3:被删除的节点是黑色,其子节点也是黑色,将其子节点顶替上来,变成了双黑的问题,此时有以下情况
    *   Case 1:新节点的兄弟节点为**红色**,此时若新节点在左边则做左旋操作,否则做右旋操作,之后再将其父节点颜色改变为红色,兄弟节点

        

    

从图中可以看出,操作之后红黑树并未达到平衡状态,而是变成的黑兄的情况

  • Case 2:新节点的兄弟节点为黑色,此时可能有如下情况
    *   红父二黑侄:将父节点变成黑色,兄弟节点变成红色,新节点变成黑色即可,如下图所示

        

        

  • 黑父二黑侄:将父节点变成新节点的颜色,新节点变成黑色,兄弟节点染成红色,还需要继续以父节点为判定点继续判断,如下图所示
    

  • 红侄:

情况一:新节点在右子树,红侄在兄弟节点左子树,此时的操作为右旋,并将兄弟节点变为父亲的颜色,父亲节点变为黑色,侄节点变为黑色,如下图所示

情况二:新节点在右子树,红侄在兄弟节点右子树,此时的操作为先左旋,后右旋并将侄节点变为父亲的颜色,父节点变为黑色,如下图所示

情况三:新节点在左子树,红侄在兄弟节点左子树,此时的操作为先右旋在左旋并将侄节点变为父亲的颜色,父亲节点变为黑色,如下图所示

情况四:新节点在右子树,红侄在兄弟节点右子树,此时的操作为左旋,并将兄弟节点变为父节点的颜色,父亲节点变为黑色,侄节点变为黑色,如下图所示

红黑树实现

如下是使用JAVA代码实现红黑树的过程,主要包括了插入、删除、左旋、右旋、遍历等操作

插入

/* 插入一个节点
 * @param node
 */
private void insert(RBTreeNode<T> node){
    int cmp;
    RBTreeNode<T> root = this.rootNode;
    RBTreeNode<T> parent = null;

    //定位节点添加到哪个父节点下
    while(null != root){
        parent = root;
        cmp = node.key.compareTo(root.key);
        if (cmp < 0){
            root = root.left;
        } else {
            root = root.right;
        }
    }

    node.parent = parent;
    //表示当前没一个节点,那么就当新增的节点为根节点
    if (null == parent){
        this.rootNode = node;
    } else {
        //找出在当前父节点下新增节点的位置
        cmp = node.key.compareTo(parent.key);
        if (cmp < 0){
            parent.left = node;
        } else {
            parent.right = node;
        }
    }

    //设置插入节点的颜色为红色
    node.color = COLOR_RED;

    //修正为红黑树
    insertFixUp(node);
}

/**
 * 红黑树插入修正
 * @param node
 */
private void insertFixUp(RBTreeNode<T> node){
    RBTreeNode<T> parent,gparent;
    //节点的父节点存在并且为红色
    while( ((parent = getParent(node)) != null) && isRed(parent)){
        gparent = getParent(parent);

        //如果其祖父节点是空怎么处理
        // 若父节点是祖父节点的左孩子
        if(parent == gparent.left){
            RBTreeNode<T> uncle = gparent.right;
            if ((null != uncle) && isRed(uncle)){
                setColorBlack(uncle);
                setColorBlack(parent);
                setColorRed(gparent);
                node = gparent;
                continue;
            }

            if (parent.right == node){
                RBTreeNode<T> tmp;
                leftRotate(parent);
                tmp = parent;
                parent = node;
                node = tmp;
            }

            setColorBlack(parent);
            setColorRed(gparent);
            rightRotate(gparent);
        } else {
            RBTreeNode<T> uncle = gparent.left;
            if ((null != uncle) && isRed(uncle)){
                setColorBlack(uncle);
                setColorBlack(parent);
                setColorRed(gparent);
                node = gparent;
                continue;
            }

            if (parent.left == node){
                RBTreeNode<T> tmp;
                rightRotate(parent);
                tmp = parent;
                parent = node;
                node = tmp;
            }

            setColorBlack(parent);
            setColorRed(gparent);
            leftRotate(gparent);
        }
    }
    setColorBlack(this.rootNode);
}

插入节点的操作主要分为以下几步:

  • 1.定位:即遍历整理红黑树,确定添加的位置,如上代码中insert方法中就是在找到添加的位置
  • 2.修复:这也就是前面介绍的,添加元素后可能会使得红黑树不在满足其特性,这时候需要通过变色、旋转来调整红黑树,也就是如上代码中insertFixUp方法
删除节点

如下为删除节点的代码

private void remove(RBTreeNode<T> node){
    RBTreeNode<T> child,parent;
    boolean color;
    //被删除节点左右孩子都不为空的情况
    if ((null != node.left) && (null != node.right)){

        //获取到被删除节点的后继节点
        RBTreeNode<T> replace = node;

        replace = replace.right;
        while(null != replace.left){
            replace = replace.left;
        }

        //node节点不是根节点
        if (null != getParent(node)){
            //node是左节点
            if (getParent(node).left == node){
                getParent(node).left = replace;
            } else {
                getParent(node).right = replace;
            }
        } else {
            this.rootNode = replace;
        }

        child = replace.right;
        parent = getParent(replace);
        color = getColor(replace);

        if (parent == node){
            parent = replace;
        } else {
            if (null != child){
                setParent(child,parent);
            }
            parent.left = child;

            replace.right = node.right;
            setParent(node.right, replace);
        }

        replace.parent = node.parent;
        replace.color = node.color;
        replace.left = node.left;
        node.left.parent = replace;
        if (color == COLOR_BLACK){
            removeFixUp(child,parent);
        }

        node = null;
        return;
    }

    if (null != node.left){
        child = node.left;
    } else {
        child = node.right;
    }

    parent = node.parent;
    color = node.color;
    if (null != child){
        child.parent = parent;
    }

    if (null != parent){
        if (parent.left == node){
            parent.left = child;
        } else {
            parent.right = child;
        }
    } else {
        this.rootNode = child;
    }

    if (color == COLOR_BLACK){
        removeFixUp(child, parent);
    }
    node = null;
}

/**
 * 删除修复
 * @param node
 * @param parent
 */
private void removeFixUp(RBTreeNode<T> node, RBTreeNode<T> parent){
    RBTreeNode<T> other;
    //node不为空且为黑色,并且不为根节点
    while ((null == node || isBlack(node)) && (node != this.rootNode) ){
        //node是父节点的左孩子
        if (node == parent.left){
            //获取到其右孩子
            other = parent.right;
            //node节点的兄弟节点是红色
            if (isRed(other)){
                setColorBlack(other);
                setColorRed(parent);
                leftRotate(parent);
                other = parent.right;
            }

            //node节点的兄弟节点是黑色,且兄弟节点的两个孩子节点也是黑色
            if ((other.left == null || isBlack(other.left)) &&
                    (other.right == null || isBlack(other.right))){
                setColorRed(other);
                node = parent;
                parent = getParent(node);
            } else {
                //node节点的兄弟节点是黑色,且兄弟节点的右孩子是红色
                if (null == other.right || isBlack(other.right)){
                    setColorBlack(other.left);
                    setColorRed(other);
                    rightRotate(other);
                    other = parent.right;
                }
                //node节点的兄弟节点是黑色,且兄弟节点的右孩子是红色,左孩子是任意颜色
                setColor(other, getColor(parent));
                setColorBlack(parent);
                setColorBlack(other.right);
                leftRotate(parent);
                node = this.rootNode;
                break;
            }
        } else {
            other = parent.left;
            if (isRed(other)){
                setColorBlack(other);
                setColorRed(parent);
                rightRotate(parent);
                other = parent.left;
            }

            if ((null == other.left || isBlack(other.left)) &&
                    (null == other.right || isBlack(other.right))){
                setColorRed(other);
                node = parent;
                parent = getParent(node);
            } else {
                if (null == other.left || isBlack(other.left)){
                    setColorBlack(other.right);
                    setColorRed(other);
                    leftRotate(other);
                    other = parent.left;
                }

                setColor(other,getColor(parent));
                setColorBlack(parent);
                setColorBlack(other.left);
                rightRotate(parent);
                node = this.rootNode;
                break;
            }
        }
    }
    if (node!=null)
        setColorBlack(node);
}

删除节点主要分为几种情况去做对应的处理:

  • 1.删除节点,按照如下三种情况去删除节点
    • 1.真正删除的节点没有子节点
    • 2.真正删除的节点有一个子节点
    • 3.正在删除的节点有两个子节点
  • 2.修复红黑树的特性,如代码中调用removeFixUp方法修复红黑树的特性。

3.总结

以上主要介绍了红黑树的一些特性,包括一些操作详细的解析了里面的过程,写的时间比较长,感觉确实比较难理清楚。后面会持续的理解更深入,若有存在问题的地方,请指正。

参考文章

红黑树(五)之 Java的实现

通过分析 JDK 源代码研究 TreeMap 红黑树算法实现

红黑树

(图解)红黑树的插入和删除

红黑树深入剖析及Java实现

​

微信公众号

个人公众号:程序员黄小斜

​黄小斜是 985 硕士,阿里巴巴Java工程师,在自学编程、技术求职、Java学习等方面有丰富经验和独到见解,希望帮助到更多想要从事互联网行业的程序员们。​作者专注于 JAVA 后端技术栈,热衷于分享程序员干货、学习经验、求职心得,以及自学编程和Java技术栈的相关干货。​黄小斜是一个斜杠青年,坚持学习和写作,相信终身学习的力量,希望和更多的程序员交朋友,一起进步和成长!

原创电子书:关注微信公众号【程序员黄小斜】后回复【原创电子书】即可领取我原创的电子书《菜鸟程序员修炼手册:从技术小白到阿里巴巴Java工程师》这份电子书总结了我2年的Java学习之路,包括学习方法、技术总结、求职经验和面试技巧等内容,已经帮助很多的程序员拿到了心仪的offer!

程序员3T技术学习资源: 一些程序员学习技术的资源大礼包,关注公众号后,后台回复关键字 “资料” 即可免费无套路获取,包括Java、python、C 、大数据、机器学习、前端、移动端等方向的技术资料。

技术公众号:Java技术江湖

如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的微信公众号【Java技术江湖】

这是一位阿里 Java 工程师的技术小站。作者黄小斜,专注 Java 相关技术:SSM、SpringBoot、MySQL、分布式、中间件、集群、Linux、网络、多线程,偶尔讲点Docker、ELK,同时也分享技术干货和学习经验,致力于Java全栈开发!

Java工程师必备学习资源:关注公众号后回复”Java“即可领取 Java基础、进阶、项目和架构师等免费学习资料,更有数据库、分布式、微服务等热门技术学习视频,内容丰富,兼顾原理和实践,另外也将赠送作者原创的Java学习指南、Java程序员面试指南等干货资源

我的公众号

​

Java集合框架底层数据结构:从动态数组到红黑树,深入理解实现原理 深入解析List、Set、Queue、Map四大接口的常用实现类的底层实现,帮助零基础读者彻底掌握集合框架的设计逻辑。作为Java开发者,持续输出技术总结是提升能力的关键。无论你是初学Java的新手,还是希望巩固基础的中级开发者,本文都将成为你的集合类“速查手册”📚。| Java集合框架的每个类都有其独特的底层数据结构,这些结构直接影响集合的。理解集合类的底层数据结构,是写出高性能Java代码的关键。增删快但查询慢,其本质区别源于底层是数组还是链表。,获取更多Java学习和开发干货! 阅读详情

相关推荐

详细解读Java中Map集合的底层原理(干货+源码解读)

在上一篇文章中给大家讲解了Java里的Set集合及其常用子类。现在我们已经掌握了Java里的两大集合,最后还有另一大集合等待着我们学习,这就是Map集合。与之前的集合不太一样,Map集合属于双列集合,该集合中的信息是key-value形式;而之前的LIst和Set都是单列集合,里面的元素没有key。有些小伙伴可能会很好奇,我们已经学习了List和Set集合了,为什么还要再搞出来一个Map集合呢?Map集合与Collection集合又有什么不同呢?要想搞清楚以上问题,我们可以考虑这么一个需求。

关注我!带你一路 "狂飙" 到底! 3730

Java之红黑树

1、简介 红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。 红黑树是一种特化的AVL树(平衡二叉树),都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。 它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。 红黑树是一种平衡二叉查找树的变体,它的左右子树高差有可能大于 1,所以红黑树不是

qq_41720578的博客 5602

DIY便携式PEMF磁脉冲治疗仪:百元成本自制生物物理疗法设备

脉冲电磁场(PEMF)疗法是一种基于生物物理原理的非侵入性技术,它通过特定频率的电磁脉冲作用于细胞层面,影响细胞膜电位和离子通道活动,从而可能调节细胞代谢与功能。其技术价值在于提供了一种物理干预手段,在健康科技和生物黑客领域被探索用于放松、恢复等场景。实现PEMF的核心是通过信号发生与功率放大驱动电磁线圈产生可控磁场。本文以蓝牙音频模块和智能手机App为切入点,详细解析了如何利用低成本电子元件(如DFRobot XY-WRBT模块和漆包线线圈)构建一个可自定义频率的便携式PEMF设备,涵盖了从电路设计、线圈

weixin_31476015的博客 347

Java——红黑树

红黑树是一种平衡二叉搜索树,其节点由红、黑两种颜色组成。

m0_59408612的博客 1721

可变形卷积(Deformable Conv)原理解析与torch代码实现

图6为可变形卷积示意图。图1所示为普通卷积在输入特征图上进行卷积计算的过程,卷积核大小为3*3,在输入特征图尺寸为7*7上进行卷积,将卷积核权重与输入特征图对应位置元素相乘并求和得到输出特征图元素,按一定方式滑动窗口就能计算得到整张输出特征图。图6所示,在input feature map上普通卷积操作对应卷积采样区域是一个卷积核大小的正方形(绿框),而可变形卷积对应的卷积采样区域为一些蓝框表示的点,这就是可变形卷积与普通卷积的区别。先来一张图感受一下,图3为标准卷积与可变形卷积的卷积示例。

panghuzhenbang的博客 5万+

C语言入门—初识C语言

一、C语言概述 1、什么是C语言 语言是用来交流沟通的,有一方说,有一方听。必须要两方参与。(自言自语的除外) 语言是人与人交流,而C语言是人与机器交流 语言有独特的语法规则和定义,双方必须遵循这些规则和定义才能实现真正的交流。 接下来首先了解下计算机的组成: 2、计算机介绍 2.1、计算机结构组成 2.2、计算机系统组成 2.3、程序的指令 指令是对计算机进行程序控制的最小单元 计算机的指令系统是指所有指令的集合 程序是指为完成某一项特定任务而用某种言语编写的一组指令序列 3、C语言发展历程 3.

jun319817的博客 1034

Java 实现 红黑树(通俗易懂)

红黑树的概念和模拟实现

每篇博客都不是最终版,都会随着我的学习更新 3052

论文阅读------Exposure Fusion: A Simple and Practical Alternative to High Dynamic Range Photography

Mertens T, Kautz J, Van Reeth F. Exposure fusion: A simple and practical alternative to high dynamic range photography[C]//Computer graphics forum. Oxford, UK: Blackwell Publishing Ltd, 2009, 28(1): 161-171. 摘要 本文提出了一种将包围曝光的序列融合到高质量图像中的技术,而无需先转换为高动态范围(HD.

qq_25283239的博客 3396

使用红黑树实现的java集合_Java集合详解6:这次,从头到尾带你解读Java中的红黑树...

《Java集合详解系列》是我在完成夯实Java基础篇的系列博客后准备开始写的新系列。这些文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看喜欢的话麻烦点下Star、fork哈文章首发于我的个人博客:www.how2playlife.com什么是红黑树首先,什么是红黑树呢? 红黑树是一种“平衡的”二叉查找树,它是一种经典高效的算法,能够保证在最坏的情况下动态集合...

weixin_39992957的博客 253

避坑指南:Unity与Visual Studio开发环境配置中的5个常见问题及解决方案

本文针对Unity与Visual Studio开发环境配置中的5个常见问题,提供了详细的解决方案。重点解决了项目文件生成失败导致命名空间无法识别、调试器无法附加、包管理器与扩展安装混乱、脚本编译错误以及多版本环境冲突等核心痛点,帮助开发者构建稳定高效的开发调试环境。

weixin_27791839的博客 280

win10自动修复-无限循环【通用完美】超简单解决办法

2020.02.14今个我的笔记本电脑(Thinkpad Carbon 7 X1)(win10)早晨起来发现蓝屏,上面显示自动修复失败,重启后依然自动修复失败,不断手动重启,始终是修复失败。然后上网开始搜集资料找解决办法。 前边介绍关闭自动修复,如何找出错文件的方法;如果想看最终解决办法,直接看第三部分 上网就会发现这种现象很常见,同时是电脑自动安装系统更新,或者安装某些驱动出现。解决办法也大...

y15941300574的博客 19万+

Java中的红黑树(如果想知道Java中有关红黑树的知识点,那么只看这一篇就足够了!)

Java中的红黑树(如果想知道Java中有关红黑树的知识点,那么只看这一篇就足够了!)

秋刀鱼不做梦的编程日常 7584

开源libmodbus编译为32位和64位动态库

libmodbus 是支持Linux,Mac OS X,window 的一个开源库,支持modbus TCP和RTU 两种模式。

lemontree1945的博客 1922

【Java 基础篇】Java TreeSet 详解:红黑树实现的有序集合

在开始介绍TreeSet之前,我们先来回顾一下集合的基本概念。集合是 Java 编程中常用的数据结构之一,它用于存储一组对象。有序集合(Ordered Collection):其中的元素按照某种顺序排列,可以是添加顺序、自然顺序或自定义顺序。无序集合(Unordered Collection):其中的元素没有明确定义的顺序。集合可以用于存储不同类型的数据,例如整数、字符串、对象等。唯一性:集合是否允许重复元素。有序性:集合中的元素是否有顺序。性能:在集合中执行常见操作的性能,如添加、删除、查找等。

繁依Fanyi的博客 1万+

UFS软件分区介绍

本文主要介绍了ufs软件分区管理的概况,能够使大家对软件分区有个大体的认识

肥匪斐's blogs 1万+

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

java中的Set集合详解

原文之部分某处有争论,读者谨慎阅读,后期本人再进行本文内容修正 1.简介 Set集合中的元素是无序的且不可重复, 如果试图把两个相同元素加入同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入。 2.HasheSet底层数据结构 HashSet底层数据结构是哈希表,因此具有很好的存取和查找性能。 哈希表:一个元素为链表的数组,综合了链表(存储速度快)和数组(查询速度快)的优点。 3.哈希表的存取原理 3.1 调用对象的hashCode()方法,获得要存储元素的哈希值。

m0_53222768的博客 1万+

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Java中的Set集合详解

目录一、简介二、HashSet类三、TreeSet类 一、简介 Set集合中的元素是无序的且不可重复, 如果试图把两个相同元素加入同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入。 二、HashSet类 HashSet底层数据结构是哈希表,因此具有很好的存取和查找性能。 哈希表:一个元素为链表的数组,综合了链表(存储速度快)和数组(查询速度快)的优点。 哈希表的...

总结经验,与君共勉 5285

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Java集合核心详解【十分钟带你了解整个集合体系】

前言: 集合是Java中非常重要的一章,学习难度也相对较大,不会很快就能掌握,这里我们先对集合框架有一个大概的了解,记住其中的基础知识,后面深入研究某一个集合时,才能更好的掌握。 文章目录 一、集合介绍 二、集合与数组的区别 三、集合框架图 四、Collection详解图 五、Map详解 一、集合是什么? Java是面向对象的语言,一般我们在编程的时候自然需要存储对象的容器,数组可以满足这个需求,但是数组初始化时长度是固定的,但是我们往往需要一个长度可变化的容器,因此,集..

weixin_62754939的博客 2043

Java集合详解6:TreeMap和红黑树

Java集合详解6:TreeMap和红黑树 初识TreeMap 之前的文章讲解了两种Map,分别是HashMap与LinkedHashMap,它们保证了以O(1)的时间复杂度进行增、删、改、查,从存储角度考虑,这两种数据结构是非常优秀的。另外,LinkedHashMap还额外地保证了Map的遍历顺序可以与put顺序一致,解决了HashMap本身无序的问题。 尽管如此,HashMap与Link...

weixin_34290631的博客 263

新所得库 - Java集合 - HashMap & TreeMap源码解读实战篇

HashMap为什么需要链表+红黑树混合?红黑树的转换阈值是多少?为什么设定为8?TreeMap添加元素是否需要实现 hashCode/equals?(不需要)HashMap的键为什么不需要实现 Comparable?TreeMap和HashMap谁更快?(大多数场景HashMap更快)│ 计算 hash值 │↓│ 计算桶索引 i │↓│ tab[i] 为空?│是 否↓ ↓创建新节点 哈希冲突判断├ 链表插入└ 红黑树插入put() 的底层流程是怎样的?为什么要使用高位扰动?

tang7mj的博客 1455

一篇带你搞懂 java 集合

集合是java的基础。我们有了集合,在我们开发过程中,事半功倍。我们常用的集合有这几类Array,Map,Set,Queue等,他们每一类在java迭代升级的过程中,也是有不同的升级优化。

哈士奇 2万+

Java TreeSet集合详解

TreeSet是 Java 集合框架中的一种有序集合,它实现了Set接口,因此具有不允许重复元素的特性。与HashSet不同,TreeSet使用红黑树数据结构来存储元素,这使得元素在集合中保持有序。有序性TreeSet中的元素按照自然排序(元素的自然顺序)或者指定的排序方式(通过比较器)排列。这意味着您可以遍历TreeSet得到的元素是按照一定的顺序排列的。唯一性(Uniqueness):与HashSet一样,TreeSet也保证元素的唯一性,不允许重复元素。

loongnoy的博客 1717

Java集合详解——TreeSet集合的介绍及其排序

放到TreeS儿童集合中的元素:无序不可重复,但可以按照元素的大小顺序自动排序。 放到TreeSet或者TreeMap集合key部分中的元素要想做到排序,包括两种方式: 第一种:放在集合中的元素实现java.lang.Comparable接口。 第二种:在构造TreeSet或者TreeMap集合的时候给它传一个比较器对象。 Comparator的设计符合OCP原则。。...

Best_Basic的博客 9352

Java中的集合类

Java中所有的类都位于java.util包下,主要由两个接口派生出来。分别是Collection(集合)和Map.Collection(映射集合),包含了List和Set两大分支。Map是一个映射接口。Set、Map、List(集,映射,列表)可以看做集合的三大类。 而遍历集合的工具有Iterator和Enumeration(迭代器和枚举); Arrays(数组)和Collection(集合)是操作数组集合的两个工具类。 一、Java中的集合主要分为四类: 1、List列表:有序的,可重复的; 2、Q.

qq_45105530的博客 1万+

Java 常用集合类与红黑树旋转机制详解

Java 开发中最常见的集合类,系统梳理其底层结构与线程安全性,并结合红黑树旋转过程图解,讲解涉及的核心算法(如 CAS、分段锁、红黑树)

qq_72807062的博客 737
上一篇: Java集合详解5:深入理解LinkedHashMap和LRU缓存
下一篇: Java集合详解7:一文搞清楚HashSet,TreeSet与LinkedHashSet的异同
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值