zoukankan      html  css  js  c++  java
  • 15、Linux内核中用到的红黑树、STL标准库map用到的红黑树两者的区别

    区别:Linux内核中用到的红黑树是可以存储同样的key的,但是STL标准库map中用到的红黑树不能存储相同的key,原因是map对原有的红黑树做了修改。

    1.原有的红黑树结构是可以插入相同的key

     例如以下是截取的nginx 的红⿊树的实现,nginx 的红⿊树的实现和Linux内核中红黑树的实现相似。

    // 这个是截取 nginx 的红⿊树的实现,这段代码是 insert 操作中的⼀部分,只是为了(1)找到节点的位置,(2)改变为红色,执⾏完这个函数还需要检测插⼊节点后是否平衡(主要是看他的⽗节点是否也是红⾊节点)
    // 调⽤ ngx_rbtree_insert_value 时,temp传的参数为 红⿊树的根节点,node传的参数为待插⼊的节点
    void ngx_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,ngx_rbtree_node_t *sentinel)
    {
        ngx_rbtree_node_t **p;
        for (;;) {
            p = (node->key < temp->key) ? &temp->left : &temp->right;// 这⾏很重要
            if (*p == sentinel) {
                break;
            }
            temp = *p;
        }
        *p = node;
        node->parent = temp;
        node->left = sentinel;
        node->right = sentinel;
        ngx_rbt_red(node);
    }  

          

     按照以上的带啊,如果要往上面这个红黑树上面再插入key=123时,此时 node->key =123, 我们来看这段代码

    p = (node->key < temp->key) ? &temp->left : &temp->right;

    当要插入的节点123和根节点345比较,往左走,然后和123比较,此时要插入的节点和123相同,按照                                                                                        (node->key < temp->key) ? &temp->left : &temp->right  这行代码的话,它会往右走,然后再和234比较,比234小,所以它会插入到234的左节点上,此时红黑树上面有2个key为123的节点,如下图:

            

    2.map中的红黑树不能插入相同的key

      

       map<int, int> tep;
        tep.insert(make_pair<int,int>(1,20));
        tep.insert(make_pair<int, int>(2, 21));
        tep.insert(make_pair<int, int>(1, 22));
    
        for (auto temp : tep)
        {
            cout << temp.second << endl;
        }

    以上代码输出结构为20,21 ,那就说明当map发现再次插入的和之前的冲突时,直接会抛弃。map红黑树似于以下的代码

    // 不插⼊相同节点 如果插⼊相同 让它变成修改操作 此时 红⿊树当中就不会有相同的key了定时器 key 时间戳
    void ngx_rbtree_insert_value_ex(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,ngx_rbtree_node_t *sentinel)
    {
        ngx_rbtree_node_t **p;
        for (;;) {
            // {-------------add-------------
            if (node->key == temp->key) {
                temp->value = node->value;
                return;
            }
            // }-------------add-------------
            p = (node->key < temp->key) ? &temp->left : &temp->right;// 这⾏很重要
            if (*p == sentinel) {
                break;
            }
            temp = *p;
        }
        *p = node;
        node->parent = temp;
        node->left = sentinel;
        node->right = sentinel;
        ngx_rbt_red(node);
    }

    较之前的代码多了这个判断

    //如果要插入的节点和之前的节点相同,则直接return掉,不插入
    if
    (node->key == temp->key) { temp->value = node->value; return; }

     

  • 相关阅读:
    创建型设计模式之-单例
    设计模式(1、创造型2、结构型、3行为型)
    手写IOC容器和两种注入(构造方法注入和属性注入)
    从依赖倒置原则到IOC控制反转
    自定义HttpHandler可以做什么
    一个用户在浏览器上输入网址怎么走到我们写的.net程序中的,请求到管道处理
    代理Nginx
    .Net Expression表达式目录树(自己动态创建表达式目录树)
    canvas绘制圆环进度条
    城市二级联动
  • 原文地址:https://www.cnblogs.com/zwj-199306231519/p/14323147.html
Copyright © 2011-2022 走看看