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 != ) { // 從根節點開始,往下尋找適當的安插點
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()的更多相关文章
- stl_tree.h
stl_tree.h G++ ,cygnus\cygwin-b20\include\g++\stl_tree.h 完整列表 /* * * Copyright (c) 1996,1997 * Silic ...
- stl_set.h
stl_set.h // Filename: stl_set.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: http://blo ...
- stl_map.h
stl_map.h // Filename: stl_map.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: http://blo ...
- stl_multiset.h
stl_multiset.h // Filename: stl_multiset.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: ...
- stl_multimap.h
stl_multimap.h // Filename: stl_multimap.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: ...
- STL中_Rb_tree的探索
我们知道STL中我们常用的set与multiset和map与multimap都是基于红黑树.本文介绍了它们的在STL中的底层数据结构_Rb_tree的直接用法与部分函数.难点主要是_Rb_tree的各 ...
- map vs hash_map
1. map, multimap, set, multiset g++ 中 map, multimap, set, multiset 由红黑树实现 map: bits/stl_map.h multim ...
- C++ string::size_type 类型【转】
int main() { string str("Hello World!\n"); cout << "The size of " << ...
- 关于size_t与size_type
整理自关于size_t与size_type 问题起源于这样一段代码: #include <algorithm> #include <stdio.h> int main() { ...
随机推荐
- bzoj 1024 [SCOI2009]生日快乐——模拟
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1024 可以枚举这边放多少块.那边放多少块. 注意精度.不要每次用x*y/base算有多少块, ...
- java 3类的继承
模板类 泛型程序设计方法 类的组合 类的继承 java只有单继承 隐藏和覆盖 用super.x调用 访问静态属性 静态属性不继承 静态成员只有一个,不会有副本 静态成员只有一个所有的超类和子类 方法的 ...
- check constraints
SELECT constraint_name, constraint_type, column_name, STATUSfrom user_constraints natural join user_ ...
- 使用淘宝镜像cnpm安装Vue.js
简介: Vue.js是前端一个比较火的MVVM框架, 是一套构建用户界面的渐进式框架. Vue 只关注视图层, 采用自底向上增量开发的设计. Vue 的目标是通过尽可能简单的 API 实现响应的数据绑 ...
- PHP核心编程--目录操作(包含文件操作)
一.目录操作 1. 创建目录 创建目录mkdir(目录名称) //返回值为布尔 一次性创建主目录及其子目录 判断是不是一个目录is_dir //返回true,false 判断目录或文件是否存 ...
- RGBA(0,0,0,0)调色
前三个值(红绿蓝)的范围为0到255之间的整数或者0%到100%之间的百分数.这些值描述了红绿蓝三原色在预期色彩中的量. 第四个值,alpha值,制定了色彩的透明度/不透明度,它的范围为0.0到1.0 ...
- Ecplise中Junit4单元测试的基本用法
看了一些Junit4的视频,简单了解了Junit4的一些基本用法,整理记录一下. 环境搭建 这里使用的开发工具是MyEclipse,首先新建一个Java工程,将Junit4的jar包引入,eclips ...
- jq 添加内容
向页面动态添加内容,一般用于动态网页,需要即时请求数据,并更新在页面上,使用append()更多一些,empty() - 清空所有子元素,remove() - 清除自身所有子元素. append() ...
- BZOJ1878 洛谷1972 HH的项链题解
洛谷链接 BZOJ链接 看到这样不用修改的题目,应该佷容易就联想到了离线来处理. 我们发现若将询问按照r来排序,排完后每次对答案有贡献的仅是每个颜色最后出现的位置 我们用next[i]表示i处颜色之前 ...
- VirtualBox使用随笔
1.virtualbox配置Android手机USB热点 host:Windows10;guest:windows XP/10 右击我的电脑 - 管理 - 设备管理器 - 网卡适配器,若手机正确vb连 ...