set的特性是,所有元素都會根據元素的鍵值自動被排序,set元素的鍵值就是實值,實值就是鍵值,set不允許兩個元素有相同的鍵值。
set的元素值不可以通過迭代器來改變,因為set元素就是其鍵值,關係到set元素的排列規則;如果任何改變set元素值,會嚴重破壞set組織。
set是以rb-tree作為底層機制,又由於set所開放的各種操作介面,rb-tree也提供,所以幾乎所有的set操作行為都只是呼叫rb-tree的操作行為。
1. set的構成
set的內部成員變數只有乙個 _rep_type _m_t; // red-black tree representing set.
set的內部迭代器全部都是const_iterator,杜絕寫入操作
set的成員變數型別中 typedef _rb_tree,key_compare, _key_alloc_type> _rep_type可以看出,構造的rb-tree的value和key是同乙個型別。
template,
typename _alloc = std::allocator<_key> >
class set
private:
typedef typename __gnu_cxx::__alloc_traits<_alloc>::template
rebind<_key>::other _key_alloc_type;
typedef _rb_tree,
key_compare, _key_alloc_type> _rep_type;
_rep_type _m_t; // red-black tree representing set.
typedef __gnu_cxx::__alloc_traits<_key_alloc_type> _alloc_traits;
public:
//@// allocation/deallocation
/*** @brief default constructor creates no elements.
*/set()
: _m_t()
。。。}
2. 元素的插入操作
元素的插入操作insert實現如下,它內部呼叫的是_m_insert_unique,在c++高階——stl原始碼之紅黑樹(_rb_tree)一文中,我們已經分析過該函式,它對於新值的插入是不允許結點重複的,若重複,插入無效。
std::pairinsert(const value_type& __x)
template#if __cplusplus >= 201103l
template#endif
pair::iterator, bool>
_rb_tree<_key, _val, _keyofvalue, _compare, _alloc>::
#if __cplusplus >= 201103l
_m_insert_unique(_arg&& __v)
#else
_m_insert_unique(const _val& __v)
#endif
_m_get_insert_unique_pos的主要實現:插入新值,不允許重複,若重複插入無效。
templatepair::_base_ptr,
typename _rb_tree<_key, _val, _keyofvalue,
_compare, _alloc>::_base_ptr>
_rb_tree<_key, _val, _keyofvalue, _compare, _alloc>::
_m_get_insert_unique_pos(const key_type& __k)
iterator __j = iterator(__y);//指向插入點的父結點
if (__comp)//comp為true,說明插在左側
//新鍵值不與既有結點重複,於是執行安插
if (_m_impl._m_key_compare(_s_key(__j._m_node), __k))
return _res(__x, __y);
return _res(__j._m_node, 0);
}
multiset的特性以及用法和set完全相同,唯一的差別在於它允許鍵值重複,因此它的插入操作採用的是底層機制rb-tree的_m_insert_equal。
iterator
insert(const value_type& __x)
呼叫的是rb-tree內部的方法,實現如下:
template#if __cplusplus >= 201103l
template#endif
typename _rb_tree<_key, _val, _keyofvalue, _compare, _alloc>::iterator
_rb_tree<_key, _val, _keyofvalue, _compare, _alloc>::
#if __cplusplus >= 201103l
_m_insert_equal(_arg&& __v)
#else
_m_insert_equal(const _val& __v)
#endif
上述**中呼叫了_m_get_insert_equal_pos,其中的實現是從根節點開始,往下尋找適當的插入點,區別於上述的新值的判斷,這裡是不做判斷是否有重複的。
templatepair::_base_ptr,
typename _rb_tree<_key, _val, _keyofvalue,
_compare, _alloc>::_base_ptr>
_rb_tree<_key, _val, _keyofvalue, _compare, _alloc>::
_m_get_insert_equal_pos(const key_type& __k)
return _res(__x, __y);//x為插入點,y為插入點的父結點
}
STL原始碼分析set
include include using namespace std int main set iset ia,ia 5 cout size iset.size endl cout 3 count iset.count 3 endl iset.insert 3 cout size iset.siz...
C 高階 STL原始碼之順序容器介面卡
容器介面卡是一種利用存在的容器型別採用另一種不同的抽象型別的工作方式實現。stack是一種先進後出的資料結構,它只有乙個出口 stack允許新增元素 移除元素 取得最頂端的元素 但是除了頂端外不可以訪問其他元素 stack沒有迭代器。stack在預設的情況下是以deque作為底部容器來完成所有的工作...
STL原始碼分析之Vector
地球人都知道vector的查詢效率很高,插入和刪除的效率低下,容器會隨著元素的不斷增加自動增長,最近在看了stl原始碼之後,發現確實是這樣,下面是vector一些關鍵的函式.從這些函式可以看出插入和刪除的過程,以及容器自動增長的方式.兩個通過下標獲取元素的函式.reference operator ...