首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

linux 红黑树 封装map

红黑树是一种自平衡的二叉查找树,它在Linux内核中被广泛用于实现高效的查找、插入和删除操作。红黑树的每个节点都有一个颜色属性(红色或黑色),并且满足以下性质:

  1. 每个节点要么是红色,要么是黑色。
  2. 根节点是黑色。
  3. 所有叶子节点(NIL节点)是黑色。
  4. 如果一个节点是红色的,则它的两个子节点都是黑色的。
  5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

这些性质保证了红黑树的平衡性,使得在最坏情况下,查找、插入和删除操作的时间复杂度都是O(log n)。

红黑树封装Map的优势

  1. 高效的查找性能:由于红黑树的自平衡特性,查找操作的时间复杂度为O(log n),比哈希表的平均时间复杂度稍慢,但在最坏情况下仍能保持较好的性能。
  2. 有序性:红黑树中的元素是有序的,这使得范围查询和顺序遍历变得高效。
  3. 稳定的性能:相比于哈希表,红黑树在最坏情况下的性能不会退化到O(n)。

类型与应用场景

  • 类型:红黑树通常用于实现关联数组(Map),其中键值对按照键的顺序存储。
  • 应用场景
    • 需要频繁进行范围查询的场景。
    • 需要保持元素有序的场景。
    • 对查找性能有较高要求且数据量较大的场景。

示例代码

以下是一个简单的红黑树封装Map的示例代码(使用C语言和Linux内核中的红黑树实现):

代码语言:txt
复制
#include <linux/rbtree.h>
#include <linux/kernel.h>

// 定义键值对结构体
struct my_key_value {
    int key;
    char value[100];
    struct rb_node node;
};

// 定义红黑树根节点
static struct rb_root my_tree = RB_ROOT;

// 插入键值对
void insert_key_value(int key, const char *value) {
    struct my_key_value *new_kv = kmalloc(sizeof(struct my_key_value), GFP_KERNEL);
    if (!new_kv)
        return;

    new_kv->key = key;
    strcpy(new_kv->value, value);

    struct rb_node **new = &(my_tree.rb_node), *parent = NULL;
    struct my_key_value *this;

    while (*new) {
        this = container_of(*new, struct my_key_value, node);
        parent = *new;

        if (key < this->key)
            new = &((*new)->rb_left);
        else if (key > this->key)
            new = &((*new)->rb_right);
        else
            break;
    }

    rb_link_node(&new_kv->node, parent, new);
    rb_insert_color(&new_kv->node, &my_tree);
}

// 查找键值对
char *find_key_value(int key) {
    struct my_key_value *kv;
    kv = rb_find(&my_tree, &my_key_value, key);
    if (kv)
        return kv->value;
    return NULL;
}

// 删除键值对
void delete_key_value(int key) {
    struct my_key_value *kv;
    kv = rb_find(&my_tree, &my_key_value, key);
    if (kv) {
        rb_erase(&kv->node, &my_tree);
        kfree(kv);
    }
}

可能遇到的问题及解决方法

  1. 插入操作失败:可能是由于内存分配失败(kmalloc返回NULL)。解决方法是在插入前检查内存分配是否成功。
  2. 查找操作失败:可能是由于键不存在。解决方法是在查找后检查返回值是否为NULL。
  3. 删除操作失败:可能是由于键不存在。解决方法是在删除前检查键是否存在。

通过上述代码和解释,你应该能够理解红黑树封装Map的基础概念、优势、类型、应用场景以及常见问题的解决方法。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

手撕AVL树、红黑树,红黑树封装map、set

树形结构主要有四种:map,set,multimap,multiset。这四种容器的共同点是使用平衡搜索树即红黑树作为底层结构,容器中的元素是一个有序的序列。...map支持下标访问符,即在[]中放入key,就可以找到与key对应的value并且可以修改value。map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。...用红黑树封装set和map先实现RBTree的迭代器迭代器类框架template//依次是T,T&,T*class __RBTreeIterator...和set同时调用红黑树的普通迭代器时,红黑树应该如何区分上层的value是允许被修改是不许被修改呢???...红黑树,红黑树封装map和set的介绍就到这里拉,如果这篇文章对你有帮助的话,请给博主点赞+收藏,感谢看官的大力支持~

83610

红黑树模拟封装map和set

前言: 由于map和set的底层是红黑树实现的,只不过是放入的数据一个是pair类型一个是Key类型,故这里我们利用红黑树这个模版给它简略实例化出map和set。...一·红黑树的修改: 先透露一下这里我们的修改操作其实和hash的封装那里相类似,只不过这里相当于hash的封装相当于更简单一些,比如没有那些细节问题的处理,总的来说就是迭代器这里的操作处理好,然后根据传递的类型对之前写的红黑树的插入查找的数据类型更改一下...二·封装RBtree: 主要完成容器对应的迭代器操作和基本的插入查找操作,后面的封装类似哈希封装成的unordered_map,set类似(本质区别就在于map和set利用红黑树完成的有序操作), 2.1...];其他都一样就是调用红黑树的成员函数就可。...(); return 0; } 结言:此篇讲述封装红黑树过程,其中有大部分处理和哈希的封装相似,上篇已经讲述过了,此篇就不在多言,到此望有助。

6800
  • 用红黑树封装实现map和set

    在源码里面,对于map和set的实现,底层是用同一棵红黑树封装出来的,并不是用了两棵红黑树 那么大家肯定会有疑问了,一棵红黑树这么能两用呢,况且map和set的底层存储的节点类型不一样啊,map是存储的键值对...,set只是存储key 这时设计map和set的大佬就想到了一个极佳的办法,在红黑树底层中用了一个模板参数Value来代表红黑树结点存储对象的类型,这个类型可能是pair键值对,也有可能是key类型。...我们就可以根据value的类型来去确定是map还是set了,但是大家可能会有一点小疑问,既然有了value就可以实现红黑树了,那我们还要关键码key有什么用呢? 这里的关键码key是必不可少的!...因为在红黑树搜索的时候,依靠的还是关键码进行搜索,通过所传关键码和红黑树结点中的关键码的大小关系,确定到红黑树中要搜索的某个结点。 红黑树的find函数的参数类型必须是key!...在实现map和set之前,我们先想一想,上一篇博文的红黑树有哪些地方需要进行改进的?

    7910

    C++:基于红黑树封装map和set

    红黑树的修改 想要用红黑树封装map和set,需要对之前实现的key-value红黑树进行修改,因为map是key-value结构而set是key结构,之前实现的红黑树不能满足需求。...我们需要将key和key-value抽象统一成成一个类型T,需要修改红黑树节点类和红黑树类进行。...2.对于T,代表的是红黑树里存的是key还是key-value。...红黑树的迭代器 红黑树的迭代器是对红黑树节点指针的封装,其实现与list的迭代器类似,但是由于红黑树的遍历走的是中序遍历,所以其迭代器的++走的是当前节点中序遍历的下一个节点,其--也是类似的道理。...的模拟实现 对红黑树进行修改后,只需对其接口函数进行封装和实现KeyOfT仿函数即可。

    6510

    【C++】基于红黑树封装set和map

    前言 前面我们介绍了set和map的底层细节,在上篇文章中也简单实现了红黑树,而我们知道set和map的底层就是依靠红黑树实现的,那么在本文我们将学习如何基于红黑树来封装出set和map。...pair,现在又需要基于红黑树封装出set和map,而我们知道set中存的是K,map中存的是pair,它们数据类型不一样,那我们要拷贝两份红黑树的代码来分别封装set和map吗...我们可以想办法只用一个红黑树封装set和map,像这种使用不同类型在同一套代码中操作的需求,我们很容易就想到了模版。...,红黑树节点类模版参数T是K类型;当用map实例化红黑树类模版时,红黑树节点类模版参数T是pair类型。...二、模版参数 有同学可能注意到了,上面用红黑树封装set和map时传过去了两个参数。一个T类型不是就能确定是K还是pair了嘛,为什么还要传过去一个K呢?

    10010

    初识C++ · 基于红黑树封装map + set

    1 正确认识关系层 本章是基于红黑树封装的map + set,和以往不同的是,我们之前实现链表部分,可以创建了一个迭代器类然后直接进行使用,但是这里不可以,这里的大体的关系是,节点类 -> 迭代器类...-> 红黑树本体 -> map + set。...map + set来说,不应该是key或者是key-value模型吗?我们上文介绍的红黑树就很单纯了,单纯到只能写一种模型,因为我们写死了数据类型只能是pair。...是红黑树本体,此刻展示了部分封装,即map + set是基于红黑树实现的结构,所以在set + map 使用函数的时候,就是使用的红黑树的函数,那么我们想要搞清楚红黑树节点数据类型的原因,就应该看这段typedef...迭代器类只是一个类而已,基于红黑树封装的map + set来说,我们使用的迭代器应该是基于红黑树实现的, 如果莫名使用一个类来当作迭代器,就少了红黑树这层关系,即实例化都实例化不了 为什么两个迭代器的样子都是一样的

    9010

    【C++】红黑树的应用(封装map和set)

    前言 红黑树类的实现参考上一篇文章:【C++】红黑树的全面探索和深度解析-CSDN博客 之前我们已经学习了如何手搓一棵红黑树,现在让我们来对红黑树进行改造,并且封装成map和set....在STL库中,set 和 map 的 key 都是不能修改的,因为要符合二叉搜索树的特性,但是 map 中的 value 又是可以修改的。这个问题需要单独处理。 (5) 红黑树相关接口的改造。...红黑树的改造 改造红黑树以适配map和set容器,主要涉及到如何根据这两种容器的特性来设计和实现红黑树节点的存储以及相应的操作。...Set 和 map的模拟实现 4.1 Set的基本设计 set的底层为红黑树,因此只需在set内部封装一棵红黑树,即可将该容器实现出来。...right); return newRoot; } private: Node* _root = nullptr; public: int _rotateNum = 0; }; 以上就是红黑树的改造及封装

    8610

    C++【一棵红黑树封装 set 和 map】

    ---- 前言 红黑树的基本情况我们已经在上一篇文章中学习过了,本文主要研究的是红黑树的实际应用:封装实现 set 和 map,看看如何通过一棵红黑树满足两个不同的数据结构;在正式封装之前,先要对之前的红黑树进行完善...set 和 map 红黑树的封装实现会涉及部分代码改动 为了进行区分,红黑树的完善代码名为 RBTree - 副本.hpp 存放在 Gitee 仓库中 2.1、解决 k 与 k/v 的参数冲突...,会去调用 红黑树 中相应的函数,所以我们不需要实现 还是那句话:底层的数据结构足够强大,封装的时候就不需要操太多心 对于 set 和 map 都需要的函数,可以在 红黑树 中统一实现,两者分别调用即可...---- 4、完整源码 关于本次完善的红黑树、封装实现 set 和 map 的相关代码在下面这个 Gitee 仓库中 《 封装set和map博客 》 ---- 总结 以上就是本次关于 C++【一棵红黑树封装...set 和 map】的全部内容了,在本文中,我们首先将 红黑树 进行了完善,解决了一些深拷贝问题,新增了迭代器,同时还用反向迭代器适配器适配出了 反向迭代器,当红黑树完善后,我们用同一棵红黑树同时封装实现了

    34530

    【C++深度探索】红黑树实现Set与Map的封装

    前言   前面我们学习过map、set、multimap、multiset的使用,这四种容器都是使用红黑树作为其底层结构。...AVL树更优,而且红黑树实现比较简单,所以实际运用中红黑树更多。   ...今天我们就可以利用之前实现过的红黑树来对C++STL库中的set和map进行模拟实现。 1....修改红黑树   我们之前模拟实现过红黑树,插入的节点是键值对pair类型,而如果要使用红黑树来对set和map封装的话,set存储的应该是单个值,而不是键值对,所以我们就需要对红黑树进行修改,使得set...结语 map和set的底层都是使用一颗红黑树来实现的,然后在外面套了一层壳,为了能够更好的实现代码复用,我们对红黑树进行了很多修改还使用了仿函数,最终用一颗红黑树模拟实现除了map和set。

    9310

    【C++修炼之路】21.红黑树封装map和set

    红黑树封装map和set 前言 一.改良红黑树的数据域结构 1.1 改良后的结点 1.2 改良后的类 二. 封装的set和map 2.1 set.h 2.2 map.h 三....迭代器 3.1 迭代器封装 3.2 const迭代器 四.完整代码实现 4.1 RBTree.h 4.2 set.h 4.3 map.h 4.4 Test.cpp 前言 上一节中,说到了红黑树的实现...,并且已经知道map和set的底层共用了同一套红黑树的结构。...但这样就会出现一个问题,map的数据域和set不一样,比较大小的方式自然也就不一样。因此上一篇中的红黑树还需要做出一些改变才能用来实现map和set。...一.改良红黑树的数据域结构 对于如何设计针对map、set的红黑树结构,看源码的实现无疑是最好的方式: 对于源码的实现,我们知道set是的键值对,但是在使用时却只显示一个k,map是

    33900

    【c++】map和set&&AVL树&&红黑树详解&&模拟实现&&map和set封装

    树的性能 4.1.8 AVl树的模拟实现 4.2 红黑树 4.2.1 红黑树的概念 4.2.2 红黑树的性质 4.2.3 红黑树节点的定义 4.2.4 红黑树结构 4.2.5 红黑树的插入操作 4.2.5.1...树的比较 4.2.9 红黑树的应用 4.2.10 红黑树的模拟实现 4.3 红黑树模拟实现STL中的map与set 4.3.1 红黑树的迭代器 4.3.1.1 begin()与end() 4.3.1.2...,所以实际运用中红黑树更多 4.2.9 红黑树的应用 C++ STL库 -- map/set、mutil_map/mutil_set Java 库 linux内核 其他一些库 4.2.10 红黑树的模拟实现...的模拟实现 map的底层结构就是红黑树,因此在map中直接封装一棵红黑树,然后将其接口包装下即可 Mymap.h #pragma once namespace dc { template封装一棵红黑树,即可将该容器实现出来(具体实现可参考map) Myset.h #pragma once namespace dc { template class

    28610

    【C++从小白到大牛】利用红黑树封装map和set

    前言: 我们已经学过了如何去实现一棵完整的红黑树,而我们所知道的map和set容器的底层都是由红黑树实现的,因此我们今天来学习如何用红黑树来实现封装map和set。...本来我们需要两个红黑树去分别封装map和set,但是代码会有重复、冗余,因此我们采用泛型编程的思想,同一颗红黑树通过传不同的模板参数来分别实现map和set。...就是为了复用同一个类模板的红黑树,让代码变的简洁,体现了泛型编程的思想。 比如这里的模板参数T,如果传的是K类型的,代表使用的是set,如果参数传的是pair类型的就代表是map。...但是在红黑树中,不清楚T类型到底是K还是key-value,但是map和set知道,因此我们可以将这个仿函数定义在我们的map和set里面,进行一个传参。...key) { return _t.Insert(key); } private: RBTree _t; }; 上面便是仿函数的新玩法 红黑树迭代器的实现

    10210

    封装红黑树实现mymap和myset

    set实例化rb_tree时第⼆个模板参数给的是key,map实例化rb_tree时第⼆个模板参数给的是 pair,这样⼀颗红⿊树既可以实现key搜索场景的set,也可以实现key/value搜索场 景的...模拟实现map和set 2.1 实现出复⽤红⿊树的框架,并⽀持insert 参考源码框架,map和set复⽤之前我们实现的红⿊树。...我们这⾥相⽐源码调整⼀下,key参数就⽤K,value参数就⽤V,红⿊树中的数据类型,我们使⽤ T。...树 // 2、封装map和set框架,解决KeyOfT // 3、iterator // 4、const_iterator // 5、key不⽀持修改的问题 // 6、operator[] template...需要注意的是stl源码空,红⿊树增加了⼀个哨兵位头结点 做为end(),这哨兵位头结点和根互为⽗亲,左指向最左结点,右指向最右结点。

    7010

    Map集合、散列表、红黑树介绍

    所以,就先介绍Map集合、散列表和红黑树吧! 看这篇文章之前最好是有点数据结构的基础: Java实现单向链表 栈和队列就是这么简单 二叉树就这么简单 ? ?...红黑树是对2-3查找树的改进,它能用一种统一的方式完成所有变换。 红黑树是一种平衡二叉树,因此它没有3-节点。那红黑树是怎么将3-节点来改进成全都是二叉树呢?...很好理解:红黑树也是平衡树的一种,在插入元素的时候它也得保持树的平衡,那红黑树是以什么的方式来保持树的平衡的呢?...,遵守这些约束的才能叫做红黑树: 红黑树是二叉搜索树。...集合的基础知识,了解Map的常用子类~ 简单介绍了散列表和红黑树,他俩作为Hashxxx和Treexxx的底层,了解其整体思想和相关基础在后续看源码也不至于那么懵~

    84730

    红黑树(一):构建红黑树

    这一篇文章就来看看如何构建红黑树 对于平衡二叉树的构建,可以参考小程序中的文章(C++版)。...平衡二叉树 红黑树 红黑树属于平衡二叉树,但是并非严格意义上的平衡二叉树,因为平衡二叉树要求节点的左右子树高度差不超过1, 而红黑树放弃了这种高度平衡,利用对结点上色的操作来保证树相对平衡,这其中原因大概是维护一个绝对平衡的二叉树代价太大...但如果插入频率小或者只有一次构建,那么平衡二叉树的查询性能还是比红黑树高。...此时红黑树构建平衡分为4种情况: 情况一:红黑树为空树,此时插入结点充当根结点,上色为黑 情况二:插入结点已经存在,此时替换插入结点值即可 情况三:插入结点的位置,其父结点是黑色,此时平衡未打破,插入完成...到这里就构建完成了 相对于构建新增,红黑树的删除情况更为复杂,由于时间关系(这周只有一天休息加上绘图太费劲),留到下一次分享。 构建代码 红黑树构建源码

    1.7K42

    红黑树

    红黑树概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或 Black。...通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。...红黑树的性质 每个结点不是红色就是黑色 根节点是黑色的 如果一个节点是红色的,则它的两个孩子结点是黑色的,树中没有连续的红节点 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点...每个叶子结点都是黑色的(此处的叶子结点指的是空结点) 为什么满足上面的性质,红黑树就能保证:其最长路径中节点个数不会超过最短路径中节点个数的两倍?...插入 红黑树的叔叔是关键 u存在且为红,变色继续向上处理 u不存在或存在且为黑,旋转(单旋+双旋)+变色 情况一:cur为红,parent为红,grandfather为黑(固定),uncle存在且为红

    47720

    红黑树

    ,因此就出现了很多自平衡的二叉查找树,这些自平衡二叉查找树的查询效率都会稳定在O(logN),红黑树就是一种自平衡的二叉查找树。...下面我们会红黑树的特征、插入以及删除来分析红黑树是如何进行自平衡的。...特征 想要了解红黑树如何自平衡,就必须了解红黑树的特征,因为自平衡操作都是围绕这些特征来的,一旦一个红黑树因为插入和删除节点打破了自身的特征,那么他就需要进行自平衡(变色、旋转)来使得二叉树重新满足红黑树的特征...通过上述特征,决定了红黑树的一个重要特性:从根到叶子的最长的可能路径不多于最短路径的两倍长。 下图是一张红黑树示意图: ?...,需要我们细细揣摩,并且反复的研究,在了解红黑树的基本概念以后,我们后续会分析一下HashMap中红黑树的实现以及着手自己实现一个红黑树。

    94320

    红黑树

    前言 红黑树的应用还是比较广泛的。比如Java8的HashMap的底层就用到了红黑树,还有TreeMap和TreeSet也用到了。 下面主要以下几个方面学习一下红黑树。...1)二叉查找树BST 2)红黑树RBTree的规则、增删查 3)红黑树的Java实现。...其中两款具有代表性的平衡树分别为AVL树和红黑树。AVL树由于实现比较复杂,而且插入和删除性能差,在实际环境下的应用不如红黑树。...下图中这棵树,就是一颗典型的红黑树: ? 什么情况下会破坏红黑树的规则,什么情况下不会破坏规则呢?我们举两个简单的栗子: 添加节点 1.向原红黑树插入值为14的新节点: ?...由于父节点15是黑色节点,因此这种情况并不会破坏红黑树的规则,无需做任何调整。 2.向原红黑树插入值为21的新节点: ?

    86031
    领券