C++ 哈希

文章介绍了C++STL中的unordered_map关联式容器,强调其快速查询特性,底层基于哈希结构。哈希冲突的概念和解决方法,如开放定址法(闭散列)和链地址法(开散列)被讨论。还提到了位图和布隆过滤器的应用,尤其是在处理大数据和概率查找场景中的优势和局限性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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使用的统一的封装的方式。所以基本每个容器的使用方式都很接近。

unordered_map使用

1.2 unordered_set

unordered_set使用

1.3 使用容器,解决oj问题

在长度 2N 的数组中找出重复 N 次的元素

思路:我们可以使用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 哈希冲突

不同关键字通过相同哈希哈数计算出相同的哈希地址,
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值