文章目录
数据结构 P8 哈希表(hash)
简介
哈希表的定义
哈希表是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key)
这里把这种对应关系f称为哈希函数,又称为散列函数,采用哈希技术将存储在一块连续的存储空间中,这块连续存储空间称为哈希表
哈希表查找的步骤
在存储时,通过哈希函数计算记录的哈希地址,并按此哈希地址存储该记录
当查找记录时,我们通过同样的哈希函数计算记录的哈希地址,按此哈希地址访问该记录
哈希技术既是一种存储方法,也是一种查找方法
哈希技术最适合的求解问题是查找与给定值相等的记录
构造方法
直接定地址法
直接定地址法:取关键字的某个线性函数值为哈希地址
优点:简单、均匀、也不会产生冲突
缺点:需要事先知道关键字的分布情况,适合查找表较小且连续的情况
数字分析法
抽取方法是使用关键字的一部分来计算哈希存储位置的方法,这在哈希函数中是常常用到的手段
数字分析法通常适合处理关键字位数比较大的情况,如果事先知道关键字的分布且关键字的若干位分布较均匀
平方取中法
平方取中法比较适合于不知道关键字的分布,而位数又不是很大的情况
折叠法
折叠法是将关键字从左到右分割成位数相等的几部分,然后将这几部分叠加求和,并按哈希列表表长,取后几位作为散列地址
除留余数法
除留余数法
处理哈希表冲突
开发定地址法
开放地址法就是一旦发生了冲突,就去寻找下一个空的函数地址,只要函数表足够大,空的哈希地址总能找到,并将记录存入
再哈希函数法
链地址法
公共溢出区法
哈希表查找的实现
创建结构体
创建文件
编写hash.h
创建哈希表
编写hash.h
编写hash.c
hash *hash_create(){
hash *HT;
if((HT = (hash *)malloc(sizeof(hash))) == NULL){
printf("malloc is failed\n");
return NULL;
}
memset(HT,0,sizeof(hash));
return HT;
}//创建哈希表
插入关键字
编写hash.h
编写hash.c
int hash_insert(hash *HT,data_t key){
lklist p,q;
if(HT == NULL){
printf("HT is NULL\n");
return -1;
}
if((p = (lklist)malloc(sizeof(listnode))) == NULL){
printf("malloc is failed\n");
return -1;
}
p->key = key;
p->value = key % N;
p->next = NULL;
q = &(HT->data[key % N]);
while(q->next && q->next->key < p->key){
q = q->next;
}
p->next = q->next;
q->next = p;
return 0;
}//哈希表插入关键字
查找关键字
编写hash.h
编写hash.c
lklist hash_search(hash *HT,data_t key){
lklist p;
if(HT == NULL){
printf("HT is NULL\n");
return NULL;
}
p = &(HT->data[key % N]);
while(p->next && p->next->key != key){
p = p->next;
}
if(p->next == NULL){
return NULL;
}else{
printf("found\n");
return p->next;
}
}//哈希表关键字查找
编写test.c
#include <stdio.h>
#include "hash.h"
int main(int argc, const char *argv[])
{
hash *HT;
int data[] ={4,52,35,19,53,92,76,43,59,42,11};
int i,key;
lklist r;
if((HT = hash_create()) == NULL){
return -1;
}
for(i = 0;i < sizeof(data)/sizeof(int);i++){
hash_insert(HT,data[i]);
}
printf("input:");
scanf("%d",&key);
r = hash_search(HT,key);
if(r == NULL){
printf("not found\n");
}else{
printf("found:%d %d\n",key,r->key);
}
return 0;
}
测试程序