红黑树简要总结

【博客】这个人的博客讲得太好了http://www.cnblogs.com/skywang12345/p/3245399.html 
【视频】北京大学《高级数据结构与算法》B站上面有 两个配合看,真的特别好。先看博客再看视频。 
【我的github上会放一些代码】https://github.com/kouhonglady/dataStruct_algorithms 
【注意!!】这个是我看了视频和博客的总结,如果直接看,看不懂了,给我自己写个笔记。

1.【红黑树基本的五个性质】:

  • 1)每个结点要么是红的,要么是黑的。
  • 2)根结点是黑的。
  • 3)每个叶结点,即空结点(NIL)是黑的。
  • 4)如果一个结点是红的,那么它的俩个儿子都是黑的。
  • 5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点(这个数目叫做阶,不包括该节点本身)。

2.【红黑树性质】:

  • 1) 红黑树是满二叉树,空叶节点也看作节点,阶为K的红黑树,最短路是K,最长是2K从根到叶的简单路径长度。
  • 2)阶为K的红黑树,树高最小为K+1,最高为2K+1.。树高最大为2log(n+1)+1。

3.【插入算法】
新节点着色为红色,若父节点是黑色算法结束。若父节点红色,双红调整。(注意这个和我开头给的博客里面写的不同,是因为博客后面两种都属于情况二)

  • 情况一:新增节点的叔父节点也是红色,父–祖换色,继续对祖父节点进行红红冲突检查(因为祖父节点变成了红色,可能与上面的节点发生红红冲突。)一直往上走的原因是,转化为情况二,可能会变平衡,如果一直不平衡最后走到树根,直接把红色变成黑色,就平衡啦。
    -这里写图片描述
  • 情况二:新增节点的叔父节点是黑色,这样就通过各种旋转,把其变得平衡。这个过程也涉及父祖变色。但是只有当其中两种情况通过旋转变成“父祖子”在一条斜线上再变色再进行最后一步旋转。
  • 这里写图片描述

4.【删除算法】
先调用BST的删除算法,删除的子节点只会是最多有一个孩子的节点(在其右子树中找替代节点的时候,着色不变)。如果删除的节点是红色的,则红黑树平衡,不需要调整。否则需要进行颜色平衡。【把删除节点的颜色复制给删除节点的子节点(即代替删除节点位置的节点),变成双色节点。】

  • 情况一: x是“红+黑”节点。
    处理方法:直接把x设为黑色,结束。此时红黑树性质全部恢复。
  • 情况二:x是“黑+黑”节点,且x是根。
    处理方法:什么都不做,结束。此时红黑树性质全部恢复。
  • 情况三:x是“黑+黑”节点,且x不是根。 双黑调整(为了满足红黑树性质5,设双黑节点的兄弟节点为c)
    —-case1:c是黑色,且子节点有红色节点,–>重构,完成操作(a,b两种情况,见图)。
    这里写图片描述
    —–case2:C是黑色,且有两个黑子节点,–>换色–>父节点B原为黑色,可能需要从B继续向上调整。(这种情况如果不能转换为case1,最后会变成B节点为双黑,并且为根节点,即情况二。)
    这里写图片描述
    —–case3:C是红色, –>转换状态–>C转为父节点,调整为case1或者case2继续处理。
    这里写图片描述
<think>好的,用户想深入了解epoll中红黑树的使用和结构,特别是数据结构的作用。我之前已经介绍过eventpoll结构体,其中提到了rbr作为红黑树节点。现在需要更详细地展开红黑树的部分。 首先,需要确认用户的基础知识。他们可能已经知道epoll的基本原理,但想深入红黑树的实现细节。因此,我需要结合内核源码和引用中的信息,解释红黑树在epoll中的具体应用。 根据引用[1],红黑树用于高效管理文件描述符,保证O(log n)的操作时间。引用[4]提到了ep_rbtree_insert函数的源码,这可以说明红黑树如何插入节点。需要解释红黑树的结构,比如节点如何组织,键值是什么。 用户的问题包括数据结构的作用,所以需要分点说明红黑树的作用,比如高效管理动态fd、快速查找和有序性。同时,结合引用中的内容,如引用[3]提到红黑树服务于多线程,中间观察者需要高效通知,这可能和事件触发机制有关。 需要对比其他数据结构,比如哈希表,解释为什么选择红黑树。引用[2]提到了哈希表的挑战,红黑树在动态增删时更稳定。这可能涉及自平衡特性,避免哈希冲突。 还要考虑红黑树在epoll中的具体实现,比如每个epitem节点包含哪些信息,如sockfd、事件掩码等。引用[4]的源码显示,插入时比较ffd(文件描述符信息),这可能作为键值。 需要提到红黑树的优势,比如插入、删除、查找都是O(log n),适合高并发场景。引用[5]指出epoll支持大量连接,红黑树的结构支撑了这一点。 可能还需要解释红黑树与就绪链表rdllist的关系,当事件触发时,如何从红黑树中找到对应的epitem并加入就绪链表。引用中提到回调函数,这部分需要简要说明。 总结来说,回答的结构应该包括红黑树的结构、节点组成、作用、源码中的实现,以及与其他数据结构的对比。确保引用相关文献,如引用[1]、[4]、[2]来支持解释,同时保持语言清晰易懂,适合有一定技术背景的读者。</think>### 深入解析epoll中红黑树的设计与作用 结合Linux内核源码与引用文献,epoll使用红黑树(`rbr`)作为核心数据结构来管理所有监控的文件描述符(fd),其设计目标是为高并发场景提供**高效的事件注册与检索能力**。以下从结构、功能、源码实现三方面详细分析: --- #### 一、红黑树的结构特性 1. **节点定义** 每个红黑树节点对应一个`epitem`结构体(即被监控的fd的元数据),关键字段如下: ```c struct epitem { struct rb_node rbn; // 红黑树节点(含颜色标记与父子指针) struct list_head rdllink; // 就绪事件链表指针 struct epoll_filefd ffd; // 文件描述符信息(sockfd + 文件指针) struct eventpoll *ep; // 所属eventpoll实例 struct epoll_event event; // 用户注册的事件掩码(EPOLLIN/EPOLLOUT等) // ...其他元数据(如等待队列项) }; ``` **键值设计**:以`ffd`(`sockfd`和文件指针的组合)作为红黑树的排序依据[^1][^4]。 2. **树形结构优势** - **自平衡性**:通过颜色标记与旋转操作,保证树高度始终为$O(\log n)$,避免退化为链表[^1][^4] - **有序性**:节点按`ffd`有序排列,支持快速范围查询与精确查找[^2] --- #### 二、红黑树的核心作用 1. **高效管理动态fd集合** - **增删操作**:`epoll_ctl(EPOLL_CTL_ADD/DEL)`通过`ep_rbtree_insert`和`ep_rbtree_remove`函数操作红黑树,时间复杂度稳定为$O(\log n)$[^4] - **对比哈希表**:红黑树无需处理哈希冲突,且动态增删场景下性能更稳定(哈希表扩容可能导致抖动)[^2] 2. **快速事件匹配** - 当内核检测到fd事件(如socket数据到达)时,通过`ep_item_poll`回调函数找到对应的`epitem`,并根据`event`掩码判断是否触发,随后将其加入`rdllist`就绪链表[^1][^5] - **查找复杂度**:通过`ffd`精确查找`epitem`仅需$O(\log n)$,优于链表的$O(n)$[^4] 3. **支持大规模并发连接** - 红黑树的内存占用与连接数成线性关系(每个节点仅需约40字节元数据),可轻松管理数十万级fd[^5] - **对比select/poll**:无需每次全量传递fd集合,内核直接通过红黑树管理长连接[^1][^5] --- #### 三、源码级实现细节(以插入为例) ```c // 内核源码片段(fs/eventpoll.c)[^4] static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi) { struct rb_node **p = &ep->rbr.rb_root.rb_node; struct rb_node *parent = NULL; struct epitem *epic; // 按ffd比较,寻找插入位置 while (*p) { parent = *p; epic = rb_entry(parent, struct epitem, rbn); if (EP_CMP_FFD(&epi->ffd, &epic->ffd) > 0) p = &parent->rb_right; else p = &parent->rb_left; } // 插入新节点并调整平衡 rb_link_node(&epi->rbn, parent, p); rb_insert_color(&epi->rbn, &ep->rbr); } ``` **关键步骤**: 1. 从根节点开始遍历,按`ffd`比较确定插入位置(左子树或右子树) 2. 插入新节点后调用`rb_insert_color`调整颜色与旋转,保持红黑树平衡[^4] --- #### 四、性能对比实验 | 操作类型 | 红黑树(epoll) | 哈希表 | 链表(poll) | |----------------|-----------------|-----------------|--------------| | 插入/删除 | $O(\log n)$ | $O(1)$~$O(n)$* | $O(1)$ | | 事件查找 | $O(\log n)$ | $O(1)$ | $O(n)$ | | 内存占用 | $O(n)$ | $O(n)$ | $O(n)$ | > *哈希表性能受负载因子影响,极端情况下退化为链表[^2] **结论**:红黑树在动态增删与查找场景下提供稳定的$O(\log n)$复杂度,完美适配epoll高并发的核心需求[^1] --- #### 五、与其他组件的关系 1. **与就绪链表(`rdllist`)**:红黑树存储所有监控的fd,而`rdllist`仅缓存已触发事件的`epitem`,两者通过回调函数联动[^5] 2. **与等待队列(`wq`)**:当`rdllist`更新时,通过`wq`唤醒阻塞在`epoll_wait`的进程,实现事件通知[^5] --- ### 相关问题 1. 红黑树的自平衡机制如何避免树高度失控? 2. 为什么选择`ffd`而非单纯`sockfd`作为红黑树键值? 3. 在百万级连接场景下,红黑树与哈希表的实际性能差异如何量化?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值