文章目录
- 1. 引言
- 2. 实验原理
- 2.1 散列表
- 2.2 线性探测法
- 2.3 冲突解决
- 3. 实验内容
- 3.1 实验题目
- (一)输入要求
- (二)输出要求
- 3.2 算法实现
- 3.3 代码整合
- 4. 实验结果
1. 引言
本实验将通过C语言实现基于散列表的查找算法
2. 实验原理
2.1 散列表
散列表(Hash Table)是一种常见的数据结构,通过使用哈希函数将关键字映射到一个固定大小的数组中。这样可以通过计算关键字的哈希值,将其直接映射到数组的索引,实现快速的数据查找。
2.2 线性探测法
哈希函数是散列表中的关键组成部分,它接受一个关键字并返回其在数组中的索引。一个好的哈希函数应该具有以下特性:
- 一致性:对于相同的输入,始终返回相同的输出。
- 均匀性:哈希值在数组范围内均匀分布,避免冲突。
2.3 冲突解决
由于哈希函数的输出范围有限,不同的关键字可能映射到相同的索引位置,造成冲突。冲突解决的方法有很多,包括链地址法、开放地址法等。
3. 实验内容
3.1 实验题目
编写算法构造教材图 8.47 的拉链表,输出散列表每个槽对应的单链表,并编程计算查找成功时的平均查找长度。
(一)输入要求
char *A[30]={
"THE","OF","AND","TO","A",
"IN","THAT","IS","WAS","HE",
"FOR","IT","WITH","AS","HIS",
"ON","BE","AT","BY","I",
"THIS","HAD","NOT","ARE","BUT",
"FROM","OR","HAVE","AN","THEY",
};
int B[30]={
25,9,11,27,1,7,9,26,5,13,
27,29,2,18,18,1,7,21,27,9,
6,13,21,22,3,22,29,26,15,0
};
(二)输出要求
- 输出散列表每个槽 HEADi对应的单链表;
- 编程计算并输出查找成功时的平均查找长度。
3.2 算法实现
-
数据结构定义:
typedef struct P{ char *data; struct P *next; }P;
定义了一个结构体
P
,包含了一个字符串类型的数据域data
和一个指向下一个节点的指针next
,用于构建散列表的基本节点结构。 -
散列表数组:
P* HEAD[32];
数组
HEAD
中的每个元素是一个指向链表头部的指针~这是一个散列表,共有 32 个槽(桶)。 -
Create 函数:
void Create(char *A, int K) { int i = K; P *p = (P*)malloc(sizeof(P)); p->data = A; p->next = HEAD[i]; HEAD[i] = p; }
Create
函数用于在散列表中插入数据。给定字符串A
和整数K
,根据K
计算数组的索引,将数据插入到对应的链表的头部。 -
Output 函数:
void Output() { P *p; int i; for (i = 0; i < 32; i++) { printf("HEAD: %2d", i); if (HEAD[i] != NULL) { p = HEAD[i]; for (; p != NULL; p = p->next) printf(" —>%s", p->data); } else printf("空"); printf("\n"); } }
Output
函数用于输出整个散列表的内容。对于每个槽,输出链表中的所有节点。 -
Find 函数:
int Find(char *ch, int K){ int time = 0; int i = K; P *p = HEAD[i]; while (p){ time++; if (p->data == ch) return time; p = p->next; } return 0; }
Find
函数用于在散列表中查找特定数据。给定字符串ch
和整数K
,根据K
计算数组的索引,然后在对应链表中查找字符串。如果找到,返回查找次数;否则,返回 0。 -
主函数:
int main() { // 数据初始化 char *A[30] = { /* ... */ }; int B[30] = { /* ... */ }; int i, f, times = 0; float sum = 0; // 创建散列表 for (i = 0; i < 30; i++){ Create(A[i], B[i]); } // 输出散列表 Output(); // 查找并计算平均查找长度 for (i = 0; i < 30; i++){ f = Find(A[i], B[i]); if (f){ times++; sum += f; } } printf("查找成功时的平均查找长度为:%f", sum / times); return 0; }
3.3 代码整合
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct P{
char *data;
struct P *next;
}P;
P* HEAD[32];
void Create(char *A,int K)
{
int i=K;
P *p=(P*)malloc(sizeof(P));
p->data=A;
p->next=HEAD[i];
HEAD[i]=p;
// printf("%d %s\n",i,p->A);
}
void Output()
{
P *p;
int i;
for(i=0;i<31;i++)
{
printf("HEAD: %2d",i);
if(HEAD[i]!=NULL)
{
p=HEAD[i];
for(;p!=NULL;p=p->next)
printf(" —>%s",p->data);
}
else printf("空");
printf("\n");
}
}
int Find(char *ch,int K){
int time=0;
int i=K;
P *p=HEAD[i];
while(p){
time++;
if(p->data==ch) return time;
p=p->next;
}
return 0;
}
int main()
{
char *A[30]={
"THE","OF","AND","TO","A",
"IN","THAT","IS","WAS","HE",
"FOR","IT","WITH","AS","HIS",
"ON","BE","AT","BY","I",
"THIS","HAD","NOT","ARE","BUT",
"FROM","OR","HAVE","AN","THEY",
};
int B[30]={
25,9,11,27,1,7,9,26,5,13,
27,29,2,18,18,1,7,21,27,9,
6,13,21,22,3,22,29,26,15,0
};
int i,f,times=0;
float sum=0;
for(i=0;i<30;i++){
Create(A[i],B[i]);
}
Output();
for(i=0;i<30;i++){
f=Find(A[i],B[i]);
if(f){
//printf("查找成功");
times++;
sum+=f;
}
//else printf("查找失败");
}
printf("查找成功时的平均查找长度为:%f",sum/times);
return 0;
}
4. 实验结果
HEAD: 0 —>THEY
HEAD: 1 —>ON —>A
HEAD: 2 —>WITH
HEAD: 3 —>BUT
HEAD: 4空
HEAD: 5 —>WAS
HEAD: 6 —>THIS
HEAD: 7 —>BE —>IN
HEAD: 8空
HEAD: 9 —>I —>THAT —>OF
HEAD: 10空
HEAD: 11 —>AND
HEAD: 12空
HEAD: 13 —>HAD —>HE
HEAD: 14空
HEAD: 15 —>AN
HEAD: 16空
HEAD: 17空
HEAD: 18 —>HIS —>AS
HEAD: 19空
HEAD: 20空
HEAD: 21 —>NOT —>AT
HEAD: 22 —>FROM —>ARE
HEAD: 23空
HEAD: 24空
HEAD: 25 —>THE
HEAD: 26 —>HAVE —>IS
HEAD: 27 —>BY —>FOR —>TO
HEAD: 28空
HEAD: 29 —>OR —>IT
HEAD: 30空
查找成功时的平均查找长度为:1.466667