C++ STL(第十四篇:Set 和 Map)

1、Set

set 的特性是,所有元素都會根據元素的鍵值自動被排序。set 的元素不像 map 那樣可以同時擁有實值(value)和鍵值(key),set 元素的鍵值就是實值,實值就是鍵值。 set 不允許兩個元素有相同的鍵值

因爲 set 元素值就是其鍵值,關係到 set 元素的排列規則,如果任意改變 set 元素值,會嚴重破壞 set 組織。所以 set 的迭代器是 const_iterator,杜絕寫入操作

set 擁有與 list 相同的某些性質:當客戶端對它進行元素新增操作或刪除操作時,操作之前的所有迭代器,在操作之後都依然有效。當然,被刪除的那個元素的迭代器必然是個例外。

由於 RB-tree 是一種平衡二叉搜索樹,自動排序的效果很不錯,所以標準 STL set 即以 RB-tree 爲底層機制。又由於 set 所開放的各種操作接口, RB-tree 也都提供了,所以幾乎所有的 set 操作行爲,都只是轉調用 RB-tree 的操作行爲而已。大概的代碼如下:

template<class Key, class Compare = less<Key>, class Alloc = alloc>
class set
{
public:
	typedef Key key_type;
	typedef Key value_type;
	typedef Compare key_compare;	// key 的比較函數
	typedef Compare value_compare;	// value 的比較函數
	typedef rb_tree<......> rep_type;
	typedef typename rep_type::const_pointer pointer;  //一堆跟萃取有關的類型,都是 const 的
	......	
	rep_type t;						// 底層採用紅黑樹來表現 set
	
public:
	set();		//一系列重載函數
	
	iterator begin() const { return t.begin(); }
	iterator end() const { return t.end(); }
	bool empty() const { return t.empty(): }
	size_type size() const { return t.size(); }
	
	xxx insert( ... )  { return t.xxxx(); }
	xxx erase(...) { return t.xxxx(); } 
};

2、Map

map 特性是,所有元素都會根據元素的鍵值自動被排序。map 的所有元素都是pair,同時擁有實值(value)和鍵值(key)。pair的第一個元素被視爲鍵值,第二元素被視爲實值。map不允許兩個元素擁有相同的鍵值。

template<class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;

T1 first;
T2 second;

pair() : first(T1()), second(T2()) {}
pair(const T1& a, const T2& b) : first(a), second(b){}
};

我們不能更改 map 的鍵值,因爲鍵值關係到 map 的排序規則。但是我們可以修改元素的實值,因爲實值並不影響 map 元素的排列規則

和 set 一樣 map 底層也使用的是 RB-tree 來實現的。只是比較元素大小時,map 比較的是 pair 的第一個元素。大概代碼如下:

template<......>
class map
{
public:
	typedef Key key_type;		//鍵值類型
	typedef T data_type;		//實值類型
	typedef T mapped_type;
	
	typedef pair<const Key, T> value_type;	//元素型別
	typedef Compare key_compare;			//鍵值比較函數
	Compare comp;
	
public:
	//比較時,使用pair 的第一個元素
	bool operator()( const value_type& x, const value_type& y ) const 
	{
		return comp( x.first, y.first);
 	}
 	
private:
	typedef rb_tree<key_type, value_type, select1st<value_type>, key_compare, Alloc> rep_type;
	rep_type t;		//以紅黑樹作爲 底層,表現map
	
	//剩下的函數跟 set 基本是一樣的
};

3、multiset 和 multimap

multiset 特性以及用法和 set 完全相同,唯一的差別在於它允許鍵值重複,因此它的插入操作採用的是底層機制 RB-tree 的 insert_equal() 而非 insert_unique()。

而multimap 和 map 完全相同,唯一的差別也是允許鍵值的重複,也是使用了 RB-tree 的 insert_equal() 而非 insert_unique() 函數。

感謝大家,我是假裝很努力的YoungYangD(小羊)

參考資料:
《STL源碼剖析》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章