STL之set,map,multiset,multimap

set,map和multiset,multimap的不同在于insert函数时调用底层红黑树不同的insert函数。

/*插入节点:节点键值不允许重复,若重复则插入无效
返回值是个pair,第一元素是个 rb_tree 迭代器,指向新增节点*/
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
pair<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;//y为根节点的父节点
	link_type x = root();//x为根节点
	bool comp = true;
	while (x != 0)//从根节点开始,往下寻找适当的插入点
	{
		//二叉查找树特性插入
		y = x;
		comp = key_compare(KeyOfValue()(v), key(x));//比较新增值v 和x节点的键值
		x = comp ? left(x) : right(x);//v遇"大"则往左,遇"小或等于"往右
	}//while内单次每次运行结束,y总为x的父节点
	
	iterator j = iterator(y);//此时y节点必为叶子节点
	if (comp)//v小于比较值,将插入左侧
	{	
		if (j == begin())//begin()实际就是header->left,也就是树的最左节点
			return pair<iterator, bool>(__insert(x, y, v), true);//转入实际插入函数__insert()
		else//如果插入点之父节点不为最左节点
			--j;//调整j,--重载,调用decrement(),即找到比当前节点小的最大节点
		//与此同时还有++重载,调用increment(),找到比当前节点大的最小节点
	}
	if (key_compare(key(j.node), KeyOfValue()(v)))//遇"小"将插入右侧(v值大)
		return pair<iterator, bool>(__insert(x, y, v), true);
	/*以上,x为新插入点位置,y为插入点之父节点,v为键值*/

	return pair<iterator, bool>(j, false);//存在重复键值就不插入
}
/*插入节点:节点键值允许重复
返回值是一个 rb_tree 迭代器,指向新增节点*/
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_equal(const Value& v)
{
	link_type y = header;//y为根节点的父节点
	link_type x = root(); //x为根节点
	while (x != 0)//从根节点开始,往下寻找适当的插入点
	{
		y = x;
		//直接找到合适位置,无需考虑键值是否重复
		x = key_compare(KeyOfValue()(v), key(x)) ? left(x) : right(x);
	}
	return __insert(x, y, v);
}
/*x为新增节点位置,y为新增节点的父节点,v为新增节点的键值*/
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::
__insert(base_ptr x_, base_ptr y_, const Value& v) {
	link_type x = (link_type)x_;
	link_type y = (link_type)y_;
	link_type z;

	if (y == header || x != 0 || key_compare(KeyOfValue()(v), key(y)))
	{
		z = create_node(v);//为新节点配置空间
		left(y) = z;                // also makes leftmost() = z when y == header
		if (y == header)//如果y为头节点,也就是空树第一次插入节点
		{
			root() = z;//z为根节点,与header节点互为父节点
			rightmost() = z;//树的最大节点
		}
		else if (y == leftmost())//如果y为最左节点
			leftmost() = z;//修正最小节点
	}
	else//上面三种全不满足,即插入键值大于插入点的父节点,右侧插入
	{
		z = create_node(v);
		right(y) = z;//使新节点成为插入点的父节点y的右子结点
		if (y == rightmost())
			rightmost() = z;          // maintain rightmost() pointing to max node
	}
	//设置新增节点z的关系
	parent(z) = y;
	left(z) = 0;
	right(z) = 0;
	//平衡红黑树
	__rb_tree_rebalance(z, header->parent);

	++node_count;//节点数累加
	return iterator(z);//返回迭代器,指向新增节点
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值