/**
* 实验题目:
* 实现哈希表的相关运算算法
* 实验目的:
* 领会哈希表的构造和查找过程及其相关算法设计
* 实验内容:
* 设计程序,实现哈希表的相关运算,并完成如下功能:
* 1、建立关键字序列(16, 74, 60, 43, 54, 90, 46, 31, 29, 88, 77)对应的哈希
* 表A[0..12],哈希函数为H(k)=k%p,并采用开放地址法中的线性探测法解决冲突
* 备注:
* 这里的哈希表A[0..12],m=13,取p=m=13,哈希函数H(k)=k%13
* 解决冲突的线性探测法是:d(0)=H(k),d(i+1)=(d(i)+1)%m
* 2、在上述哈希表中查找关键字为29的记录
* 3、在上述哈希表中删除关键字为77的记录,再将其插入
*/
#include
#define MAX_SIZE (100) // 定义最大哈希表长度
#define NULL_KEY (-1) // 定义空关键字值
#define DEL_KEY (-2) // 定义被删关键字值
typedef int key_type; // 关键字类型
typedef char info_type; // 其他数据类型
typedef struct {
key_type key; // 关键字域
info_type data; // 其他数据域
int det_times; // 探测次数域
}HashTable; // 哈希表元素类型
/*---------------将关键字为key的记录插入到哈希表中-------------*/
void insert_ht(HashTable ha[], int &n, int m, int p, key_type key)
{
int i;
int adr;
adr = key % p;
if(ha[adr].key == NULL_KEY || ha[adr].key == DEL_KEY) // x[i]可以直接放在哈希表中
{
ha[adr].key = key;
ha[adr].det_times = 1;
}
else // 发生冲突时采用线性探测法解决冲突
{
i = 1; // i记录x[i]发生冲突的次数
do
{
adr = (adr + 1) % m;
i++;
}while(ha[adr].key != NULL_KEY && ha[adr].key != DEL_KEY);
ha[adr].key = key;
ha[adr].det_times = i;
}
n++;
}
/*---------------------------创建哈希表------------------------*/
void create_ht(HashTable ha[], key_type x[], int n, int m, int p)
{
int i;
int n1 = 0;
for(i = 0; i < m; i++) // 哈希表置初值
{
ha[i].key = NULL_KEY;
ha[i].det_times = 0;
}
for(i = 0; i < n; i++)
insert_ht(ha, n1, m, p, x[i]);
}
/*---------------------------输出哈希表------------------------*/
void disp_ht(HashTable ha[], int n, int m)
{
int i;
float avg = 0;
printf(" 哈希表地址: ");
for(i = 0; i < m; i++)
{
printf("%-4d", i);
}
printf("\n");
printf(" 哈希表关键字:");
for(i = 0; i < m; i++)
{
if(ha[i].key == NULL_KEY || ha[i].key == DEL_KEY)
{
printf(" ");
}
else
{
printf("% -4d", ha[i].key);
}
}
printf("\n");
printf(" 探测次数: ");
for(i = 0; i < m; i++)
{
if(ha[i].key == NULL_KEY || ha[i].key == DEL_KEY)
{
printf(" ");
}
else
{
printf("% -4d", ha[i].det_times);
}
}
printf("\n");
for(i = 0; i < m; i++)
{
if(ha[i].key != NULL_KEY || ha[i].key != DEL_KEY)
{
avg = avg + ha[i].det_times;
}
}
avg = avg / n;
printf(" 平均查找长度ASL(%d)=%g\n", n, avg);
}
/*---------------------------在哈希表中查找关键字key------------------------*/
int search_ht(HashTable ha[], int m, int p, key_type key)
{
int adr;
adr = key % p;
while(ha[adr].key != NULL_KEY && ha[adr].key != key)
{
adr = (adr + 1) % m; // 采用线性探测法找下一个地址
}
if(ha[adr].key == key) // 查找成功
return adr;
else // 查找失败
return -1;
}
/*---------------------------删除哈希表中的关键字key------------------------*/
int delete_ht(HashTable ha[], int m, int p, int &n, int key)
{
int adr;
adr = search_ht(ha, m, p, key);
if(adr != -1) // 在哈希表中找到该关键字
{
ha[adr].key = DEL_KEY;
n--; // 哈希表长度减1
}
else // 在哈希表中未找到该关键字
return 0;
}
int main(int argc, char *argv[])
{
int x[] = {16,74,60,43,54,90,46,31,29,88,77};
int n = 11; // 哈希表长度
int m = 13;
int p = 13;
int key = 29; // 查找关键字
int i;
HashTable ha[MAX_SIZE];
printf("(1)创建哈希表\n");
create_ht(ha, x, n, m, p);
printf("(2)输出哈希表:\n");
disp_ht(ha, n, m);
printf("(3)查找关键字为%d的记录位置\n", key);
i = search_ht(ha, m, p, key);
if(i != -1)
printf(" ha[%d].key=%d\n", i, key);
else
printf(" 提示:未找到%d\n", key);
key = 77;
printf("(4)删除关键字%d\n", key);
delete_ht(ha, m, p, n, key);
printf("(5)删除后的哈希表:\n");
disp_ht(ha, n, m);
printf("(6)查找关键字为%d的记录位置\n", key);
i = search_ht(ha, m, p, key);
if(i != -1)
printf(" ha[%d].key=%d\n", i, key);
else
printf(" 提示:未找到%d\n", key);
printf("(7)插入关键字%d\n", key);
insert_ht(ha, n, m, p, key);
printf("(8)插入后的哈希表:\n");
disp_ht(ha, n, m);
return 0;
}
测试结果:
(1)创建哈希表
(2)输出哈希表:
哈希表地址: 0 1 2 3 4 5 6 7 8 9 10 11 12
哈希表关键字: 77 54 16 43 31 29 46 60 74 88 90
探测次数: 2 1 1 1 1 4 1 1 1 1 1
平均查找长度ASL(11)=1.36364
(3)查找关键字为29的记录位置
ha[6].key=29
(4)删除关键字77
(5)删除后的哈希表:
哈希表地址: 0 1 2 3 4 5 6 7 8 9 10 11 12
哈希表关键字: 54 16 43 31 29 46 60 74 88 90
探测次数: 1 1 1 1 4 1 1 1 1 1
平均查找长度ASL(10)=1.5
(6)查找关键字为77的记录位置
提示:未找到77
(7)插入关键字77
(8)插入后的哈希表:
哈希表地址: 0 1 2 3 4 5 6 7 8 9 10 11 12
哈希表关键字: 77 54 16 43 31 29 46 60 74 88 90
探测次数: 2 1 1 1 1 4 1 1 1 1 1
平均查找长度ASL(11)=1.36364