5.1
图片截自答案(非自己画的)
2.
3.
4.
将会插入失败
5.2
待完善
5.3
待完善
5.4
假设P为进行rehash时的装填因子,如果P接近或者等于1.0的话,那么一连串的insert和delete操作就会导致反复的rehash。
如果原表tablesize为2N,当有2N*P个elements时rehash,这时候新表的tablesize就是N,而elements为2PN。这时它需要进行2N-2PN次插入,或者PN次删除才会进行rehash。令2N-2PN=PN,那么P的值为
2
3
2\over3
32。
5.5
- 因为这种策略下,每一个位置都能被探测到,所有冲突总能被解决。
- 可以消除一次聚集,却不能消除二次聚集,因为所有的冲突都使用同一个冲突解决序列。
- 及4.
期望时间与平方探测相近,并且在表未被填满的情况下,插入不会失败。
(从以前的答案中贴过来)
#ifndef _2_7_h
#define _2_7_h
#include <time.h>
extern int RandInt(int i,int j);
clock_t start,finish;
extern void Substitution(int A[],int N);
#endif
#include <stdlib.h>
#include <time.h>
int RandInt(int i,int j)
{
int tmp;
if(i>j)
{
tmp=i;
i=j;
j=tmp;
}
srand((unsigned int)time(0));
return rand()%(j-i+1)+i;
}
#include "2.7.h"
static void Swap(int *p,int *q);
void Substitution(int A[],int N)
{
int i;
for(i=0;i<N;i++)
A[i]=i+1;
for(i=1;i<N;i++)
Swap(&A[i],&A[RandInt(0,i)]);
}
void Swap(int *p,int *q)
{
int tmp;
tmp=*p;
*p=*q;
*q=tmp;
}
5.6
- 分离链接法
- 优点:适度增加装填因子时,性能不受影响,而且可以在扩容时避免再次散列(这相当耗时)。
- 缺点:需要包含另外一个数据结构(链表),一个成功的查找需要遍历大约 1 + λ 2 1+ {\lambda\over2} 1+2λ。给新单元分配地址需要时间,导致算法速度被拖慢。
- 开放定址法
- 线性探测法:只要表有空的单元就不会插入失败。但是会发生一次聚集(primary clustering),并且在装填因子 λ \lambda λ逐渐增大时,需要的探测次数会迅速增加。
- 平方探测法:消除了一次聚集(primary clustering),同时在表的大小是素数,且表至少有一半是空的时候,总能够插入一个新的元素。但是如果表被填满超过一半,或则表的大小不是素数时,有可能会插入失败。同时无法进行标准删除操作,可能导致表提前过满。依旧无法避免二次聚集(secondary clustering)。
- 双散列:使用第二个散列函数增加消耗,同时第二个散列函数的选择必须满足诸多条件。
5.7
5.8
使用线性探测法,在极限情况下散列表也需要30000个表项才能插入完单词,但是这是不可能的,因为性能将极其低下。所以散列表大致应该有60000个表项,而每个表项有8bytes,所以总共480000bytes。
5.9
- 对的
- 不一定,因为不同的单词可能得到的哈希值相同。
- 300007bit,大概37501bytes
- 假设TableSize=300007的情况下,30000个单词将占据表项的10%,那么不在表中的单词将有10%的机会落到值为1的位置上。即错误的概率是 1 10 1\over10 101
- 在对单词拼写要求不是特别严格的情况下,是可用的。因为当文档有20页时,其中的拼写错误有60处,平均可以检测出54处。如果把TableSize扩大约三倍,这种情况下错误概率约 1 30 1\over30 301,也不过能检测出58处,而这将消耗100kb的空间。
5.10
待完善
5.11
待完善
5.12
待完善
5.13
5.14
图片截自答案(非自己画的)