散列表
11.3 散列函数
- 好的散列函数的特点:一个好的散列函数应满足简单均与假设,每个关键字被等可能的散列到m个槽位中的任何一个,并与其他关键字已散列到哪个槽位无关。
- 将关键字转化为自然函数
- 多数关键字都假定关键字的全域为自然数集N={0,1,2…},如果所给关键字不是自然数,需要找到一种方法来将它们转换为自然数。
- 一个字符串可以被转换为适当的基数符号表示的整数。如将pt表示为十进制整数对(112,116),然后通过某个基数,进行乘除操作转换为一个很大的数,
- 除法散列法
- 通常取K除以m的余数,将关键字k映射到m个槽中,散列函数为 h(k)=kmodm ,
- 不要选择 m为2的幂次,通常选择一个不太接近2的整数幂的素数
- 乘法散列法
- 构造乘法散列法的步骤:
- 第一步,用关键字K乘上常数A(0
- 构造乘法散列法的步骤:
练习题解答
11.3-1
- 查找关键字k,可以利用散列值h(k)找到对应的链表 (这个问题问的很没有水平。不对,应该是我水平不够,没看懂这个问题)
11.3-2
由于以128为基数,如果字符串r很大,那么以128为基数的k值可能会很大,该方法是书中所说的将关键字转换为大自然数,会造成很大的空间消耗。题目意思是进行处理,将大空间消耗减少成固定的空间消耗。所以要计算k mod m,运用除模运算的性质: (a+b)%m=(a%m+b%m)% m, (ab)%m=(a(b%m))%m;参考来源
代码如下:int hash_string(char a[],int m,int base,int length) { int res=0; int i; for(i=0;i<length;i++) { res+=(a[i]*(base%m))%m; res%=m; } return res; }
11.3-3
- 还是运用(ab)%m=(a(b%m))%m,而 xi∗(2p)imod(2p−1)=xi∗1∗(2p)(i−1)mod2p−1 ,然后逐步递推化解下去。
11.3-4
代码如下:
“`
#include<stdio.h>
#include<math.h>
#define A ((sqrt(5)-1)/2)
int hash(int key,int m)
{
double x=key*A;
int c=(int)key*A;
return (int)((x-c)*m);
}
int main()
{
int a[5]={61,62,63,64,65};
int i;
for(i=0;i<5;i++)
printf("%d \t",hash(a[i],1000));
printf("\n");
return 0;
}
```
11.3-5
- 占坑,等会了再来填补
11.3-6
- 占坑,等会了再来填补