【C++ Primer 第11章】4. 无序容器

一、介绍

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 << "\t" << iter->first.age << endl;
40     }
41 
42     return 0;
43 }

运行结果:

【分析】:因为Tom2和Tom3的age相同,由我们定义的operator<只是比较的age,所以Tom3覆盖了Tom2,结果中没有Tom2。

猜你喜欢

转载自www.cnblogs.com/sunbines/p/9051314.html