定义
- 设记录表L=(R1 R2…其中Ri(L<=i<=n)为记录, 对给定的某个值k,
在表L中确定key= k的记录的过程,称为查找。 - 若表Lz中存在记录Ri de key = k,记为Ri.key,则查找成功,返回该记录在表L中的序号i(或Ri的地址),否者(查找失败)返回0(或空地址NULL )
查找方法有顺序查找、折半查找、分块查找、Hash表查找等
查找算法的优劣影响到计算的使用效率,应根据应用场合选择响应的查找算法。
对于查找算法,主要分析其T(n)(时间复杂度),一般以“平均查找长度”来衡量T(n)
平均查找长度ASL (Average Search Length) :对给定k,查找表L
中记录比较次数的期望值(或平均值),即:
Pi为查找Ri的概率。等概率情况下Pi=1/n; Ci为查找Ri时key的比较次数(或查找次数)。
哈希表
理想的查找方法是:对给定的k,不经任何比较便能获取所需的记录,其查找的时间复杂度为常数级0©。
这就要求在建立记录表的时候,确定记录的key与其存储地址之间的关系f,即使key与记录的存放地址H相对应:
当要查找key=k的记录时,通过关系就可得到相应记录的地址而获取记录,从而免去了key的比较过程。
这个关系f就是所谓的Hash函数(或称散列函数、杂凑函数) ,记为
H(key)。
它实际上是一个地址映象函数,其自变量为记录的key,函数值为记录的存储地址(或称Hash地址)。
不同的key可能得到同一个Hash地址,即当key;≠key,时, 可能有
H(key)=H(key2),此时称key 和key2为同义词。这种现象称为“冲突"
或“碰撞”,因为一个数据单位只可存放一条记录,
一般, 选取Hash函数只能做到使冲突尽可能少,却不能完全避免。这就要求在出现冲突之后,寻求适当的方法来解决冲突记录的存放问题。
一般, 选取Hash函数只能做到使冲突尽可能少,却不能完全避免。这就要求在出现冲突之后,寻求适当的方法来解决冲突记录的存放问题。
选取(或构造) Hash函数的方法很多,原则是尽可能将记录均匀分布,以减少冲突现象的发生。以下介绍几种常用的构造方法。
直接地址法
平方取中法
叠加法
保留除数法
随机函数法
保留除数法
又称质数除余法,设Hash表空间长度为m,选取-个不大于m的最大质数p,令:H(key)=key%p
表的填充因子a:0.7-0.8左右,(需要存储的的数据占存储空间的比例)
a = n / m (n :需要存储的数据个数)
链式hash的实现
hash.c
#include "hash.h"
hash* hash_creat(){
hash *HT;
if((HT = (hash *)malloc(sizeof(hash)))== NULL){
printf("HT malloc is failed \n");
return NULL;
}
memset(HT,0,sizeof(hash));
return HT;
}
int hash_insert(hash *HT, datatype key){
linklist p,q;
if(HT == NULL){
printf("HT is NULL\n");
return -1;
}
if((p = (linklist)malloc(sizeof(listnode))) == NULL){
printf("HT is NULL\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;
printf("key = %d\n",key);
return 0;
}
linklist hash_search(hash *HT,datatype key){
linklist 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("found2\n");
return p->next;
}
return NULL;
}
hash.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include “hash.h”
hash * hash_create() {
hash * HT;
if ((HT = (hash *)malloc(sizeof(hash))) == NULL) {
printf("malloc failed\n");
return NULL;
}
memset(HT, 0, sizeof(hash));
return HT;
}
int hash_insert(hash *HT, datatype key) {
linklist p, q;
if (HT == NULL) {
printf("HT is NULL\n");
return -1;
}
if ((p = (linklist)malloc(sizeof(listnode))) == NULL) {
printf("malloc 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;
}
linklist hash_search(hash *HT, datatype key) {
linklist 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;
}
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hash.h"
int test();
int main(){
printf("main start\n");
test();
return 0;
}
int test(){
printf("test start\n");
hash *HT;
datatype key;
int data[] = {24,35,74,29,36,96,48,55,6,13,62};
int i;
linklist r;
if((HT = hash_creat()) == NULL){
printf("HT is NULL\n");
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;
}