哈希表(概念)c++
1 哈希表的定义
哈希表(hash table),⼜称散列表,是根据关键字(比如往哈列表里面存整数,那么整数就是关键字,也就是往哈希表里面存的类型,这个类型就是关键字)直接进⾏访问的数据结构;
- 哈希表建⽴了⼀种关键字和存储地址之间的直接映射关系,使每个关键字与结构中的唯⼀存储位置相对应。也就是针对每个关键字都会通过映射关系,拿到一个存储地址,接下来在存储地址里面存储我们想要存储的信息
- 理想情况下,在散列表中进⾏查找的时间复杂度为O(1) ,即与表中的元素数量⽆关。因此哈希表是⼀种存储和查找⾮常快的结构
案例:统计一下字符串 “abcabcc” 中,每一个字符出现的次数,字符串只包含小写字母
这个案例就蕴藏着哈希表的思想,哈希表是给我一个关键字,通过映射关系,找到存储位置,这个案例里面每一个小写字母就是关键字,当我们想找到一个关键词出现的次数的时候,通过关键字ch减去字符‘a’就能找到存储位置,因此这个cnt数组本身就是一个哈希表;这个存储位置,你想存什么是根据你题目的要求,比如这道题要存次数,这里用的就是整型int,如果这道题是想看一个字符有没有出现过,就可以把int换成布尔类型,这个bool类型的数组就是bool类型的哈希表
2 哈希函数
将关键字映射成对应的地址就是哈希函数,也叫作散列函数,记作:hash(key)= addr比如上述案例中的ch-'a’就是一个哈希函数,记作:hash(key)=key'a;大家可以把它写成一个公式,我把值之后,通过这个公式能计算出来一个地址就可以了,比如hash('a') = 'a' - 'a' = 0
- 说白了,哈希函数就是这个(关键字->映射关系->存储位置)里的映射关系。
- 交给哈希函数一个关键字哈希函数给我们计算出一个存储位置
3 哈希冲突
哈希函数可能会把两个或两个以上不同的关键字,映射到同一个位置上,这种情况被称为哈希冲突,也称散列冲突。起冲突的两个不同关键字被称为同义词。
案例:给定数组a={1,3,17,1000000007,49,49,100000007},统计每个数出现的次数
思路一:
创建一个大小为 1e9+8 的数组。但它行不通,首先栈的空间非常有限,如果尝试在函数内部声明如此大的数组,会导致栈溢出,如果分配到堆里面,假设每个元素是整型数组,大小就为4字节×1e9= 4 GB如果系统内存不足或者程序是32 位的可能会导致分配失败
思路二:
设计哈希函数:hash(key)= key%7 ;模7之后创建一个大小为7的数组就可以每个元素映射到数组中每一个下标位置
但如果是以下案例,又会发生问题
哈希函数: hash(key)= key %7
hash(1)=1%7=1
hash(3)=3%7=3
hash(17)=17%7=3
hash(1000000007)=1000000007%7=6
>hash(49)=49%7=0
上面的例子中3模出来的下标是3,7模出来的下标也是3,它们两个就引起了哈希冲突,把两个不同的关键字映射到了同一个位置上,那在统计每个数出现的次数的时候,结果就乱套了,大家可能会说那我换一个模的数字呢,比如模8/9/10,但题目要是把数组里面的元素换成18 17 16,也会出现同样的问题,所以哈希冲突是不可避免的.我们要做的不是消除哈希冲突,而是需要设计出优秀的哈希函数,并且处理哈希冲突。