哈希函数的构造及注意事项

哈希表的主要作用其实就是处理数据的映射,把数据转换为更方便,更容易处理的数据。

而映射就是就是一个函数,称之为哈希函数。

 

通常构造哈希函数需要考虑以下要点:

(1)哈希函数的耗时时间

(2)关键字的长度

(3)哈希表的大小

(4)关键字的分布情况

(5)记录的查找频率

 

下面只介绍构造哈希函数最常用的方法也是很简单的方法:

除留余数法

取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。

H(key)=key MOD p (p<=m)

 

所谓的哈希表表长,就是你计划定义的数组元素个数的大小。

 

 

冲突的处理方法

设置的哈希函数一般可以减少冲突,但避免不了。所以,需要有针对冲突的处理方式。

 

冲突处理:令数组元素个数为m ,则当H(key) 已经存储了元素的时候,依次探查 (H(key)+i) modp , i=1,2,3……,直到找到空的存储单元为止(或者从头到尾扫描一圈仍未发现空单元,这就是哈希表已经满了,发生了错误。当然这是可以通过扩大数组范围避免的)。

 

其实意思就是如果H(key)值已经被其他元素占用了,试下H(key)+1,2,3...

 

另外一个就是求模时的p尽量使用素数,不选素数的话可能会造成hash出值的范围和原定义的不一致哈希函数。

 

 

举个例子

好的HASH函数需要把原始数据均匀地分布到HASH数组里

原始数据不大会是真正的随机的,可能有某些规律,

比如大部分是偶数,这时候如果HASH数组容量是偶数,容易使原始数据HASH后不会均匀分布。
比如 2 4 6 8 10 126个数,如果对6 取余 得到2 4 0 2 4 0 只会得到3HASH值,冲突会很多
如果对 7 取余 得到 2 4 6 1 3 5 得到6HASH值,没有冲突

同样地,如果数据都是3的倍数,而HASH数组容量是3的倍数,HASH后也容易有冲突

 

#ifndef _HASH_H_
#define _HASH_H_

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>

#define HASH_GENE 4
#define OVER_ (65535*65535)

int hash(char *key_str, unsigned long MAX_SS_NUM);

#endif //_HASH_H_

hash.c

#include "hash.h"

int hash(char *key_str, unsigned long MAX_SS_NUM)
{
register unsigned int h;
register unsigned char *p;

for(h=0, p = (unsigned char *)key_str; *p ; p++)
{
h = 31 * h + *p;
}

return (h % MAX_SS_NUM);
}




  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值