【C++】学习笔记——哈希_1


十八、哈希

1. unordered系列关联式容器

在C++11中,STL又提供了4个unordered系列的关联式容器,这四个容器与红黑树结构的关联式容器使用方式基本类似,只是其底层结构不同。
在这里插入图片描述
->查看文档戳这里<-
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
其实这4个加上 unordered 前缀的容器与不加这个前缀的容器几乎没什么不同,唯一不同的就是:unordered容器底层实现采用的是哈希表的存储结构,并不会对数据排序。
如下示例大家就能理解unordered容器了:

#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <set>
using namespace std;

// 集合
void test_set1()
{
    set<int> s;
    s.insert(1);
    s.insert(7);
    s.insert(4);
    s.insert(9);
    s.insert(2);
    cout << "set : ";
    for (auto e : s) cout << e << " ";
    cout << endl;
}

// 无序集合
void test_unordered_set1()
{
    unordered_set<int> s;
    s.insert(1);
    s.insert(7);
    s.insert(4);
    s.insert(9);
    s.insert(2);
    cout << "unordered_set : ";
    for (auto e : s) cout << e << " ";
    cout << endl;
}

int main()
{
    test_set1();
    test_unordered_set1();
    return 0;
}

结果:
在这里插入图片描述
可以看到的是,unordered_set不仅没有排序,还把原数组给搞乱了。
哪unordered容器有什么优势呢?这不被普通的完爆? 其实unordered容器为了加快查找速度,存储数据的时候搞了点小把戏,使其尽可能的在常数时间内查找到某一元素 。因此,unordered容器比普通容器查找要快,但它通常在遍历元素子集的范围迭代方面效率较低。

2. 底层结构

哈希函数

顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,因此在查找一个元素时,必须要经过关键码的多次比较。顺序查找时间复杂度为O(N),平衡树中为树的高度,即O( l o g 2 N log_2 N log2N),搜索的效率取决于搜索过程中元素的比较次数。但是有没有一种方式,可以让我们只需要一次即可直接找到元素呢?
答案是有的,我们只需要建立存储位置与数据之间的映射关系即可。这种存储方式叫做哈希方法。哈希方法中使用的转换函数称为哈希(散列)函数,构造出来的结构称为 哈希表(Hash Table) ,或者称散列表。
例如:数据集合{1,7,6,4,5,9};
哈希函数设置为:hash(key) = key % capacity;capacity为存储元素底层空间总的大小。
在这里插入图片描述
很多人都会想到,这样的存储方法是不安全的,很容易出现 不同关键字通过相同哈希哈数计算出相同的哈希地址,这种现象称为 哈希冲突(哈希碰撞)

哈希冲突

引起哈希冲突的一个原因可能是:哈希函数设计不够合理。
但是,再合理的哈希函数也不能对应所有情况,哈希冲突是无法避免的 。因此我们需要着手解决哈希冲突。比如上面那个例子,当再次插入 15 时,会因为 15 % 10 = 5 ,而下标5已经被占用,我们可以向后遍历,直到找到一个空位放下 ,这是闭散列方法。当然还有其他的方法,比如开散列。开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。
在这里插入图片描述


未完待续

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值