hash相关理论

将网上和课件的hash做个小结 

1、解决冲突是hash表的关键,冲突越少,hash表的效率越高

2、设计hash函数方法,分别介绍整数和字符串的hash函数

一、整数的hash函数 

(1)最常见的是直接取余数法,h(k)=k mod M,M表示hash表的容量,此处应注意M的选取,M若选不好,很容易出现同义词。一般情况下,可以选M为素数或者不包含小于20的质因数的合数。

 (2)平方取中法,对关键字k平方,中间几位数k的每一位的影响最大,把关键字k平方后,取出中间r位作为哈希函数h(k)的值,这时需要容量M=2的r次方,一般情况是将关键字转化为二进制,平方后取中间r位作为哈希地址即h(k)

例如:r=4,k=100 

k=(1100100)(二进制表示) 

k平方 =(10010 1000 10000)(二进制表示)

h(k)=(1000)(二进制表示)=8

 (3)利用无理数,用关键字k乘以(0,1)之间的一个无理数A,然后取出小数部分,乘以M,再取出整数部分作为哈希地址

例如 k=100,A=0.,587778,M=20,则h(k)= 15

比较三种优劣:

直接取余法:实现容易,效果手M影响大

平方取中发:速度快,不易推广

乘积取整法:M可以任意选取,效果好,速度慢

因此,在一般情况下,选取第一种就行了 

 二、字符串的hash函数

 (1)字符串一般比较长,无法实现直接定址

 (2) 由于字符串在计算机中是以二进制形式存在,可以将字符串看做256进制的大整数,利用整数中直接取余法

 (3)BKDRhash函数

// BKDR Hash Function
unsigned int BKDRHash(char *str)
{
unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
unsigned int hash = 0;

while (*str)
{
    hash = hash * seed + (*str++);
}

return (hash & 0x7FFFFFFF);
}

 (4)SDBMhash函数

unsigned int SDBMHash(char *str)
{
unsigned int hash = 0;

while (*str)
{
// equivalent to: hash = 65599*hash + (*str++);
hash = (*str++) + (hash << 6) + (hash << 16) - hash;
}

return (hash & 0x7FFFFFFF);
}

 

原文地址:https://www.cnblogs.com/hpustudent/p/2165890.html