SGI STL中set/map底層都是通過RB-tree實現的。
首先看看RB-tree結點的定義

1 typedef bool __rb_tree_color_type; 2 const __rb_tree_color_type __rb_tree_red = false; 3 const __rb_tree_color_type __rb_tree_black = true; 4 5 // 結點的基類 6 struct __rb_tree_node_base 7 { 8 typedef __rb_tree_color_type color_type; 9 typedef __rb_tree_node_base* base_ptr; 10 11 // 關鍵的4個域 12 color_type color; 13 base_ptr parent; 14 base_ptr left; 15 base_ptr right; 16 17 // 返回極值 18 static base_ptr minimum(base_ptr x) 19 { 20 while (x->left != 0) x = x->left; 21 return x; 22 } 23 24 static base_ptr maximum(base_ptr x) 25 { 26 while (x->right != 0) x = x->right; 27 return x; 28 } 29 } 30 31 // 多了一個value域 32 template <class Value> 33 struct __rb_tree_node : public __rb_tree_node_base 34 { 35 typedef __rb_tree_node<Value>* link_type; 36 Value value_field; 37 };
下圖是RB-tree結點跟其迭代器的關系
重點看看__rb_tree_iterator的operator++跟operator--,
實際是調用__rb_tree_base_iterator的increment跟decrement。
可以看出迭代器前移/后移的時候會按key的順序找到下一個/上一個結點。
(set/map<...>::begin()會返回RB-tree中key最小的結點,因此使用operator++遍歷會按key的順序從小到大遍歷結點)

1 void increment() 2 { 3 if (node->right != 0) { 4 node = node->right; 5 while (node->left != 0) 6 node = node->left; 7 } 8 else { 9 base_ptr y = node->parent; 10 while (node == y->right) { 11 node = y; 12 y = y->parent; 13 } 14 if (node->right != y) 15 node = y; 16 } 17 } 18 19 void decrement() 20 { 21 if (node->color == __rb_tree_red && 22 node->parent->parent == node) 23 node = node->right; 24 else if (node->left != 0) { 25 base_ptr y = node->left; 26 while (y->right != 0) 27 y = y->right; 28 node = y; 29 } 30 else { 31 base_ptr y = node->parent; 32 while (node == y->left) { 33 node = y; 34 y = y->parent; 35 } 36 node = y; 37 } 38 }
SGI STL中的rb_tree用了一個小trick,就是使用了一個header結點,用來代表整個rb_tree。
該結點與root結點互為父結點,該結點的left指向最左(key最小)的結點,right指向最右(key最大)的結點。
除此之外,該rb_tree的實現跟普通的紅黑樹類似,詳情可以查看:http://www.cnblogs.com/runnyu/p/4679279.html。

1 template <class Key, class Value, class KeyOfValue, class Compare, 2 class Alloc = alloc> 3 class rb_tree { 4 // rb_tree的基本定義 5 protected: 6 typedef __rb_tree_node_base* base_ptr; 7 typedef __rb_tree_node<Value> rb_tree_node; 8 typedef simple_alloc<rb_tree_node, Alloc> rb_tree_node_allocator; 9 public: 10 typedef Key key_type; 11 typedef Value value_type; 12 typedef value_type* pointer; 13 typedef value_type& reference; 14 typedef rb_tree_node* link_type; 15 typedef size_t size_type; 16 typedef ptrdiff_t difference_type; 17 18 typedef __rb_tree_iterator<value_type, reference, pointer> iterator; 19 20 link_type header; 21 // ... 22 23 // 主要接口 24 iterator begin() { return leftmost(); } // 返回最左邊的結點(最小key) 25 iterator end() { return header; } 26 27 iterator insert_equal(const value_type& x); // 插入元素 並允許鍵值相同 28 pair<iterator,bool> insert_unique(const value_type& x); // 插入元素 鍵值是獨一無二的 29 30 };
set/multiset
有了rb_tree,set/multiset的實現也只是調用rb_tree的接口而已。
其中set跟multiset不一樣的是,set插入的時候調用的是insert_unique(),而multiset調用的是insert_equal()。
下面是給出set的基本定義:

1 template <class Key, class Compare = less<Key>, class Alloc = alloc> 2 class set { 3 public: 4 typedef Key key_type; 5 typedef Key value_type; // 使用的value類型跟key一樣 6 typedef Compare key_compare; 7 typedef Compare value_compare; 8 private: 9 typedef rb_tree<key_type, value_type, 10 identity<value_type>, key_compare, Alloc> rep_type; 11 rep_type t; 12 public: 13 // 接口的實現只是對rb_tree的封裝 不一一列舉了 14 iterator begin() const { return t.begin(); } 15 iterator end() const { return t.end(); } 16 pair<iterator,bool> insert(const value_type& x) { 17 pair<typename rep_type::iterator, bool> p = t.insert_unique(x); 18 return pair<iterator, bool>(p.first, p.second); 19 } 20 // ... 21 };
map/multimap
map/mulitmap的實現也是通過調用rb_tree的接口。
map/mulitmap不一樣的是,map插入的時候調用的是insert_unique(),而multimap調用的是insert_equal()。
下面是給出map的基本定義:

1 template <class Key, class T, class Compare = less<Key>, class Alloc 2 class map { 3 public: 4 typedef Key key_type; 5 typedef T data_type; 6 typedef T mapped_type; 7 typedef pair<const Key, T> value_type; // 在rb_tree中value的類型是pair 8 typedef Compare key_compare; 9 private: 10 // select1st直接return T.first 用於rb_tree取到key進行比較大小 11 typedef rb_tree<key_type, value_type, 12 select1st<value_type>, key_compare, Alloc> rep_type; 13 rep_type t; 14 // ... 15 16 // 接口只是對rb_tree的封裝 就不一一列舉了 17 iterator begin() { return t.begin(); } 18 iterator end() { return t.end(); } 19 pair<iterator,bool> insert(const value_type& x) { return t.insert_unique(x); } 20 // ... 21 }
另外STL中有未列入標准的hash_set/hash_map以及C++11中的unordered_set/map,底層是使用hashtable實現的。
相比於用rb_tree實現的set/map,它們的插入刪除查找操作具有O(1)的時間復雜度(沒有沖突情況下),但是它們的元素的順序是無序的。