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);//返回迭代器,指向新增节点
}