哈希表
Python字典是用哈希表(hash table)实现的。哈希表是一个数组,它的索引是对键运用哈希函数(hash function)求得的。哈希函数的作用是将键均匀地分布到数组中,一个好的哈希函数会将冲突(译者注:冲突指不同键经过哈希函数计算得到相同的索引,这样造成索引重复的冲突。)的数量降到最小。Python没有这类哈希函数,它最重要的哈希函数(用于字符串和整数)很常规:
>>> map(hash, (0, 1, 2, 3))
[0, 1, 2, 3]
>>> map(hash, ("namea", "nameb", "namec", "named"))
[-1658398457, -1658398460, -1658398459, -1658398462]
哈希表核心思想就是python的字典,需要存储的对象就是字典的value,对象的关键字就是字典的键,通过哈希函数把字典的键映射到一个内存地址上,然后内存地址里存储的就是对象。—哈希函数构建的是地址。
哈希表(散列表),是除顺序表、链表、索引表存储结构之外的一种存储线性表的 存储结构。基本思想就是对于n个对象,设置一个长度为m的连续内存单元,以每个对象的关键字ki作为自变量,通过一个哈希函数h(ki),把ki映射为内存单元的地址,并且把对象存储在这个内存单元中。
哈希冲突值得就是不同的ki但是通过哈希函数得到了相同的h(ki),从而产生的哈希冲突。
哈希函数的目标是使得得到的哈希地址可以尽可能的均匀分布在给定的n个连续的内存地址单元上,同时使得计算过程尽可能简单以达到更高的时间效率。
哈希函数的构造方法
1、直接定址法
h(k) = k + c
优点是计算简单并且不可能冲突发生。当关键字分布均匀的时候可以采用,但是不均匀的时候会产生较多的内存单元的大量浪费。
2、除留余数法
h(k) = k % p
优点是计算简单,使用范围广–最经常使用的方法。
哈希冲突的解决
哈希冲突的产生和 已经装入的元素N和哈希地址的空间大小m有关,也就是装入越少,空间越大,肯定越好。
1、开放定址法
a、线性探查
遇到冲突的时候,继续往下探测,可以考虑直接线性探索,在冲突地址的基础上继续探索下一个地址, 直到找到没有使用过的地址。缺点是会导致堆积问题。
b、平方探查
也就是在原来的基础上,加上或减去平方,再取余数–因为一定是在 m的空间里面。
d = (d +/- i*i) % m
2、拉链法
把所有冲突的词用单链表连接起来。
优点是:
1、处理简单,没有堆积现象
2、适合事先无法确定表长的情况,就不会过多的设置内存空间导致浪费。
3、删除方便。
缺点是链表的指针需要额外的空间,如果元素的规模比较小,还是使用开放定址法比较节省空间。