stl_tree.h/insert_unique()

// 安插新值;節點鍵值不允許重複,若重複則安插無效。
// 注意,傳回值是個pair,第一元素是個 RB-tree 迭代器,指向新增節點,
// 第二元素表示安插成功與否。
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
pair<typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator, bool>
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_unique(const Value& v)
{
  link_type y = header;
  link_type x = root(); // 從根節點開始
  bool comp = true;
  while (x != 0) {      // 從根節點開始,往下尋找適當的安插點
    y = x;
    comp = key_compare(KeyOfValue()(v), key(x)); // v 鍵值小於目前節點之鍵值?
    x = comp ? left(x) : right(x);  // 遇「大」則往左,遇「小於或等於」則往右
  }
  // 離開 while 迴圈之後,y 所指即安插點之父節點(此時的它必為葉節點)

  iterator j = iterator(y);   // 令迭代器j指向安插點之父節點 y
  if (comp) // 如果離開 while 迴圈時 comp 為真(表示遇「大」,將安插於左側)
    if (j == begin())   // 如果安插點之父節點為最左節點
      return pair<iterator,bool>(__insert(x, y, v), true);
      // 以上,x 為安插點,y 為安插點之父節點,v 為新值。
    else    // 否則(安插點之父節點不為最左節點)
      --j;  // 調整 j,回頭準備測試...
  if (key_compare(key(j.node), KeyOfValue()(v)))
    // 小於新值(表示遇「小」,將安插於右側)
    return pair<iterator,bool>(__insert(x, y, v), true);

  // 進行至此,表示新值一定與樹中鍵值重複,那麼就不該插入新值。
  return pair<iterator,bool>(j, false);
}

以上iterator j的作用为:若待插入的key与某个结点相同(设为p),则在while循环中,某一次x = p后,大于等于向右走,则下一次x =
p.right,由于v的值一定小于p的右子树中任何一个值,所以进入p的右子树后,x一定是一直向左走直到节点y(y的左儿子为空)。则y为p的右子树最小值,iterator(p)
= iterator(y) - 1,p即为代码中的j。若v与j的值不同,则可以执行插入操作,否则返回j和false。

http://blog.csdn.net/ww32zz/article/details/48523759

comp == true 时,如果 j != begin() 则 --j,此时 j 指向 y 的前一个节点,这个节点可能和新插入的节点 v 的值相同,也就是上面说的 p,所以需要再比较 p 和 v

comp == false 时,y 的 right 为 0,v >= y , 如果 y 是最后一个节点,即 end() - 1,再判断是否 y < v;如果 y 不是最后一个节点,y的后一个节点是 y 的父节点或更上层的节点,

而且 y 在 y后一节点的 left tree 中,v 一定小于 y的后一个节点,否则不会到达 y。所以程序中没有判断 y 是否是最后一个节点。

这里两种情况的不对称根源于比较函数 < 和 >= 的不对称。

时间: 2024-11-08 17:35:17

stl_tree.h/insert_unique()的相关文章

《STL源码剖析》---stl_tree.h阅读笔记

STL中,关联式容器的内部结构是一颗平衡二叉树,以便获得良好的搜索效率.红黑树是平衡二叉树的一种,它不像AVL树那样要求绝对平衡,降低了对旋转的要求,但是其性能并没有下降很多,它的搜索.插入.删除都能以O(nlogn)时间完成.平衡可以在一次或者两次旋转解决,是"性价比"很高的平衡二叉树. RB-tree(red black tree)红黑树是平衡二叉树.它满足一下规则 (1)每个节点不是红色就是黑色. (2)根节点是黑色. (3)如果节点为红色,则其子节点比为黑色. (4)任何一个节

stl_tree.h

stl_tree.h G++ 2.91.57,cygnus\cygwin-b20\include\g++\stl_tree.h 完整列表 /* * * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpo

STL源码剖析 容器 stl_tree.h

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie RB-tree(红黑树) -------------------------------------------------------------------------- 平衡二叉搜索树 --> 平衡可提高搜索效率 常见的平衡二叉搜索树有: AVL-tree(任何节点的左右子树高度相差最多 1).红黑树.AA-tree AVL-tree 破坏平衡的情况及恢复平衡的方法 恢复时要先找到失

stl_map.h

stl_map.h // Filename: stl_map.h // Comment By: 凝霜 // E-mail: [email protected] // Blog: http://blog.csdn.net/mdl13412 /* * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this software * and it

stl_multiset.h

stl_multiset.h // Filename: stl_multiset.h // Comment By: 凝霜 // E-mail: [email protected] // Blog: http://blog.csdn.net/mdl13412 /* * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this softwar

C++ STL源码学习(之RB Tree篇)

stl_tree.h 这是整个STL中最复杂的数据结构,也是我接触到的最复杂的数据结构之一 /** Red-black tree class, designed for use in implementing STL associative containers (set, multiset, map, and multimap). The insertion and deletion algorithms are based on those in Cormen, Leiserson, and

STL中_Rb_tree的探索

我们知道STL中我们常用的set与multiset和map与multimap都是基于红黑树.本文介绍了它们的在STL中的底层数据结构_Rb_tree的直接用法与部分函数.难点主要是_Rb_tree的各个参数的确定. 特别注意在如下代码的Selector类用于从Node中选出用于排序的key值,这个仿函数必须返回const int&而不能是int,否则less<int>::operator(const int&, const int&)会抛出segmentation fa

《coredump问题原理探究》Linux x86版7.5节 Map对象

先看一个例子: 1 #include <map> 2 3 int main() 4 { 5 std::map<int,int> iMap; 6 7 iMap[5] = 6; 8 iMap[8] = 20; 9 iMap[2] = 80; 10 11 return 0; 12 } 看一下汇编: (gdb) disassemble main Dump of assembler code for function main: 0x080486e4 <+0>: push %eb

基于内存查看STL常用容器内容

有时候在线上使用gdb调试程序core问题时,可能没有符号文件,拿到的仅是一个内存地址,如果这个指向的是一个STL对象,那么如何查看这个对象的内容呢? 只需要知道STL各个容器的数据结构实现,就可以查看其内容.本文描述了SGI STL实现中常用容器的数据结构,以及如何在gdb中查看其内容. string string,即basic_string bits/basic_string.h: mutable _Alloc_hider _M_dataplus; ... const _CharT* c_s