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);
}
以上代码基本上是copy 《STL源码剖析》书籍的224页的代码,只是添加了一行注释, 对于 --j 的注释:
--j 的作用是 找到 (小于或等于当前节点的最大的那个节点)
这段代码的逻辑是:
- 首先查看插入的新值是否是所有值中最小的,如果是,就插入,对应代码:
if (comp) // 如果离开 while 循环时 comp 为真,(表示遇到“大”,将插入于左侧)
if (j == begin()) // 如果插入点的父节点为最左节点
return pair<iterator, bool>(__insert(x, y, v), true);
- 其次,如果插入的新值不是所有值中最小的,就 --j ,找到小于或等于当前节点的最大的那个节点,然后判断找到的节点的键值是否小于 欲插入节点 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);
直接返回