set,map和multiset,multimap的不同在于insert函数时调用底层红黑树不同的insert函数。
/*插入节点:节点键值不允许重复,若重复则插入无效 返回值是个pair,第一元素是个 rb_tree 迭代器,指向新增节点*/ templatepair ::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 迭代器,指向新增节点*/ templaterb_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为新增节点的键值*/ templaterb_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);//返回迭代器,指向新增节点 }