1. unordered系列关联式容器
在 C++98 中, STL 提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到O(logN) ,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想,所以提出了哈希的映射思想
1.1 unordered_map
1. unordered_map 是存储 <key, value> 键值对的关联式容器,其允许通过 keys 快速的索引到与其对应的value 。2. 在 unordered_map 中,键值通常用于惟一地标识元素,而映射值是一个对象,其内容与此键关联。键和映射值的类型可能不同。3. 在内部 ,unordered_map 没有对 <kye, value> 按照任何特定的顺序排序 , 为了能在常数范围内找到key 所对应的 value , unordered_map 将相同哈希值的键值对放在相同的桶中。4. unordered_map 容器通过 key 访问单个元素要比 map 快,但它通常在遍历元素子集的范围迭代方面效率较低。5. unordered_maps 实现了直接访问操作符 (operator[]) ,它允许使用 key 作为参数直接访问value 。6. 它的迭代器至少是前向迭代器
1.1.2 unordered_map的接口说明
因为这个学习比较简单,就直接附上链接,unordered_map的学习其实和map很相似,因为stl使用的统一的封装的方式。所以基本每个容器的使用方式都很接近。
1.2 unordered_set
1.3 使用容器,解决oj问题
思路:我们可以使用unordered_map来统计每个元素出现的次数,然后遍历就可以得到结果
class Solution {
public:
int repeatedNTimes(vector<int>& nums) {
//使用unordered map 把元素放入其中,然后再看哪个元素出现的次数等于N
unordered_map<int,int> m;
for(auto& e: nums)
{
m[e]++;
}
//查找出现n次的
int n = nums.size()/2;
for(auto& e: m)
{
if(e.second == n)
{
return e.first;
}
}
return 0;
}
};
思路:1.我们可以采用unordered_set 对其进行去重,然后在其中一个集合找另一个集合的元素即可
2.我们也可以使用set进行排序加去重,然后通过滑动窗口的方法来得到它们相同的元素
解法1:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
//我们可以采用unordered_set 对其进行去重,然后在其中一个集合找另一个集合的元素即可
vector<int> result;
unordered_set<int> s1;
unordered_set<int> s2;
for(auto& e: nums1)
{
s1.insert(e);
}
for(auto& e: nums2)
{
s2.insert(e);
}
//在遍历s1的时候找s2
for(auto& e: s1)
{
if(s2.find(e) != s2.end())
{
result.push_back(e);
}
}
return result;
}
};
解法2:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
//使用set进行排序加去重,然后在两个set中找相同的元素
set<int> s1(nums1.begin(),nums1.end());
set<int> s2(nums2.begin(),nums2.end());
vector<int> result;
auto it1 = s1.begin();
auto it2 = s2.begin();
//比较谁的元素小就++谁的iterator
while(it1 != s1.end() && it2 != s2.end())
{
if(*it1 == *it2)
{
result.push_back(*it1);
++it1;
++it2;
}
else if(*it1 > *it2)
{
++it2;
}
else{
++it1;
}
}
return result;
}
};
2. 底层结构
unordered系列的关联式容器之所以效率比较高,是因为其底层使用了哈希结构
2.1 哈希概念顺序结构以及平衡树 中,元素关键码与其存储位置之间没有对应的关系,因此在 查找一个元素 时,必须要经过关键码的多次比较 。 顺序查找时间复杂度为 O(N) ,平衡树中为树的高度,即 O(logN) ,搜索的效率取决于搜索过程中元素的比较次数。理想的搜索方法:可以 不经过任何比较,一次直接从表中得到要搜索的元素 。如果构造一种存储结构,通过某种函数 (hashFunc) 使元素的存储位置与它的关键码之间能够建立 一一映射的关系,那么在查找时通过该函数可以很快找到该元素
插入以及搜索:
插入元素根据待插入元素的关键码,以此函数计算出该元素的存储位置并按此位置进行存放搜索元素对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素比较,若关键码相等,则搜索成功
实例:

但是如果插入了%capacity和之前的值一样时就没有办法解决了,这里的例子就可以举例14,这样就会产生哈希冲突。
2.2 哈希冲突
不同关键字通过相同哈希哈数计算出相同的哈希地址,