《STL源码剖析》 RB_tree insert_uniuqe()函数解析

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);

    直接返回

猜你喜欢

转载自blog.csdn.net/zhc_futrue/article/details/81222806