首先,还是来炒一炒剩饭,毕竟不仅是解惑,更是当作学习笔记来记的!
为什么常见的Hash集合,例如HashSet、LinkedHashSet、HashMap、LinkedHashMap等有如此高的查找能力(后面有时间也会总结一个常见集合的优劣)?
因为它通过一个(或一系列)函数,传递一个key参数,返回一个地址,通过地址直接找到对应value值,你说这样快不快?
Hash表(Hash Table、哈希表、散列表)就是基于此建立的。于是就出现一个情况了,当key1 != key2 ,f(key1)==f(key2),怎么找到key1、key2对应的value呢?
老司机要开车了!!!(理论部分)
以上情况,叫做哈希冲突,这种由同义词引起的冲突,又叫做同义词冲突(注意伏笔)。
于是,我们就考虑了,是不是这个f()函数不行啊?
从函数的角度,我们就开发超级函数,使得任意f(keyi)!=f(keyj),就有了直接定址法,即 f(k)=k+c,这就不可能有冲突了,但是这样k+c<m(地址空间),造成大量内存单元浪费。再想,除留余数法f(k)=k mod p(p=<m(地址空间)),研究表明,p取小于m的素数(质数)最佳,但是仍然会发生冲突。当然还有数字分析法、平方取中法、折叠法等,就不一一说了,都有可能发生哈希冲突,就得换个思路了,怎么解决冲突?
从解决冲突的角度,主要有开放定址法和拉链法。
开放地址法:又分线性探查法和平方探查法。
线性探查法:遇到冲突查找下一个非空地址,存入。于是就出现f(key1)==f(key2)+n的冲突了,冤不冤?你先来就能占我位置了? 坚决抵制!!
平方