sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextEnglish}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget/core-api/rbtreemodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget#/translations/zh_TW/core-api/rbtreemodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget#/translations/it_IT/core-api/rbtreemodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget#/translations/ja_JP/core-api/rbtreemodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget#/translations/ko_KR/core-api/rbtreemodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget#/translations/sp_SP/core-api/rbtreemodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageChinese (Simplified)uh1h hh _documenthsourceNlineNubhcomment)}(h SPDX-License-Identifier: GPL-2.0h]h SPDX-License-Identifier: GPL-2.0}hhsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1hhhhhhP/var/lib/git/docbuild/linux/Documentation/translations/zh_CN/core-api/rbtree.rsthKubhnote)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]h paragraph)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hh5Documentation/translations/zh_CN/disclaimer-zh_CN.rsthKhhubah}(h]h ]h"]h$]h&]uh1hhhhhhhhNubh field_list)}(hhh](hfield)}(hhh](h field_name)}(hOriginalh]hOriginal}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhKubh field_body)}(h"Documentation/core-api/rbtree.rst h]h)}(h!Documentation/core-api/rbtree.rsth]h!Documentation/core-api/rbtree.rst}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(h翻译h]h翻译}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hhhKubh)}(h.唐艺舟 Tang Yizhou h]h)}(h-唐艺舟 Tang Yizhou h](h唐艺舟 Tang Yizhou <}(hj hhhNhNubh reference)}(htangyeechou@gmail.comh]htangyeechou@gmail.com}(hj*hhhNhNubah}(h]h ]h"]h$]h&]refurimailto:tangyeechou@gmail.comuh1j(hj ubh>}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhj ubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubeh}(h]h ]h"]h$]h&]uh1hhhhhhhhKubhsection)}(hhh](htitle)}(h Linux中的红黑树(rbtree)h]h Linux中的红黑树(rbtree)}(hj]hhhNhNubah}(h]h ]h"]h$]h&]uh1j[hjXhhhhhK ubh)}(hhh](h)}(hhh](h)}(h日期h]h日期}(hjqhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjnhhhKubh)}(h2007年1月18日h]h)}(hjh]h2007年1月18日}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjnubeh}(h]h ]h"]h$]h&]uh1hhhhKhjkhhubh)}(hhh](h)}(h作者h]h作者}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhKubh)}(hRob Landley h]h)}(hRob Landley h](h Rob Landley <}(hjhhhNhNubj))}(hrob@landley.neth]hrob@landley.net}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:rob@landley.netuh1j(hjubh>}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjubeh}(h]h ]h"]h$]h&]uh1hhhhKhjkhhubeh}(h]h ]h"]h$]h&]uh1hhjXhhhhhKubjW)}(hhh](j\)}(h'何为红黑树,它们有什么用?h]h'何为红黑树,它们有什么用?}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j[hjhhhhhKubh)}(hX红黑树是一种自平衡二叉搜索树,被用来存储可排序的键/值数据对。这与基数树(被用来高效 存储稀疏数组,因此使用长整型下标来插入/访问/删除结点)和哈希表(没有保持排序因而无法 容易地按序遍历,同时必须调节其大小和哈希函数,然而红黑树可以优雅地伸缩以便存储任意 数量的键)不同。h]hX红黑树是一种自平衡二叉搜索树,被用来存储可排序的键/值数据对。这与基数树(被用来高效 存储稀疏数组,因此使用长整型下标来插入/访问/删除结点)和哈希表(没有保持排序因而无法 容易地按序遍历,同时必须调节其大小和哈希函数,然而红黑树可以优雅地伸缩以便存储任意 数量的键)不同。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h红黑树和AVL树类似,但在插入和删除时提供了更快的实时有界的最坏情况性能(分别最多两次 旋转和三次旋转,来平衡树),查询时间轻微变慢(但时间复杂度仍然是O(log n))。h]h红黑树和AVL树类似,但在插入和删除时提供了更快的实时有界的最坏情况性能(分别最多两次 旋转和三次旋转,来平衡树),查询时间轻微变慢(但时间复杂度仍然是O(log n))。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h1引用Linux每周新闻(Linux Weekly News):h]h1引用Linux每周新闻(Linux Weekly News):}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh block_quote)}(hX内核中有多处红黑树的使用案例。最后期限调度器和完全公平排队(CFQ)I/O调度器利用 红黑树跟踪请求;数据包CD/DVD驱动程序也是如此。高精度时钟代码使用一颗红黑树组织 未完成的定时器请求。ext3文件系统用红黑树跟踪目录项。虚拟内存区域(VMAs)、epoll 文件描述符、密码学密钥和在“分层令牌桶”调度器中的网络数据包都由红黑树跟踪。 h]h)}(hX内核中有多处红黑树的使用案例。最后期限调度器和完全公平排队(CFQ)I/O调度器利用 红黑树跟踪请求;数据包CD/DVD驱动程序也是如此。高精度时钟代码使用一颗红黑树组织 未完成的定时器请求。ext3文件系统用红黑树跟踪目录项。虚拟内存区域(VMAs)、epoll 文件描述符、密码学密钥和在“分层令牌桶”调度器中的网络数据包都由红黑树跟踪。h]hX内核中有多处红黑树的使用案例。最后期限调度器和完全公平排队(CFQ)I/O调度器利用 红黑树跟踪请求;数据包CD/DVD驱动程序也是如此。高精度时钟代码使用一颗红黑树组织 未完成的定时器请求。ext3文件系统用红黑树跟踪目录项。虚拟内存区域(VMAs)、epoll 文件描述符、密码学密钥和在“分层令牌桶”调度器中的网络数据包都由红黑树跟踪。}(hj&hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj"ubah}(h]h ]h"]h$]h&]uh1j hhhKhjhhubh)}(hw本文档涵盖了对Linux红黑树实现的使用方法。更多关于红黑树的性质和实现的信息,参见:h]hw本文档涵盖了对Linux红黑树实现的使用方法。更多关于红黑树的性质和实现的信息,参见:}(hj:hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK$hjhhubj!)}(hLinux每周新闻关于红黑树的文章 https://lwn.net/Articles/184495/ 维基百科红黑树词条 https://en.wikipedia.org/wiki/Red-black_tree h]hdefinition_list)}(hhh](hdefinition_list_item)}(hKLinux每周新闻关于红黑树的文章 https://lwn.net/Articles/184495/ h](hterm)}(h)Linux每周新闻关于红黑树的文章h]h)Linux每周新闻关于红黑树的文章}(hjYhhhNhNubah}(h]h ]h"]h$]h&]uh1jWhhhK'hjSubh definition)}(hhh]h)}(h https://lwn.net/Articles/184495/h]j))}(hjnh]h https://lwn.net/Articles/184495/}(hjphhhNhNubah}(h]h ]h"]h$]h&]refurijnuh1j(hjlubah}(h]h ]h"]h$]h&]uh1hhhhK'hjiubah}(h]h ]h"]h$]h&]uh1jghjSubeh}(h]h ]h"]h$]h&]uh1jQhhhK'hjNubjR)}(hI维基百科红黑树词条 https://en.wikipedia.org/wiki/Red-black_tree h](jX)}(h维基百科红黑树词条h]h维基百科红黑树词条}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jWhhhK*hjubjh)}(hhh]h)}(h,https://en.wikipedia.org/wiki/Red-black_treeh]j))}(hjh]h,https://en.wikipedia.org/wiki/Red-black_tree}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurijuh1j(hjubah}(h]h ]h"]h$]h&]uh1hhhhK*hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jQhhhK*hjNubeh}(h]h ]h"]h$]h&]uh1jLhjHubah}(h]h ]h"]h$]h&]uh1j hhhK&hjhhubeh}(h]id1ah ]h"]'何为红黑树,它们有什么用?ah$]h&]uh1jVhjXhhhhhKubjW)}(hhh](j\)}(h红黑树的Linux实现h]h红黑树的Linux实现}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j[hjhhhhhK-ubh)}(hoLinux的红黑树实现在文件“lib/rbtree.c”中。要使用它,需要“#include ”。h]hoLinux的红黑树实现在文件“lib/rbtree.c”中。要使用它,需要“#include ”。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK/hjhhubh)}(hXLinux的红黑树实现对速度进行了优化,因此比传统的实现少一个间接层(有更好的缓存局部性)。 每个rb_node结构体的实例嵌入在它管理的数据结构中,因此不需要靠指针来分离rb_node和它 管理的数据结构。用户应该编写他们自己的树搜索和插入函数,来调用已提供的红黑树函数, 而不是使用一个比较回调函数指针。加锁代码也留给红黑树的用户编写。h]hXLinux的红黑树实现对速度进行了优化,因此比传统的实现少一个间接层(有更好的缓存局部性)。 每个rb_node结构体的实例嵌入在它管理的数据结构中,因此不需要靠指针来分离rb_node和它 管理的数据结构。用户应该编写他们自己的树搜索和插入函数,来调用已提供的红黑树函数, 而不是使用一个比较回调函数指针。加锁代码也留给红黑树的用户编写。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK1hjhhubeh}(h]linuxah ]h"]红黑树的linux实现ah$]h&]uh1jVhjXhhhhhK-ubjW)}(hhh](j\)}(h创建一颗红黑树h]h创建一颗红黑树}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j[hjhhhhhK7ubh)}(hH红黑树中的数据结点是包含rb_node结构体成员的结构体::h]hG红黑树中的数据结点是包含rb_node结构体成员的结构体:}(hj#hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK9hjhhubh literal_block)}(hDstruct mytype { struct rb_node node; char *keystring; };h]hDstruct mytype { struct rb_node node; char *keystring; };}hj3sbah}(h]h ]h"]h$]h&]hhuh1j1hhhK;hjhhubh)}(h当处理一个指向内嵌rb_node结构体的指针时,包住rb_node的结构体可用标准的container_of() 宏访问。此外,个体成员可直接用rb_entry(node, type, member)访问。h]h当处理一个指向内嵌rb_node结构体的指针时,包住rb_node的结构体可用标准的container_of() 宏访问。此外,个体成员可直接用rb_entry(node, type, member)访问。}(hjAhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK@hjhhubh)}(hV每颗红黑树的根是一个rb_root数据结构,它由以下方式初始化为空:h]hV每颗红黑树的根是一个rb_root数据结构,它由以下方式初始化为空:}(hjOhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKChjhhubj!)}(h!struct rb_root mytree = RB_ROOT; h]h)}(h struct rb_root mytree = RB_ROOT;h]h struct rb_root mytree = RB_ROOT;}(hjahhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKEhj]ubah}(h]h ]h"]h$]h&]uh1j hhhKEhjhhubeh}(h]id2ah ]h"]创建一颗红黑树ah$]h&]uh1jVhjXhhhhhK7ubjW)}(hhh](j\)}(h在一颗红黑树中搜索值h]h在一颗红黑树中搜索值}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j[hj}hhhhhKHubh)}(h为你的树写一个搜索函数是相当简单的:从树根开始,比较每个值,然后根据需要继续前往左边或 右边的分支。h]h为你的树写一个搜索函数是相当简单的:从树根开始,比较每个值,然后根据需要继续前往左边或 右边的分支。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKJhj}hhubh)}(h示例::h]h示例:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKMhj}hhubj2)}(hXstruct mytype *my_search(struct rb_root *root, char *string) { struct rb_node *node = root->rb_node; while (node) { struct mytype *data = container_of(node, struct mytype, node); int result; result = strcmp(string, data->keystring); if (result < 0) node = node->rb_left; else if (result > 0) node = node->rb_right; else return data; } return NULL; }h]hXstruct mytype *my_search(struct rb_root *root, char *string) { struct rb_node *node = root->rb_node; while (node) { struct mytype *data = container_of(node, struct mytype, node); int result; result = strcmp(string, data->keystring); if (result < 0) node = node->rb_left; else if (result > 0) node = node->rb_right; else return data; } return NULL; }}hjsbah}(h]h ]h"]h$]h&]hhuh1j1hhhKOhj}hhubeh}(h]id3ah ]h"]在一颗红黑树中搜索值ah$]h&]uh1jVhjXhhhhhKHubjW)}(hhh](j\)}(h!在一颗红黑树中插入数据h]h!在一颗红黑树中插入数据}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j[hjhhhhhKdubh)}(h在树中插入数据的步骤包括:首先搜索插入新结点的位置,然后插入结点并对树再平衡 ("recoloring")。h]h在树中插入数据的步骤包括:首先搜索插入新结点的位置,然后插入结点并对树再平衡 (”recoloring”)。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKfhjhhubh)}(h插入的搜索和上文的搜索不同,它要找到嫁接新结点的位置。新结点也需要一个指向它的父节点 的链接,以达到再平衡的目的。h]h插入的搜索和上文的搜索不同,它要找到嫁接新结点的位置。新结点也需要一个指向它的父节点 的链接,以达到再平衡的目的。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKihjhhubh)}(h示例::h]h示例:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKlhjhhubj2)}(hXint my_insert(struct rb_root *root, struct mytype *data) { struct rb_node **new = &(root->rb_node), *parent = NULL; /* Figure out where to put new node */ while (*new) { struct mytype *this = container_of(*new, struct mytype, node); int result = strcmp(data->keystring, this->keystring); parent = *new; if (result < 0) new = &((*new)->rb_left); else if (result > 0) new = &((*new)->rb_right); else return FALSE; } /* Add new node and rebalance tree. */ rb_link_node(&data->node, parent, new); rb_insert_color(&data->node, root); return TRUE; }h]hXint my_insert(struct rb_root *root, struct mytype *data) { struct rb_node **new = &(root->rb_node), *parent = NULL; /* Figure out where to put new node */ while (*new) { struct mytype *this = container_of(*new, struct mytype, node); int result = strcmp(data->keystring, this->keystring); parent = *new; if (result < 0) new = &((*new)->rb_left); else if (result > 0) new = &((*new)->rb_right); else return FALSE; } /* Add new node and rebalance tree. */ rb_link_node(&data->node, parent, new); rb_insert_color(&data->node, root); return TRUE; }}hjsbah}(h]h ]h"]h$]h&]hhuh1j1hhhKnhjhhubeh}(h]id4ah ]h"]!在一颗红黑树中插入数据ah$]h&]uh1jVhjXhhhhhKdubjW)}(hhh](j\)}(h9在一颗红黑树中删除或替换已经存在的数据h]h9在一颗红黑树中删除或替换已经存在的数据}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j[hjhhhhhKubh)}(h;若要从树中删除一个已经存在的结点,调用::h]h:若要从树中删除一个已经存在的结点,调用:}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj2)}(hhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj2)}(h{struct mytype *data = mysearch(&mytree, "walrus"); if (data) { rb_erase(&data->node, &mytree); myfree(data); }h]h{struct mytype *data = mysearch(&mytree, "walrus"); if (data) { rb_erase(&data->node, &mytree); myfree(data); }}hjLsbah}(h]h ]h"]h$]h&]hhuh1j1hhhKhjhhubh)}(hY若要用一个新结点替换树中一个已经存在的键值相同的结点,调用::h]hX若要用一个新结点替换树中一个已经存在的键值相同的结点,调用:}(hjZhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj2)}(hkvoid rb_replace_node(struct rb_node *old, struct rb_node *new, struct rb_root *tree);h]hkvoid rb_replace_node(struct rb_node *old, struct rb_node *new, struct rb_root *tree);}hjhsbah}(h]h ]h"]h$]h&]hhuh1j1hhhKhjhhubh)}(h通过这种方式替换结点不会对树做重排序:如果新结点的键值和旧结点不同,红黑树可能被 破坏。h]h通过这种方式替换结点不会对树做重排序:如果新结点的键值和旧结点不同,红黑树可能被 破坏。}(hjvhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubeh}(h]id5ah ]h"]9在一颗红黑树中删除或替换已经存在的数据ah$]h&]uh1jVhjXhhhhhKubjW)}(hhh](j\)}(h<(按排序的顺序)遍历存储在红黑树中的元素h]h<(按排序的顺序)遍历存储在红黑树中的元素}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j[hjhhhhhKubh)}(h我们提供了四个函数,用于以排序的方式遍历一颗红黑树的内容。这些函数可以在任意红黑树 上工作,并且不需要被修改或包装(除非加锁的目的)::h]h我们提供了四个函数,用于以排序的方式遍历一颗红黑树的内容。这些函数可以在任意红黑树 上工作,并且不需要被修改或包装(除非加锁的目的):}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj2)}(hstruct rb_node *rb_first(struct rb_root *tree); struct rb_node *rb_last(struct rb_root *tree); struct rb_node *rb_next(struct rb_node *node); struct rb_node *rb_prev(struct rb_node *node);h]hstruct rb_node *rb_first(struct rb_root *tree); struct rb_node *rb_last(struct rb_root *tree); struct rb_node *rb_next(struct rb_node *node); struct rb_node *rb_prev(struct rb_node *node);}hjsbah}(h]h ]h"]h$]h&]hhuh1j1hhhKhjhhubh)}(hXT要开始迭代,需要使用一个指向树根的指针调用rb_first()或rb_last(),它将返回一个指向 树中第一个或最后一个元素所包含的节点结构的指针。要继续的话,可以在当前结点上调用 rb_next()或rb_prev()来获取下一个或上一个结点。当没有剩余的结点时,将返回NULL。h]hXT要开始迭代,需要使用一个指向树根的指针调用rb_first()或rb_last(),它将返回一个指向 树中第一个或最后一个元素所包含的节点结构的指针。要继续的话,可以在当前结点上调用 rb_next()或rb_prev()来获取下一个或上一个结点。当没有剩余的结点时,将返回NULL。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h迭代器函数返回一个指向被嵌入的rb_node结构体的指针,由此,包住rb_node的结构体可用 标准的container_of()宏访问。此外,个体成员可直接用rb_entry(node, type, member) 访问。h]h迭代器函数返回一个指向被嵌入的rb_node结构体的指针,由此,包住rb_node的结构体可用 标准的container_of()宏访问。此外,个体成员可直接用rb_entry(node, type, member) 访问。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h示例::h]h示例:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj2)}(hstruct rb_node *node; for (node = rb_first(&mytree); node; node = rb_next(node)) printk("key=%s\n", rb_entry(node, struct mytype, node)->keystring);h]hstruct rb_node *node; for (node = rb_first(&mytree); node; node = rb_next(node)) printk("key=%s\n", rb_entry(node, struct mytype, node)->keystring);}hjsbah}(h]h ]h"]h$]h&]hhuh1j1hhhKhjhhubeh}(h]id6ah ]h"]<(按排序的顺序)遍历存储在红黑树中的元素ah$]h&]uh1jVhjXhhhhhKubjW)}(hhh](j\)}(h带缓存的红黑树h]h带缓存的红黑树}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j[hjhhhhhKubh)}(hX计算最左边(最小的)结点是二叉搜索树的一个相当常见的任务,例如用于遍历,或用户根据 他们自己的逻辑依赖一个特定的顺序。为此,用户可以使用'struct rb_root_cached'来优化 时间复杂度为O(logN)的rb_first()的调用,以简单地获取指针,避免了潜在的昂贵的树迭代。 维护操作的额外运行时间开销可忽略,不过内存占用较大。h]hX计算最左边(最小的)结点是二叉搜索树的一个相当常见的任务,例如用于遍历,或用户根据 他们自己的逻辑依赖一个特定的顺序。为此,用户可以使用’struct rb_root_cached’来优化 时间复杂度为O(logN)的rb_first()的调用,以简单地获取指针,避免了潜在的昂贵的树迭代。 维护操作的额外运行时间开销可忽略,不过内存占用较大。}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hQ和rb_root结构体类似,带缓存的红黑树由以下方式初始化为空::h]hP和rb_root结构体类似,带缓存的红黑树由以下方式初始化为空:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj2)}(h.struct rb_root_cached mytree = RB_ROOT_CACHED;h]h.struct rb_root_cached mytree = RB_ROOT_CACHED;}hj&sbah}(h]h ]h"]h$]h&]hhuh1j1hhhKhjhhubh)}(h带缓存的红黑树只是一个常规的rb_root,加上一个额外的指针来缓存最左边的节点。这使得 rb_root_cached可以存在于rb_root存在的任何地方,并且只需增加几个接口来支持带缓存的 树::h]h带缓存的红黑树只是一个常规的rb_root,加上一个额外的指针来缓存最左边的节点。这使得 rb_root_cached可以存在于rb_root存在的任何地方,并且只需增加几个接口来支持带缓存的 树:}(hj4hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj2)}(hstruct rb_node *rb_first_cached(struct rb_root_cached *tree); void rb_insert_color_cached(struct rb_node *, struct rb_root_cached *, bool); void rb_erase_cached(struct rb_node *node, struct rb_root_cached *);h]hstruct rb_node *rb_first_cached(struct rb_root_cached *tree); void rb_insert_color_cached(struct rb_node *, struct rb_root_cached *, bool); void rb_erase_cached(struct rb_node *node, struct rb_root_cached *);}hjBsbah}(h]h ]h"]h$]h&]hhuh1j1hhhKhjhhubh)}(h8操作和删除也有对应的带缓存的树的调用::h]h7操作和删除也有对应的带缓存的树的调用:}(hjPhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj2)}(hXvoid rb_insert_augmented_cached(struct rb_node *node, struct rb_root_cached *, bool, struct rb_augment_callbacks *); void rb_erase_augmented_cached(struct rb_node *, struct rb_root_cached *, struct rb_augment_callbacks *);h]hXvoid rb_insert_augmented_cached(struct rb_node *node, struct rb_root_cached *, bool, struct rb_augment_callbacks *); void rb_erase_augmented_cached(struct rb_node *, struct rb_root_cached *, struct rb_augment_callbacks *);}hj^sbah}(h]h ]h"]h$]h&]hhuh1j1hhhKhjhhubeh}(h]id7ah ]h"]带缓存的红黑树ah$]h&]uh1jVhjXhhhhhKubjW)}(hhh](j\)}(h对增强型红黑树的支持h]h对增强型红黑树的支持}(hjwhhhNhNubah}(h]h ]h"]h$]h&]uh1j[hjthhhhhKubh)}(hXx增强型红黑树是一种在每个结点里存储了“一些”附加数据的红黑树,其中结点N的附加数据 必须是以N为根的子树中所有结点的内容的函数。它是建立在红黑树基础设施之上的可选特性。 想要使用这个特性的红黑树用户,插入和删除结点时必须调用增强型接口并提供增强型回调函数。h]hXx增强型红黑树是一种在每个结点里存储了“一些”附加数据的红黑树,其中结点N的附加数据 必须是以N为根的子树中所有结点的内容的函数。它是建立在红黑树基础设施之上的可选特性。 想要使用这个特性的红黑树用户,插入和删除结点时必须调用增强型接口并提供增强型回调函数。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjthhubh)}(hXw实现增强型红黑树操作的C文件必须包含而不是。 注意,linux/rbtree_augmented.h暴露了一些红黑树实现的细节而你不应依赖它们,请坚持 使用文档记录的API,并且不要在头文件中包含,以最小化你的 用户意外地依赖这些实现细节的可能。h]hXw实现增强型红黑树操作的C文件必须包含而不是。 注意,linux/rbtree_augmented.h暴露了一些红黑树实现的细节而你不应依赖它们,请坚持 使用文档记录的API,并且不要在头文件中包含,以最小化你的 用户意外地依赖这些实现细节的可能。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjthhubh)}(hXW插入时,用户必须更新通往被插入节点的路径上的增强信息,然后像往常一样调用rb_link_node(), 然后是rb_augment_inserted()而不是平时的rb_insert_color()调用。如果 rb_augment_inserted()再平衡了红黑树,它将回调至一个用户提供的函数来更新受影响的 子树上的增强信息。h]hXW插入时,用户必须更新通往被插入节点的路径上的增强信息,然后像往常一样调用rb_link_node(), 然后是rb_augment_inserted()而不是平时的rb_insert_color()调用。如果 rb_augment_inserted()再平衡了红黑树,它将回调至一个用户提供的函数来更新受影响的 子树上的增强信息。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjthhubh)}(h删除一个结点时,用户必须调用rb_erase_augmented()而不是rb_erase()。 rb_erase_augmented()回调至一个用户提供的函数来更新受影响的子树上的增强信息。h]h删除一个结点时,用户必须调用rb_erase_augmented()而不是rb_erase()。 rb_erase_augmented()回调至一个用户提供的函数来更新受影响的子树上的增强信息。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjthhubh)}(hi在两种情况下,回调都是通过rb_augment_callbacks结构体提供的。必须定义3个回调:h]hi在两种情况下,回调都是通过rb_augment_callbacks结构体提供的。必须定义3个回调:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjthhubh bullet_list)}(hhh](h list_item)}(h一个传播回调,它更新一个给定结点和它的祖先们的增强数据,直到一个给定的停止点 (如果是NULL,将更新一路更新到树根)。 h]h)}(h一个传播回调,它更新一个给定结点和它的祖先们的增强数据,直到一个给定的停止点 (如果是NULL,将更新一路更新到树根)。h]h一个传播回调,它更新一个给定结点和它的祖先们的增强数据,直到一个给定的停止点 (如果是NULL,将更新一路更新到树根)。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(hg一个复制回调,它将一颗给定子树的增强数据复制到一个新指定的子树树根。 h]h)}(hf一个复制回调,它将一颗给定子树的增强数据复制到一个新指定的子树树根。h]hf一个复制回调,它将一颗给定子树的增强数据复制到一个新指定的子树树根。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(h一个树旋转回调,它将一颗给定的子树的增强值复制到新指定的子树树根上,并重新计算 先前的子树树根的增强值。 h]h)}(h一个树旋转回调,它将一颗给定的子树的增强值复制到新指定的子树树根上,并重新计算 先前的子树树根的增强值。h]h一个树旋转回调,它将一颗给定的子树的增强值复制到新指定的子树树根上,并重新计算 先前的子树树根的增强值。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubeh}(h]h ]h"]h$]h&]bullet-uh1jhhhKhjthhubh)}(hrb_erase_augmented()编译后的代码可能会内联传播、复制回调,这将导致函数体积更大, 因此每个增强型红黑树的用户应该只有一个rb_erase_augmented()的调用点,以限制编译后 的代码大小。h]hrb_erase_augmented()编译后的代码可能会内联传播、复制回调,这将导致函数体积更大, 因此每个增强型红黑树的用户应该只有一个rb_erase_augmented()的调用点,以限制编译后 的代码大小。}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjthhubjW)}(hhh](j\)}(h 使用示例h]h 使用示例}(hj3hhhNhNubah}(h]h ]h"]h$]h&]uh1j[hj0hhhhhKubh)}(h区间树是增强型红黑树的一个例子。参考Cormen,Leiserson,Rivest和Stein写的 《算法导论》。区间树的更多细节:h]h区间树是增强型红黑树的一个例子。参考Cormen,Leiserson,Rivest和Stein写的 《算法导论》。区间树的更多细节:}(hjAhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj0hhubh)}(h经典的红黑树只有一个键,它不能直接用来存储像[lo:hi]这样的区间范围,也不能快速查找 与新的lo:hi重叠的部分,或者查找是否有与新的lo:hi完全匹配的部分。h]h经典的红黑树只有一个键,它不能直接用来存储像[lo:hi]这样的区间范围,也不能快速查找 与新的lo:hi重叠的部分,或者查找是否有与新的lo:hi完全匹配的部分。}(hjOhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj0hhubh)}(h然而,红黑树可以被增强,以一种结构化的方式来存储这种区间范围,从而使高效的查找和 精确匹配成为可能。h]h然而,红黑树可以被增强,以一种结构化的方式来存储这种区间范围,从而使高效的查找和 精确匹配成为可能。}(hj]hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj0hhubh)}(hXU这个存储在每个节点中的“额外信息”是其所有后代结点中的最大hi(max_hi)值。这个信息 可以保持在每个结点上,只需查看一下该结点和它的直系子结点们。这将被用于时间复杂度 为O(log n)的最低匹配查找(所有可能的匹配中最低的起始地址),就像这样::h]hXT这个存储在每个节点中的“额外信息”是其所有后代结点中的最大hi(max_hi)值。这个信息 可以保持在每个结点上,只需查看一下该结点和它的直系子结点们。这将被用于时间复杂度 为O(log n)的最低匹配查找(所有可能的匹配中最低的起始地址),就像这样:}(hjkhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj0hhubj2)}(hX/struct interval_tree_node * interval_tree_first_match(struct rb_root *root, unsigned long start, unsigned long last) { struct interval_tree_node *node; if (!root->rb_node) return NULL; node = rb_entry(root->rb_node, struct interval_tree_node, rb); while (true) { if (node->rb.rb_left) { struct interval_tree_node *left = rb_entry(node->rb.rb_left, struct interval_tree_node, rb); if (left->__subtree_last >= start) { /* * Some nodes in left subtree satisfy Cond2. * Iterate to find the leftmost such node N. * If it also satisfies Cond1, that's the match * we are looking for. Otherwise, there is no * matching interval as nodes to the right of N * can't satisfy Cond1 either. */ node = left; continue; } } if (node->start <= last) { /* Cond1 */ if (node->last >= start) /* Cond2 */ return node; /* node is leftmost match */ if (node->rb.rb_right) { node = rb_entry(node->rb.rb_right, struct interval_tree_node, rb); if (node->__subtree_last >= start) continue; } } return NULL; /* No match */ } }h]hX/struct interval_tree_node * interval_tree_first_match(struct rb_root *root, unsigned long start, unsigned long last) { struct interval_tree_node *node; if (!root->rb_node) return NULL; node = rb_entry(root->rb_node, struct interval_tree_node, rb); while (true) { if (node->rb.rb_left) { struct interval_tree_node *left = rb_entry(node->rb.rb_left, struct interval_tree_node, rb); if (left->__subtree_last >= start) { /* * Some nodes in left subtree satisfy Cond2. * Iterate to find the leftmost such node N. * If it also satisfies Cond1, that's the match * we are looking for. Otherwise, there is no * matching interval as nodes to the right of N * can't satisfy Cond1 either. */ node = left; continue; } } if (node->start <= last) { /* Cond1 */ if (node->last >= start) /* Cond2 */ return node; /* node is leftmost match */ if (node->rb.rb_right) { node = rb_entry(node->rb.rb_right, struct interval_tree_node, rb); if (node->__subtree_last >= start) continue; } } return NULL; /* No match */ } }}hjysbah}(h]h ]h"]h$]h&]hhuh1j1hhhMhj0hhubh)}(h9插入/删除是通过以下增强型回调来定义的::h]h8插入/删除是通过以下增强型回调来定义的:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM1hj0hhubj2)}(hX static inline unsigned long compute_subtree_last(struct interval_tree_node *node) { unsigned long max = node->last, subtree_last; if (node->rb.rb_left) { subtree_last = rb_entry(node->rb.rb_left, struct interval_tree_node, rb)->__subtree_last; if (max < subtree_last) max = subtree_last; } if (node->rb.rb_right) { subtree_last = rb_entry(node->rb.rb_right, struct interval_tree_node, rb)->__subtree_last; if (max < subtree_last) max = subtree_last; } return max; } static void augment_propagate(struct rb_node *rb, struct rb_node *stop) { while (rb != stop) { struct interval_tree_node *node = rb_entry(rb, struct interval_tree_node, rb); unsigned long subtree_last = compute_subtree_last(node); if (node->__subtree_last == subtree_last) break; node->__subtree_last = subtree_last; rb = rb_parent(&node->rb); } } static void augment_copy(struct rb_node *rb_old, struct rb_node *rb_new) { struct interval_tree_node *old = rb_entry(rb_old, struct interval_tree_node, rb); struct interval_tree_node *new = rb_entry(rb_new, struct interval_tree_node, rb); new->__subtree_last = old->__subtree_last; } static void augment_rotate(struct rb_node *rb_old, struct rb_node *rb_new) { struct interval_tree_node *old = rb_entry(rb_old, struct interval_tree_node, rb); struct interval_tree_node *new = rb_entry(rb_new, struct interval_tree_node, rb); new->__subtree_last = old->__subtree_last; old->__subtree_last = compute_subtree_last(old); } static const struct rb_augment_callbacks augment_callbacks = { augment_propagate, augment_copy, augment_rotate }; void interval_tree_insert(struct interval_tree_node *node, struct rb_root *root) { struct rb_node **link = &root->rb_node, *rb_parent = NULL; unsigned long start = node->start, last = node->last; struct interval_tree_node *parent; while (*link) { rb_parent = *link; parent = rb_entry(rb_parent, struct interval_tree_node, rb); if (parent->__subtree_last < last) parent->__subtree_last = last; if (start < parent->start) link = &parent->rb.rb_left; else link = &parent->rb.rb_right; } node->__subtree_last = last; rb_link_node(&node->rb, rb_parent, link); rb_insert_augmented(&node->rb, root, &augment_callbacks); } void interval_tree_remove(struct interval_tree_node *node, struct rb_root *root) { rb_erase_augmented(&node->rb, root, &augment_callbacks); }h]hX static inline unsigned long compute_subtree_last(struct interval_tree_node *node) { unsigned long max = node->last, subtree_last; if (node->rb.rb_left) { subtree_last = rb_entry(node->rb.rb_left, struct interval_tree_node, rb)->__subtree_last; if (max < subtree_last) max = subtree_last; } if (node->rb.rb_right) { subtree_last = rb_entry(node->rb.rb_right, struct interval_tree_node, rb)->__subtree_last; if (max < subtree_last) max = subtree_last; } return max; } static void augment_propagate(struct rb_node *rb, struct rb_node *stop) { while (rb != stop) { struct interval_tree_node *node = rb_entry(rb, struct interval_tree_node, rb); unsigned long subtree_last = compute_subtree_last(node); if (node->__subtree_last == subtree_last) break; node->__subtree_last = subtree_last; rb = rb_parent(&node->rb); } } static void augment_copy(struct rb_node *rb_old, struct rb_node *rb_new) { struct interval_tree_node *old = rb_entry(rb_old, struct interval_tree_node, rb); struct interval_tree_node *new = rb_entry(rb_new, struct interval_tree_node, rb); new->__subtree_last = old->__subtree_last; } static void augment_rotate(struct rb_node *rb_old, struct rb_node *rb_new) { struct interval_tree_node *old = rb_entry(rb_old, struct interval_tree_node, rb); struct interval_tree_node *new = rb_entry(rb_new, struct interval_tree_node, rb); new->__subtree_last = old->__subtree_last; old->__subtree_last = compute_subtree_last(old); } static const struct rb_augment_callbacks augment_callbacks = { augment_propagate, augment_copy, augment_rotate }; void interval_tree_insert(struct interval_tree_node *node, struct rb_root *root) { struct rb_node **link = &root->rb_node, *rb_parent = NULL; unsigned long start = node->start, last = node->last; struct interval_tree_node *parent; while (*link) { rb_parent = *link; parent = rb_entry(rb_parent, struct interval_tree_node, rb); if (parent->__subtree_last < last) parent->__subtree_last = last; if (start < parent->start) link = &parent->rb.rb_left; else link = &parent->rb.rb_right; } node->__subtree_last = last; rb_link_node(&node->rb, rb_parent, link); rb_insert_augmented(&node->rb, root, &augment_callbacks); } void interval_tree_remove(struct interval_tree_node *node, struct rb_root *root) { rb_erase_augmented(&node->rb, root, &augment_callbacks); }}hjsbah}(h]h ]h"]h$]h&]hhuh1j1hhhM3hj0hhubeh}(h]id9ah ]h"] 使用示例ah$]h&]uh1jVhjthhhhhKubeh}(h]id8ah ]h"]对增强型红黑树的支持ah$]h&]uh1jVhjXhhhhhKubeh}(h] linux-rbtreeah ]h"] linux中的红黑树(rbtree)ah$]h&]uh1jVhhhhhhhK ubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(j[N generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(jjjjjj jzjwjjjj jjjjjqjnjjjju nametypes}(jjjjzjjjjjqjjuh}(jjXjjj jjwjjj}j jjjjjjnjjjtjj0u footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}jK sRparse_messages]transform_messages] transformerN include_log]4Documentation/translations/zh_CN/core-api/rbtree.rst(NNNNta decorationNhhub.