技術在於交流、溝通,本文為博主原創文章轉載請注明出處並保持作品的完整性
unordered_set與與unordered_map相似,這次主要介紹unordered_set
unordered_set它的實現基於hashtable,它的結構圖仍然可以用下圖表示,這時的空白格不在是單個value,而是set中的key與value的數據包
有unordered_set就一定有unordered_multiset.跟set和multiset一樣,一個key可以重復一個不可以
unordered_set是一種無序集合,既然跟底層實現基於hashtable那么它一定擁有快速的查找和刪除,添加的優點.基於hashtable當然就失去了基於rb_tree的自動排序功能
unordered_set無序,所以在迭代器的使用上,set的效率會高於unordered_set
template<class _Value, class _Hash = hash<_Value>, class _Pred = std::equal_to<_Value>, class _Alloc = std::allocator<_Value> > class unordered_set : public __unordered_set<_Value, _Hash, _Pred, _Alloc> { typedef __unordered_set<_Value, _Hash, _Pred, _Alloc> _Base; ... }
參數1 _Value key和value的數據包
參數2 _Hash hashfunc獲取hashcode的函數
參數3 _Pred 判斷key是否相等
參數4 分配器
下面介紹一下unordered_set的基本使用,最后我會分享一下我的測試代碼
一 定義
//定義 unordered_set<int> c1; //operator= unordered_set<int> c2; c2 = c1;
二 容量操作
//判斷是否為空 c1.empty(); //獲取元素個數 size() c1.size(); //獲取最大存儲量 max_size() c1.max_size();
三 迭代器操作
//返回頭迭代器 begin() unordered_set<int>::iterator ite_begin = c1.begin(); //返回尾迭代器 end() unordered_set<int>::iterator ite_end = c1.end(); //返回const頭迭代器 cbegin() unordered_set<int>::const_iterator const_ite_begin = c1.cbegin(); //返回const尾迭代器 cend() unordered_set<int>::const_iterator const_ite_end = c1.cend(); //槽迭代器 unordered_set<int>::local_iterator local_iter_begin = c1.begin(1); unordered_set<int>::local_iterator local_iter_end = c1.end(1);
四 基本操作
//查找函數 find() 通過給定主鍵查找元素 unordered_set<int>::iterator find_iter = c1.find(1); //value出現的次數 count() 返回匹配給定主鍵的元素的個數 c1.count(1); //返回元素在哪個區域equal_range() 返回值匹配給定搜索值的元素組成的范圍 pair<unordered_set<int>::iterator, unordered_set<int>::iterator> pair_equal_range = c1.equal_range(1); //插入函數 emplace() c1.emplace(1); //插入函數 emplace_hint() 使用迭代器 c1.emplace_hint(ite_begin, 1); //插入函數 insert() c1.insert(1); //刪除 erase() c1.erase(1);//1.迭代器 value 區域 //清空 clear() c1.clear(); //交換 swap() c1.swap(c2);
五 籃子操作
//籃子操作 籃子個數 bucket_count() 返回槽(Bucket)數 c1.bucket_count(); //籃子最大數量 max_bucket_count() 返回最大槽數 c1.max_bucket_count(); //籃子個數 bucket_size() 返回槽大小 c1.bucket_size(3); //返回籃子 bucket() 返回元素所在槽的序號 c1.bucket(1); // load_factor 返回載入因子,即一個元素槽(Bucket)的最大元素數 c1.load_factor(); // max_load_factor 返回或設置最大載入因子 c1.max_load_factor();
六 內存操作
// rehash 設置槽數 c1.rehash(1); // reserve 請求改變容器容量 c1.reserve(1000);
七 hash func
//hash_function() 返回與hash_func相同功能的函數指針 auto hash_func_test = c1.hash_function(); //key_eq() 返回比較key值得函數指針 auto key_eq_test = c1.key_eq();
八 測試代碼
#include <iostream> #include <unordered_set> using namespace std; namespace wzj001{ void coutUnorderedSet(std::unordered_set<int>& m, string funcName) { std::unordered_set<int>::iterator it; std::cout << funcName << ": "; for ( it = m.begin(); it != m.end(); it++ ) std::cout << *it << " "; std::cout << std::endl; } void initUnorderSet(unordered_set<int>& tmp) { for(int i = 0; i < 10; i++) tmp.insert(i); } string turnBoolToString(bool tmp) { return tmp ? "true" : "false"; } void basicOperationUnorderedSet() { //定義 std::unordered_set<int> c; // 普通插入,返回pair<迭代器,插入是否成功> pair<unordered_set<int>::iterator, bool> c_insert = c.insert(1); cout << "指向key的迭代器: " << *c_insert.first << " 插入是否成功 "<< turnBoolToString(c_insert.second)<<endl; pair<unordered_set<int>::iterator, bool> c_insert2 = c.insert(2); cout << "指向key的迭代器: " << *c_insert2.first << " 插入是否成功 "<< turnBoolToString(c_insert2.second)<<endl; pair<unordered_set<int>::iterator, bool> c_insert3 = c.insert(1); cout << "指向key的迭代器: " << *c_insert3.first << " 插入是否成功 "<< turnBoolToString(c_insert3.second)<<endl; //按指定區域插入 std::unordered_set<int> c_insert_region; c_insert_region.insert(c.begin(), c.end()); coutUnorderedSet(c_insert_region, "按指定區域插入"); //構造插入 std::unordered_set<int> c_emplace; c_emplace.emplace(1); c_emplace.emplace(2); c_emplace.emplace(3); coutUnorderedSet(c_emplace, "構造插入"); //迭代器插入 std::unordered_set<int> c_emplace_hint; c_emplace_hint.emplace_hint(c_emplace_hint.begin(), 1); c_emplace_hint.emplace_hint(c_emplace_hint.begin(), 2); c_emplace_hint.emplace_hint(c_emplace_hint.begin(), 3); coutUnorderedSet(c_emplace_hint, "迭代器插入"); //刪除 std::unordered_set<int> c_erase; initUnorderSet(c_erase); coutUnorderedSet(c_erase, "初始化c_erase"); //指定位置刪除 c_erase.erase(c_erase.begin()); coutUnorderedSet(c_erase, "指定位置刪除"); //指定key刪除 c_erase.erase(8); coutUnorderedSet(c_erase, "指定key刪除"); //指定區域刪除 c_erase.erase(c_erase.begin(), c_erase.end()); coutUnorderedSet(c_erase, "指定區域刪除"); //交換 c.swap(c_emplace); coutUnorderedSet(c, "交換"); } void unorderSetElementLookup() { //查找 std::unordered_set<int> c_find; initUnorderSet(c_find); std::unordered_set<int>::iterator find_iter = c_find.find(10); if(find_iter != c_find.end()) { cout<< "找到元素 : "<< *find_iter << endl; } else cout<< "沒找到 !"<< endl; cout << "value出現次數 :" <<c_find.count(1)<< endl; //set key不可重復 pair<std::unordered_set<int>::iterator, std::unordered_set<int>::iterator> tmp = c_find.equal_range(5); if(tmp.first != c_find.end()&& tmp.second != c_find.end()) { cout << "該值所在區間為[" << *tmp.first << "," << *tmp.second << "]" << endl; } } void unorderSetBuckets() { //籃子操作 std::unordered_set<int> c_buckets; initUnorderSet(c_buckets); cout << "籃子個數: " << c_buckets.bucket_count()<< endl; cout << "籃子大小: " << c_buckets.bucket_size(1) << endl; cout << "最大籃子個數: " << c_buckets.max_bucket_count() << endl; cout << "該值所在籃子序號: " << c_buckets.bucket(3) << endl; } void unorderSetHashPolicy() { std::unordered_set<int> c_; cout << "負載: "<< c_.load_factor()<< endl; initUnorderSet(c_); cout << "負載: "<< c_.load_factor()<< endl;//使用的籃子數/籃子總數 默認的籃子數為11 cout << "最大負載: "<< c_.max_load_factor() << endl; c_.reserve(100);//預設籃子數 ,但是還沒有設定 c_.rehash(3);//設定籃子數 } void unorderSetObservers() { std::unordered_set<int> c_; initUnorderSet(c_); std::unordered_set<int>::hasher xxx = c_.hash_function(); std::unordered_set<int>::key_equal zzz = c_.key_eq(); cout << "hash_func: " << xxx(11111) << endl; cout << "key_eq: " << turnBoolToString(zzz(11111,11111)) << endl; } } int main() { wzj001::basicOperationUnorderedSet(); wzj001::unorderSetElementLookup(); wzj001::unorderSetBuckets(); wzj001::unorderSetHashPolicy(); wzj001::unorderSetObservers(); }