【正确答案】(1)分析
利用公式计算元素存放的地址:
22:d
1=0 41:d
1=2 53:d
1=5 46:d
1=6 30:d
1=2,d
2=3 13:d
1=6,d
2=9
01:d
1=3,d
2=10 67:d
1=3,d
2=10,d
3=6,d
4=2,d
5=9,d
6=5,d
7=1
得到的散列表:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 22 | 67 | 41 | 30 | | 53 | 46 | | | 13 | 01 |
等概率条件下查找成功的平均查找长度:17/8。
(2)数据结构
#define REGION_LEN 11 /*基本区域长度*/
typedef struct{
int key; /*字典元素的关键码字段*/
int value; /*字典元素的属性字段*/
}DicElement;
typedef struct{
DicElement element[REGION_LEN];
int m; /*n<=REGION LEN,为字典中的元素个数*/
}HashDictionary;
(3)思路
此法选用了一个散列函数H,以关键码为自变量,产生一个0至REGION LEN-1之间的数为地址。如果发生碰撞,则利用给出的递推公式计算下一个地址。递推公式以宏定义的形式给出。
生成散列表的函数:设计其含有一个int参数limit,用以控制字典中的元素总个数;返回值即为指向生成好的散列表的指针。首先为散列表申请空间并完成初始化。然后判断用户给出的字典元素总个数是否满足要求(不能“溢出”),接着进入while循环,不断要求用户给出关键码值,并利用散列函数将它们存入散列表。这里忽略了对元素属性的操作。返回指针值。
(4)算法
#define H1(key)(3*(key))/%(REGION_LEN)
/*用宏定义给出递归公式*/
#define H2(H,key)((H)+(7*(key)))/%(REGION_LEN)
/*这个公式的具体使用参见程序*/
#define null-1 /*null为空结点标记*/
HashDictionary*create(int limit){
int d,i;
intkey;
HashDictionary*p;
p=(HashDictionary*)malloc(sizeof(HashDictionary)); /*申请空间*/
if(p==NULL){
printf("Out of space!\n");
return(p);
}
for(i=0;i<REGION_LEN;i++)p->element[i].key=null; /*初始化*/
if(limit>REGION_LEN){
/*如果用户提供的字典元素总数会使表发生"溢出"*/
printf("Too many keys.Can put/%d keys in Dic only.\n",REGION_LEN);
limit=REGION_LEN;
}
i=0:
while(i<limit){/*依次要求用户输入key值,并按公式放入表中*/
printf("\nPlease input the key:");
scanf("/%d",&key);
d=H1(key);
if(p->element[d].key==null) /*没有发生碰撞*/
p->element[d].key=key;
else{
while(p->element[d].key!=null)d=H2(d,key);
/*按递归公式寻找可以放入的地址*/
p->element[d].key=key;
}
i++:
}
p->m=limit; /*修改字典元素总数*/
return(p);
}
(5)代价分析
设共有n(不大于REGION_LEN)个元素需要放入表中。最好情形是它们互不碰撞,代价为O(n);最坏情形是从放入第二个元素开始均有碰撞,这时为二重while循环,循环次数最多为0+1+2+…+(n-1)=O(n
2)。