set集合容器使用一种称为红黑树(Red-Black Tree)的平衡二叉检索树的数据结构,来组织泛化的元素数据。每个节点包含一个取值红色或黑色的颜色域,以利于进行树的平衡处理。作为节点键值的元素的插入,必须确保每个子树根节点的键值大于左子树所有节点的键值,而小于右子树所有节点的键值。不会将重复的键值插入容器,也不需指定具体的插入位置,而按元素在树中的关联关系,进行位置检索和插入,元素的删除亦然。 

元素数据的检索,使用的是二叉检索树的中序遍历算法,检索的效率高于vector、deque和 list 等容器。由于采用中序遍历算法可将二叉检索树的键值,由小到大排列遍历出来,因此set集合容器蕴含了元素间的有序性。

1、红黑树的定义

C++ STL的红黑树对标准红黑树略作修改,不要求叶子节点必须是黑色。 

(1)根节点是黑色。 

(2)其他节点是红色或黑色。 

(3)每个红色节点的左、右节点必须是黑色。 

(4)每条从叶子节点到根节点的路径,都包含相同数目的黑色节点。

可见,红黑树使用红黑二色进行“着色”,目的是利用颜色值做二叉树的平衡对称性的检查,只要插入的节点“着色”满足红黑二色的规定,最短路径与最长路径不会相差太远,红黑树的节点分布就能大体上达至平衡。当然,这种平衡是一种有所放宽的平衡。 

由性质(3)可得出,红黑树的任何路径都不会出现两个相邻的红色节点,否则存在一对父子节点都是红色。 

由性质(4),可设从根节点到叶节点路径上的黑色节点数均为n,于是,红黑树的最短路径为全黑的“黑→黑→…→黑”路径,即最短路径长度为n?1(相邻节点间的距离为1)。而最长路径只能取为红黑交替的“黑→红→黑→红→…→黑”路径,这样可使黑色节点数最多,即最长路径为2(n?1)。所以在红黑树的所有从根节点到叶子节点的路径中,最长路径不会超过最短路径的2倍。

2、结构

将一组整数21、30、10、8、37、46、29、5、16、19、15和32依次插入生成一个红黑树。如图所示,先构造一个黑色节点21作为根,由于30>21,因此30作为21的右节点插入,10<21,10作为21的左节点插入。

log2n(n为元素个数)。

3、说明

红黑树的插入和删除都要涉及类似平衡二叉树如何进行平衡问题。关于平衡二叉树,我们可以参见:

http://blog.163.com/zhoumhan_0351/blog/static/399542272009104113331705

关于红黑树调整代码,可以参见SGI的stl_tree文件中。附中有一部分关键的。

二、应用

1、创建

(1)set()用默认的less函数对象和内存分配器,创建一个没有任何数据元素的set对象。

set<int> s;//创建了空的set对象s ,元素类型为整型int。

(2)set(const key_compare& comp) 

指定一个比较函数对象comp来创建set对象,内存分配器为默认值。

//定义字符串比较函数对象strLess 

struct strLess{ 

bool operator()(const char* s1, const char* s2) const 

{ return strcmp(s1, s2) < 0;}

};

//创建set容器对象s 

set<const char*, strLess> s(strLess());//使用自定义的函数对象strLess,创建一个set容器对象s

(3)set(const set&) 

set拷贝构造函数,通过红黑树的拷贝构造函数,实现两个set容器的元素、头节点和节点个数的拷贝。

//set<int> s1; 

set<int> s2(s1);//利用set容器对象s1,拷贝生成set容器对象s2。 

(4)set(InputIterator first, InputIterator last)

用迭代器区间[first,last)所指的元素,创建一个set对象。

int iArray[] = { 13, 32, 19 }; 

set<int> s(iArray, iArray +3);//将数组iArray的元素插入到set容器对象s的红黑树中。 

(5)set(InputIterator first, InputIterator last, const key_compare& comp) 

用迭代器区间[first,  last)所指的元素和 comp 函数对象,创建一个 set 对象。

const char* szArray[] = { "hello", "dog", "bird" }; 

set<const char*, strLess> s(szArray, szArray +3 , strLess());//用上面定义的strLess函数对象和数组szArray,创建set对象s

2、插入

(1)pair<iterator, bool> insert(const value_type& v) 

将元素v插入set容器,要求v值不与set容器的任何元素重复,否则插入失败。返回一个pair配对对象,提供所插入元素的迭代器位置和true/false插入成功标志。 

(2)iterator insert(iterator position, const value_type& v) 

将元素v插入set容器,参数position只是提示可在position位置之前插入v,所返回的插入位置视实际情况而定,不一定能在position位置前插入。 

(3)void insert(InputIterator first, InputIterator last) 

将某迭代器区间[first,last)所指的数据作为元素,插入到set容器。

3、访问

(1)iterator begin()//通过迭代器的“++”进行中序遍历

(2)iterator end() 

及反向迭找器

4、寻找

const_iterator find(const Key& key) const;

5、其它

其它函数,如删除erase,empty,size,swap,等,基本用法同其它的容器,可参考相关的C++文档,如MSDN。