#include <iostream> using namespace std; #include <string> #include <windows.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <map> const int maxval = 2000000 * 5; #include <unordered_map> void map_test() { printf("map_test\n"); map<int, int> mp; clock_t startTime, endTime; startTime = clock(); for (int i = 0; i < maxval; i++) { mp[rand() % maxval]++; } endTime = clock(); printf("%lf\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); printf("insert finish\n"); startTime = clock(); for (int i = 0; i < maxval; i++) { if (mp.find(rand()%maxval) == mp.end()) { //printf("not found\n"); } } endTime = clock(); printf("%lf\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); printf("find finish\n"); startTime = clock(); for(auto it = mp.begin(); it!=mp.end(); it++) { } endTime = clock(); printf("%lf\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); printf("travel finish\n"); printf("------------------------------------------------\n"); } void hash_map_test() { printf("hash_map_test\n"); unordered_map<int, int> mp; clock_t startTime, endTime; startTime = clock(); for (int i = 0; i < maxval; i++) { mp[rand() % maxval] ++; } endTime = clock(); printf("%lf\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); printf("insert finish\n"); startTime = clock(); for (int i = 0; i < maxval; i++) { if (mp.find(rand() % maxval) == mp.end()) { //printf("not found\n"); } } endTime = clock(); printf("%lf\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); printf("find finish\n"); startTime = clock(); for(auto it = mp.begin(); it!=mp.end(); it++) { } endTime = clock(); printf("%lf\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); printf("travel finish\n"); printf("------------------------------------------------\n"); } int main(int argc, char *argv[]) { srand(0); map_test(); Sleep(1000); srand(0); hash_map_test(); system("pause"); return 0; }
map(使用红黑树)与unordered_map(hash_map)比较
map理论插入、查询时间复杂度O(logn)
unordered_map理论插入、查询时间复杂度O(1)ios
数据量较小时,多是因为unordered_map(hash_map)初始大小较小,大小频繁到达阈值,屡次重建致使插入所用时间稍大。(相似vector的重建过程)。
哈希函数也是有消耗的(应该是常数时间),这时候用于哈希的消耗大于对红黑树查找的消耗(O(logn)),因此unordered_map的查找时间会多余对map的查找时间。windows
数据量较大时,重建次数减小,用于重建的开销小,unordered_map O(1)的优点开始显现函数
数据量更大,优点更明显测试
使用空间:优化
前半部分为map,后半部分为unordered_map
unordered_map占用的空间比map略多,但能够接受。
map和unordered_map内部实现应该都是采用达到阈值翻倍开辟空间的机制(1六、3二、6四、12八、25六、5十二、1024……)浪费必定的空间是不可避免的。而且在开双倍空间时,若不能从当前开辟,会在其余位置开辟,开好后将数据移过去。数据的频繁移动也会消耗必定的时间,在数据量较小时尤其明显。spa
一种方法是手写定长开散列。这样作在数据量较小时有很好地效果(避免了数据频繁移动,真正趋近O(1))。但因为是定长的,在数据量较大时,数据重叠严重,散列效果急剧降低,时间复杂度趋近O(n)。3d
一种折中的方法是本身手写unordered_map(hash_map),将初始大小赋为一个较大的值。扩张能够模仿STL的双倍扩张,也能够本身采用其余方法。这样写出来的是最优的,可是实现起来极为麻烦。
综合利弊,咱们组采用unordered_map。调试
附:使用Dev测试与VS2017测试效果相差极大???code
效率差了10倍???
缘由:
Devblog
VS2017
在Debug下,要记录断点等调试信息,的确慢。
Release:不对源代码进行调试,编译时对应用程序的速度进行优化,使得程序在代码大小和运行速度上都是最优的。
VS2017切到release后,还更快
除了前面说的Debug与release致使效率差别外,编译器的不一样也会致使效率差别。 学到了。