// 安插新值;節點鍵值不允許重複,若重複則安插無效。
// 注意,傳回值是個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 != ) { // 從根節點開始,往下尋找適當的安插點
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 是否是最后一个节点。

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

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

  1. stl_tree.h

    stl_tree.h G++ ,cygnus\cygwin-b20\include\g++\stl_tree.h 完整列表 /* * * Copyright (c) 1996,1997 * Silic ...

  2. stl_set.h

    stl_set.h // Filename: stl_set.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: http://blo ...

  3. stl_map.h

    stl_map.h // Filename: stl_map.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: http://blo ...

  4. stl_multiset.h

    stl_multiset.h // Filename: stl_multiset.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: ...

  5. stl_multimap.h

    stl_multimap.h // Filename: stl_multimap.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: ...

  6. STL中_Rb_tree的探索

    我们知道STL中我们常用的set与multiset和map与multimap都是基于红黑树.本文介绍了它们的在STL中的底层数据结构_Rb_tree的直接用法与部分函数.难点主要是_Rb_tree的各 ...

  7. map vs hash_map

    1. map, multimap, set, multiset g++ 中 map, multimap, set, multiset 由红黑树实现 map: bits/stl_map.h multim ...

  8. C++ string::size_type 类型【转】

    int main() { string str("Hello World!\n"); cout << "The size of " << ...

  9. 关于size_t与size_type

    整理自关于size_t与size_type 问题起源于这样一段代码: #include <algorithm> #include <stdio.h> int main() { ...

随机推荐

  1. 当spark遇见hbase

    一.使用sbt引入hbase依赖包 "org.apache.hbase" % "hbase-server" % "2.1.0", " ...

  2. win10 请求操作需要提升解决方案

    记录一下: win10   系统管理员 打开后缀为  .xxx 的文件时, 系统提示: 请求操作需要提升 网上搜索了一下,原因是权限不够,故系统提示. 给当前用户加入了 管理员权限,各种权限都无效. ...

  3. 三、Redis操作

    一.基本介绍 1.简介 Redis是由意大利人Salvatore Sanfilippo(网名:antirez)开发的一款内存高速缓存数据库.Redis全称为:Remote Dictionary Ser ...

  4. OpenCV灰度化图像

    OpenCV2版本号非常多函数发生了变化.比如二值化,其演示样例: void CmyMFC2Dlg::OnBnClickedButton1() { // TODO: Add your control ...

  5. qt,pro文件中用于平台区分的写法

    qt,pro文件中用于平台区分的写法 切记: 大括号和平台需要在同一行中,否则会失效 unix { TARGET = appname } macx { TARGET = appname2 } win3 ...

  6. linux类库之log4j-LogBack-slf4j-commons-logging

    log4j http://commons.apache.org/proper/commons-logging/ http://logging.apache.org/log4j/2.x/ The Com ...

  7. Spark day02

    Standalone模式两种提交任务方式 Standalone-client提交任务方式 提交命令 ./spark-submit --master spark://node1:7077 --class ...

  8. oracle怎么捕获表上的DML语句(不包括select)语句)

    可以采用dml触发器,如 CREATE OR REPLACE TRIGGER tr_capt_sql BEFORE DELETE OR INSERT OR UPDATE ON manager.test ...

  9. 【风马一族_软件】微软卸载工具_msicuu2.exe

    msicuu2.exe是微软的Windows Installer清理工具,可以用来清理微软安装包软件产生的垃圾,当然也可以拿来作为修复相关软件的卸载准备使用 下载链接:http://files.cnb ...

  10. javaweb学习总结(一) - - JSP取得绝对路径

    在JavaWeb开发中,常使用绝对路径的方式来引入JavaScript和CSS文件,这样可以避免因为目录变动导致引入文件找不到的情况,常用的做法如下: 例如: 1 <!--使用绝对路径的方式引入 ...