在C++98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时的效率可达到O(logN),即最差情况下需要比较红黑树的高度次,当树中的结点非常多时,查询效率也不理想。最好的查询是,进行很少的比较次数就能够将元素找到,因此在C++11中,STL又提供了4个unordered系列的关联式容器,这四个容器与红黑树结构的关联式容器使用方式基本类似,只是其底层结构不同。
unordered_multiset容器与unordered_set容器的底层数据结构是一样的,都是哈希表,其次,它们所提供的成员函数的接口都是基本一致的,这两种容器唯一的区别就是,unordered_multiset容器允许键值冗余,即unordered_multiset容器当中存储的元素是可以重复的。
unordered_multimap容器与unordered_map容器的底层数据结构是一样的,都是哈希表,其次,它们所提供的成员函数的接口都是基本一致的,这两种容器唯一的区别就是,unordered_multimap容器允许键值冗余,即unordered_multimap容器当中存储的键值对的key值是可以重复的。
| 容器 | 底层数据结构 | 是否有序 | 实现版本 | 增删改查效率 | 迭代器类型 |
| unordered_map/unordered_set | 哈希表/散列表 | 否 | C++98 | O(1) | 单向迭代器 |
| map/set | 红黑树 | 是 | C++11 | O(logN) | 双向迭代器 |
- -- unordered_set专用查找算法。优点:使用哈希特性去查找,效率高 -- O(1)
- -- 类似如果是set的,效率是O(logN)
- auto pos = us.find(2); //unordered_set
- auto pos = s.find(2); //set
-
- -- 通用算法,优点:每个容器都可以使用,泛型算法。 缺点:暴力查找 -- O(N)
- -- 复用
- --auto pos = find(us.begin(), us.end(), 2); //find算法在 algorithm.h头文件中
- if (pos != us.end())
- {
- cout << "找到了" << endl;
- }
- else
- {
- cout << "找不到" << endl;
- }
- #include
- #include
- #include
- #include
- using namespace std;
-
- int main()
- {
- int N = 1000;
- vector<int> v;
- v.reserve(N);
- srand((unsigned int)time(NULL));
-
- //随机生成N个数字
- for (int i = 0; i < N; i++)
- {
- v.push_back(rand());
- }
-
- /****************插入效率测试****************/
- //将这N个数插入set容器
- set<int> s;
- clock_t begin1 = clock(); //记录开始时间
- for (auto e : v)
- {
- s.insert(e);
- }
- clock_t end1 = clock(); //记录结束时间
-
- //将这N个数插入unordered_set容器
- unordered_set<int> us;
- clock_t begin2 = clock();
- for (auto e : v)
- {
- us.insert(e);
- }
- clock_t end2 = clock();
-
- //分别输出插入set容器和unordered_set容器所用的时间
- cout << "set insert: " << end1 - begin1 << endl;
- cout << "unordered_set insert: " << end2 - begin2 << endl;
-
- /****************查找效率测试****************/
- //在set容器中查找这N个数
- clock_t begin3 = clock();
- for (auto e : v)
- {
- s.find(e);
- }
- clock_t end3 = clock();
-
- //在unordered_set容器中查找这N个数
- clock_t begin4 = clock();
- for (auto e : v)
- {
- us.find(e);
- }
- clock_t end4 = clock();
-
- //分别输出在set容器和unordered_set容器中查找这N个数所用的时间
- cout << "set find: " << end3 - begin3 << endl;
- cout << "unordered_set find: " << end4 - begin4 << endl;
-
- /****************删除效率测试****************/
- //将这N个数从set容器中删除
- clock_t begin5 = clock();
- for (auto e : v)
- {
- s.erase(e);
- }
- clock_t end5 = clock();
-
- //将这N个数从unordered_set容器中删除
- clock_t begin6 = clock();
- for (auto e : v)
- {
- us.erase(e);
- }
- clock_t end6 = clock();
-
- //分别输出将这N个数从set容器和unordered_set容器中删除所用的时间
- cout << "set erase: " << end5 - begin5 << endl;
- cout << "unordered_set erase: " << end6 - begin6 << endl;
- return 0;
- }
(1)对1000个数做增删查改操作


(2) 10000000个数做增删查改操作


(3)小结