在 C C C++ 11 11 11 中, S T L STL STL 標準庫引入了一個新的標準關聯式容器: u n o r d e r e d _ s e t unordered\_set unordered_set(無序集合)。功能和 s e t set set 類似,都用于存儲唯一元素。但是其底層數據結構是哈希表,因此集合中的元素都是無序存儲的,所以增刪查的時間復雜度為 O ( 1 ) O(1) O(1),增刪查的效率比 s e t set set 高。
文章目錄
- 一、unordered_set 的介紹
- 二、unordered_set 的使用(常用接口)
- 1. 常見構造
- 2. iterator 的使用
- 3. 增刪查
- 4. unordered_multiset
- 三、unordered_set 的模擬實現
- 1. STL 中的 hash_set 源碼
- 2. unordered_set 的迭代器
- 3. 模擬實現 unordered_set
- 總結
一、unordered_set 的介紹
前面部分我們已經詳細介紹了 s e t set set 容器,可以參考我的這篇博客:【STL】 s e t set set。由于 s e t set set 和 u n o r d e r e d _ s e t unordered\_set unordered_set 這兩個容器只是底層實現結構不同,其功能高度相似,基本上只要掌握 s e t set set 的用法, u n o r d e r e d _ s e t unordered\_set unordered_set 也就會用了。因此,和 s e t set set 相比只有一些性能和使用的差異,這里只介紹其差異部分。
u n o r d e r e d _ s e t unordered\_set unordered_set 的聲明如下:
template < class Key, // unordered_set::key_type/value_typeclass Hash = hash<Key>, // unordered_set::hasherclass Pred = equal_to<Key>, // unordered_set::key_equalclass Alloc = allocator<Key> // unordered_set::allocator_type> class unordered_set;
-
K e y Key Key 就是 u n o r d e r e d _ s e t unordered\_set unordered_set 底層關鍵字的類型。
-
u n o r d e r e d _ s e t unordered\_set unordered_set 默認要求 K e y Key Key 支持轉換為整形,如果不支持或者有自己的需求可以自行實現支持將 K e y Key Key 轉成整形的仿函數傳給第二個模板參數。
-
u n o r d e r e d _ s e t unordered\_set unordered_set 默認要求 K e y Key Key 支持比較相等,如果不支持或者有自己的需求可以自行實現支持將 K e y Key Key 比較相等的仿函數傳給第三個模板參數。
-
u n o r d e r e d _ s e t unordered\_set unordered_set 底層存儲數據的內存是從空間配置器申請的,如果需要可以自己實現內存池,傳給第四個參數。
注意:一般情況下,我們都不需要傳后三個模板參數。
u n o r d e r e d _ s e t unordered\_set unordered_set 底層是用哈希桶實現,增刪查平均效率是 O ( 1 ) O(1) O(1),迭代器遍歷不再有序,為了跟 s e t set set 區分,所以取名 u n o r d e r e d _ s e t unordered\_set unordered_set(無序集合)。
二、unordered_set 的使用(常用接口)
u n o r d e r e d _ s e t unordered\_set unordered_set 的底層結構是哈希表,因此不支持比較排序,所以細節上根據這一點和 s e t set set 有略微不同,其他都完全類似。這里只給出常用接口,更多詳細信息可以自行查官方文檔: u n o r d e r e d _ s e t unordered\_set unordered_set。
1. 常見構造
構造 ( c o n s t r u c t o r ) (constructor) (constructor) 函數聲明 | 接口說明 |
---|---|
u n o r d e r e d _ s e t ( ) unordered\_set() unordered_set() | 無參默認構造 |
u n o r d e r e d _ s e t ( c o n s t u n o r d e r e d _ s e t & u s t ) unordered\_set(const\ unordered\_set\&\ ust) unordered_set(const?unordered_set&?ust) | 拷貝構造 |
u n o r d e r e d _ s e t ( I n p u t I t e r a t o r f i r s t , I n p u t I t e r a t o r l a s t ) unordered\_set(InputIterator\ first, InputIterator\ last) unordered_set(InputIterator?first,InputIterator?last) | 使用迭代器區間構造 |
u n o r d e r e d _ s e t ( i n i t i a l i z e r _ l i s t < v a l u e _ t y p e > i l ) unordered\_set (initializer\_list<value\_type> il) unordered_set(initializer_list<value_type>il) | 使用 i n i t i a l i z e r initializer initializer 列表構造 |
2. iterator 的使用
i t e r a t o r iterator iterator 的使用 | 接口說明 |
---|---|
b e g i n ( ) begin() begin() + + + e n d ( ) end() end() | i t e r a t o r iterator iterator |
c b e g i n ( ) cbegin() cbegin() + + + c e n d ( ) cend() cend() | c o n s t _ i t e r a t o r const\_iterator const_iterator |
u n o r d e r e d _ s e t unordered\_set unordered_set 的迭代器是一個單向迭代器:iterator -> a forward iterator to const value_type
。
3. 增刪查
u n o r d e r e d _ s e t unordered\_set unordered_set 增刪查 | 接口說明 |
---|---|
i n s e r t insert insert | 插入 v a l val val 數據 |
e r a s e erase erase | 刪除 v a l val val 數據 |
f i n d find find | 查找 v a l val val,返回 v a l val val 位置的迭代器(沒找到返回 e n d ( ) end() end()) |
c o u n t count count | 查找 v a l val val,返回 v a l val val 的個數 |
由于 u n o r d e r e d _ s e t unordered\_set unordered_set 不支持比較大小,且容器內元素是無序的,因此就沒有 l o w e r _ b o u n d lower\_bound lower_bound 和 u p p e r _ b o u n d upper\_bound upper_bound 接口了。
4. unordered_multiset
u n o r d e r e d _ m u l t i s e t unordered\_multiset unordered_multiset 和 m u l t i s e t multiset multiset 的使用基本完全類似,都支持關鍵值( K e y Key Key)冗余。
和 m u l t i s e t multiset multiset 完全類似, i n s e r t / f i n d / c o u n t / e r a s e insert/find/count/erase insert/find/count/erase 都圍繞著支持值冗余有所差異:
-
i n s e r t insert insert 可以插入相同的值。
-
如果要查找的 x x x 有多個值, f i n d find find 會返回第一個迭代器。
-
c o u n t count count 會返回 x x x 的實際個數。
-
e r a s e erase erase 指定值刪除時,會刪除所有的 x x x。
三、unordered_set 的模擬實現
1. STL 中的 hash_set 源碼
S G I ? S T L 30 SGI-STL\ 30 SGI?STL?30 版本是 C C C++ 11 11 11 之前的 S T L STL STL 版本,源代碼中沒有 u n o r d e r e d _ s e t unordered\_set unordered_set,因為這個容器是 C C C++ 11 11 11 之后才更新的。但是 S G I ? S T L 30 SGI-STL\ 30 SGI?STL?30 實現了哈希表,容器的名字是 h a s h _ s e t hash\_set hash_set,它是作為非標準容器(非 C C C++ 標準規定必須實現的容器)出現的。
- h a s h _ s e t hash\_set hash_set:
- h a s h t a b l e . h hashtable.h hashtable.h:
2. unordered_set 的迭代器
3. 模擬實現 unordered_set
- h a s h t a b l e . h hashtable.h hashtable.h:
- u n o r d e r e d _ s e t . h unordered\_set.h unordered_set.h:
- t e s t . c p p test.cpp test.cpp: