您的位置:首页 > 理论基础 > 数据结构算法

数据结构与算法 ---- 哈希表查找

2020-08-10 15:05 766 查看

1、哈希查找也叫散列查找,整个散列查找过程大概分两步

(1)在存储时通过散列函数计算记录的散列地址,并按此散列地址存储该记录。
(2)当查找时,一样通过散列函数计算记录的散列地址,然后访问散列地址的记录。

散列函数的构造方法

(1)直接定址法

取关键字的某个线性函数值为散列地址
f(key) = a × key +b
需要事先知道关键字的分布情况,适合查找表较小且连续的情况。

(2)数字分析法
使用关键字的一部分来计算散列存储的位置。
适合处理关键字位数较大的情况。

(3)平方取中法
假设关键字是1234,那它的平方就是1522756,再抽取中间的3位就是277
适合不知道关键字的分布,而位数又不是很大的情况。

(4)折叠法

将关键字从左到右分割成位数相等的几个部分,然后将这几部分叠加求和,并按散列表表长,取后几位作为散列地址。比如关键字是9876543210,散列表表长为三位,我们将它分成四组,987|654|321|0,然后将他们叠加求和等于1962,再求后三位得到散列地址962。
适合事先不知道关键字的分布,关键字位数叫多的情况。

(5)除留余数法

此方法为最常用的构造散列函数的方法。

处理冲突散列的方法

(1)开放定址法

开放定址法就是一旦出现了冲突,就去寻找下一个空的散列地址,只要散列地址够大,空的散列地址总会被找到。

(2)再散列函数法

事先准备多几个散列函数

这里的RH就是不同的散列函数

(3)链地址法

将所有同关键字的记录存储在一个单链表中,称这种表为同义词子表,在散列表中只存储所有同义词子表的头指针。

2、散列表查找算法实现

(1)首先定义一个散列表结构
(2)对散列表进行初始化
(3)对散列表进行插入操作
(4)根据不同的情况选择散列函数和处理冲突的方法(这里选用的是除留余数法和开放定址法)

#include "stdio.h"
#include "stdlib.h"

#define HASHSIZE 10 // 定义散列表长度
#define NULLKEY -32768

typedef struct
{
int *elem; // 数据元素存储地址,动态分配数组
int count; //  当前数据元素个数
}HashTable;

int m = 0;

int Init(HashTable *H)
{
int i;

m = HASHSIZE;
H->elem = (int *)malloc(m * sizeof(int)); //分配内存
H->count = m;
for (i = 0; i<m; i++)
{
H->elem[i] = NULLKEY;
}
return 1;
}

int Hash(int k)
{
return k % m;//除留余数法
}

void Insert(HashTable *H, int k)
{
int addr = Hash(k);
while (H->elem[addr] != NULLKEY)
{
addr = (addr+1) % m;//开放定址法
}
H->elem[addr] = k;
}

int Search(HashTable *H, int k)
{
int addr = Hash(k); //求哈希地址

while (H->elem[addr] != k)//开放定址法解决冲突
{
addr = (addr+1) % m;

if (H->elem[addr] == NULLKEY || addr == Hash(k))
return -1;
}
return addr;
}

void Result(HashTable *H)//散列表元素显示
{
int i;
for (i = 0; i<H->count; i++)
{
printf("%d ", H->elem[i]);
}
printf("\n");
}

void main()
{
int i, j, addr;
HashTable H;
int arr[HASHSIZE] = { NULL };

Init(&H);

printf("输入关键字集合:");
for (i = 0; i<HASHSIZE; i++)
{
scanf_s("%d", &arr[i]);
Insert(&H, arr[i]);
}
Result(&H);

printf("输入需要查找的元素:");
scanf_s("%d", &j);
addr = Search(&H, j);
if (addr == -1)
printf("元素不存在\n");
else
printf("%d元素在表中的位置是:%d\n", j,addr);
}

时间复杂度为O(1)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: