频道栏目
首页 > 资讯 > 其他 > 正文

STL之set,map,multiset,multimap

18-04-18        来源:[db:作者]  
收藏   我要投稿

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

/*插入节点:节点键值不允许重复,若重复则插入无效
返回值是个pair,第一元素是个 rb_tree 迭代器,指向新增节点*/
template 
pair<>::iterator, bool>
rb_tree::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(__insert(x, y, v), true);//转入实际插入函数__insert()
		else//如果插入点之父节点不为最左节点
			--j;//调整j,--重载,调用decrement(),即找到比当前节点小的最大节点
		//与此同时还有++重载,调用increment(),找到比当前节点大的最小节点
	}
	if (key_compare(key(j.node), KeyOfValue()(v)))//遇"小"将插入右侧(v值大)
		return pair(__insert(x, y, v), true);
	/*以上,x为新插入点位置,y为插入点之父节点,v为键值*/

	return pair(j, false);//存在重复键值就不插入
}
/*插入节点:节点键值允许重复
返回值是一个 rb_tree 迭代器,指向新增节点*/
template 
rb_tree::iterator
rb_tree::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 
rb_tree::iterator
rb_tree::
__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);//返回迭代器,指向新增节点
}
相关TAG标签
上一篇:怎么使用单臂路由实现原来相互隔离的不同VLAN之间的互通?
下一篇:telnet远程登陆路由器:实现pc0和pc1能telnet远程登陆到R1并对路由器进行配置
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站