1.实验目的
(1) 掌握散列查找的基本思想;
(2) 掌握闭散列表的构造方法;
(3) 掌握线性探测处理冲突的方法;
(4) 验证散列技术的查找性能。
2.实验内容
(1) 对于给定的一组整数和散列函数,采用线性探测法处理冲突构造散列表;
(2) 设计查找算法,验证查找性能。
3.实现提示
首先将待查找集合存储到闭散列表ht中,然后随机生成待查元素的下标,考查在查找成功情况下的比较次数。
4.实验程序
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define SUCCESS 1
#define UNSUCCESS 0
#define HASHSIZE 7 //定义散列表表未数组的长度
#define NULLKEY -32768
typedef struct
{
int *elem; //数据元素存储基地址,动态分配数组
}HashTable;
int m = HASHSIZE; //散列表长,全局变量
//初始化散列表
int InitHashTable(HashTable *h)
{
int i;
h->elem = (int *)malloc(sizeof(int) * m);
if (h->elem == NULL)
{
fprintf(stderr, "malloc() error.\n");
return ERROR;
}
for (i = 0; i < m; i++)
{
h->elem[i] = NULLKEY;
}
return OK;
}
//散列函数
int Hash(int key)
{
return key % m; //除留余数法
}
//插入关键字进散列表
void InsertHash(HashTable *h, int key)
{
int addr = Hash(key); //求散列地址
int i;
for (i = 1; h->elem[addr] != NULLKEY;i++) //如果不为空,则冲突
{
addr = (addr + i) % m; //开放地址法的线性探测
}
h->elem[addr] = key; //直到有空位后插入关键字
}
//散列表查找关键字
int SearchHash(HashTable h, int key)
{
int addr = Hash(key); //求散列地址
int i;
for (i = 1; h.elem[addr] != key;i++) //如果所查关键字不在除留余数法的列表中,则冲突
{
addr = (addr + i) % m; //开放地址法的线性探测
if (h.elem[addr] == NULLKEY || addr == Hash(key))
{
//如果位置为空或循环回原点
printf("查找失败, %d 不在Hash表中.\n", key);
return UNSUCCESS;
}
}
printf("查找成功,%d 在Hash表第 %d 个位置.\n", key, addr+1);
return SUCCESS;
}
int main(int argc, char **argv)
{
int i,j= 0;
HashTable h;
//初始化Hash表
InitHashTable(&h);
//未插入数据之前,打印Hash表
printf("\n未插入数据之前,Hash表中内容为:\n");
for (i = 0; i < HASHSIZE; i++)
{
printf("%d ", h.elem[i]);
}
//插入数据
printf("\n现在插入数据,请输入(A代表结束哦).\n");
while (scanf_s("%d", &i) == 1)
{
if (i == 'a')
{
break;
}
InsertHash(&h, i);
}
//打印插入数据后Hash表的内容
printf("插入数据后Hash表的内容为:\n");
printf("散列地址:\t");
for (i = 0; i < HASHSIZE; i++) {
printf("%d\t", i);
}
printf("\n散列表:\t");
for (i = 0; i < HASHSIZE; i++)
{
printf("%d\t", h.elem[i]);
}
printf("\n现在进行查询.\n");
SearchHash(h, 22);
SearchHash(h, 3);
system("pause");
return 0;
}
5.实验结果
6.实验心得
光读课本对散列表和散列查找理解的不很通透,但通过这次实验,平面的文字在我的脑海里建立起了立体的概念。散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key)。建立了关键字与存储位置的映射关系,f称为散列函数,又称为哈希(Hash)函数。所谓的开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。
这次实验我使用的是开放定值法之一的线性探测法,来解决对于给定的一组整数和散列函数,处理冲突构造散列表问题。本身想再建一个数组用来存放比较次数,尝试在插入关键字函数中计算单个数据的比较次数,但该次数分散列表为空或冲突两种情况,比较复杂,修改多次后最终还是放弃了计算比较次数。