哈希函数设计:(1)直接定制法(2)除留余数法(3)数学分析发
哈希冲突:不同的关键码通过相同的哈希函数计算得到相同的哈希地址称为哈希冲突。
哈希冲突一个可能原因就是哈希函数设计不合理;如果哈希函数设计巧妙,哈希冲突可能性越低,但是不能够避免哈希冲突。
哈希冲突的处理:闭散列和开散列
- 闭散列
闭散列也叫开放地址法,当发生哈希冲突时,如果哈希表未被装满,说明哈希表中还有空位置,那么可以吧key冲放到哈希表中下一个空位置去。如何寻找下一个空位置?(1)线性探测(2)二次探测。采用闭散列处理哈希冲突不可以直接删除元素,如果直接删除可能导致后续元素找不到,所以我们设置哈希表三种状态分别为空、已删除、有元素。删除元素只是更改状态,而不是真正删除该元素。
- 线性探测
采用线性探测优点实现起来简单,缺点:一旦发生哈希冲突可能导致所有冲突连在一块,容易产生数据堆积,所以查找效率降低,那么如何缓解?负载因子
散列表的载荷因子 = 填入表中元素个数/散列表长度
上述公式,可以看出散列表长度一定,载荷因子和表中元素个数成正比。所以载荷因子越大,表中元素个数越多,冲突可能性大。所以科学研究决定载荷因子因该严格限制在0.7—0.8,超过需要扩容以降低哈希冲突。
- 二次探测
线性探测是1、2、3、、、二次探测是1^2、2^2、3^2、、、
- 开散列
开散列也叫链地址法,关键码通过哈希函数得到哈希地址,具有相同的哈希地址归为一类,每一类通过单链表连接,链表头结点存储在哈希表中。
开散列增加了指针开销,但是闭散列需要大量的空闲空间保证效率,所以总的来说开散列反而比闭散列节省空间。
哈希部分常见两种模型:(1)key模型:判断key存在与否(2)key—value模型:通过key得到对应的value
哈希搜索结果应用:
key:(1)判断一个单词拼写是否正确(2)判断一个网名是否被使用过
key—value:(1)中英文翻译(2)英文文章统计每个单词出现次数
//字符串转哈希算法http://www.cnblogs.com/-clq/archive/2012/05/31/2528153.ht
static size_t BKDRHash(const char * str) { unsigned int seed = 131; // 31 131 1313 13131 131313 unsigned int hash = 0; while (*str ) { hash = hash * seed + (*str++); } return (hash & 0x7FFFFFFF); }