一、介绍
1. Hashtable和bucket
由于unordered_map内部采用的hashtable的数据结构存储,所以,每个特定的key会通过一些特定的哈希运算映射到一个特定的位置,我们知道,hashtable是可能存在冲突的(多个key通过计算映射到同一个位置),在同一个位置的元素会按顺序链在后面。所以把这个位置称为一个bucket是十分形象的(像桶子一样,可以装多个元素)。
所以unordered_map内部其实是由很多哈希桶组成的,每个哈希桶中可能没有元素,也可能有多个元素。
无序容器管理操作
- 有序容器通过比较运算符来组织元素
- 无序容器通过哈希函数和==运算符来组织元素
这是因为无序容器在存储上组织为一组桶:
- 哈希函数将元素映射到桶
- 在桶中搜索某个元素时需要用到==运算符
如果一个桶中保存了很多元素,那么查找一个特定元素就需要大量比较操作
无序容器提供了一些管理桶和哈希策略的操作:
桶接口
• c.bucket_count()
• c.max_bucket_count()
• c.bucket_size(n)
• c.bucket(k)
桶迭代
• local_iterator
• const_local_iterator
• c.begin(n), c.end(n)
• c.cbegin(n), c.cend(n)
哈希策略
• c.load_factor()
• c.max_load_factor()
• c.rehash(n)
• c.reserve(n)
2. 构造函数
unordered_map的构造方式有几种:
•
构造空的容器
• 复制构造
•
范围构造
• 用数组构造
1 #include <iostream> 2 #include <string> 3 #include <unordered_map> 4 using namespace std; 5 6 typedef unordered_map<string, string> stringmap; 7 stringmap merge(stringmap a, stringmap b) 8 { 9 stringmap temp(a); 10 temp.insert(b.begin(), b.end()); 11 return temp; 12 } 13 14 int main() 15 { 16 stringmap first; // 空 17 stringmap second({ {"apple", "red"}, {"lemon", "yellow"} }); // 用数组初始 18 stringmap third({ {"orange", "orange"}, {"strawberry", "red"} }); // 用数组初始 19 stringmap fourth(second); // 复制初始化 20 stringmap fifth(merge(third, fourth)); // 移动初始化 21 stringmap sixth(fifth.begin(), fifth.end()); // 范围初始化 22 23 cout << "sixth contains:" << endl; 24 for (auto& x : sixth) 25 cout << x.first << ": " << x.second << endl; 26 return 0; 27 }
运行结果:
1 #include<string> 2 #include<iostream> 3 #include<map> 4 using namespace std; 5 6 struct person 7 { 8 string name; 9 int age; 10 11 person(string name, int age) 12 { 13 this->name = name; 14 this->age = age; 15 } 16 17 bool operator < (const person& p) const 18 { 19 return this->age < p.age; 20 } 21 }; 22 23 map<person, int> m; 24 int main() 25 { 26 person p1("Tom1", 20); 27 person p2("Tom2", 22); 28 person p3("Tom3", 22); 29 person p4("Tom4", 23); 30 person p5("Tom5", 24); 31 m.insert(make_pair(p3, 100)); 32 m.insert(make_pair(p4, 100)); 33 m.insert(make_pair(p5, 100)); 34 m.insert(make_pair(p1, 100)); 35 m.insert(make_pair(p2, 100)); 36 37 for (map<person, int>::iterator iter = m.begin(); iter != m.end(); iter++) 38 { 39 cout << iter->first.name << " " << iter->first.age << endl; 40 } 41 42 return 0; 43 }
运行结果:
【分析】:因为Tom2和Tom3的age相同,由我们定义的operator<只是比较的age,所以Tom3覆盖了Tom2,结果中没有Tom2。