C语言数据结构与算法---散列表(哈希表)的查找
·
一. 散列表的基本概念
基本思想:记录的存储位置与关键字之间存在对应关系
优点:查找效率高
缺点:空间效率低
散列方法: 选取某个函数,依该函数按关键字计算元素的存储位置,并按此存放;查找时,由同一个函数对给定 k 计算地址,将 k 地址单元中有关元素关键码进行对比,确定查找是否成功。
散列函数: 散列方法中使用的转换函数
散列表:(按上述思想构成的表)根据关键码值(Key)直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
冲突: 不同的关键码映射到同一个散列地址
同义词:具有相同函数值的多个关键字
二. 散列函数的构造方法
1. 要求
1. 构造好的散列函数
- 所选函数尽可能简单,以便于提高转换效率
- 所选函数度关键码计算出的地址,应在散列地址集中致均匀分布,以减少空间浪费
2. 制定一个好的解决冲突的方案
- 查找时,如果从散列函数计算出的地址中查不到关键码,则应当依据解决冲突的规则,有规律的查询其他相关单元
2. 方法
1. 构造散列函数考虑的因素
- 执行速度
- 关键字长度
- 散列表大小
- 关键字的分布情况
- 查找频率
2. 根据元素集合的特性构造
- 要求一:n 个数据原仅占用 n 个地址,虽然散列查找是以空间换时间,但仍希望散列的地址空间尽量小
- 要求二:无论用什么方法储存,目的都是尽量均匀地存放元素,以避免冲突
3. 解决冲突的办法:
- 直接定址法
(取关键字的某个线性函数值为散列地址:f (key) = a*key + b )
简单、均匀也不会有冲突但需要事先知道关键字的排布,适合表较小且连续的情况 - 数字分析法
- 平方取中法
- 折叠法
- 除留取余法
Hash(key) = key % p (p 是整数),设表长为 m ,取 p <= m 且为质数 - 随机数法
三. 散列函数的实现
结构:
#define MAXSIZE 1000
#define NULLKEY -65535
typedef struct
{
int* elem; //数据元素存储基址,数组
int size; //元素个数
}HashTable;
int m = 0;//散列表表长
散列表的创建:
void IniHashTable(HashTable* H)
{
int i;
m = MAXSIZE;
H->size = m;
H->elem = (int*)malloc(m* sizeof(int));
for (i = 0; i < m; i++)
{
H->elem[i] = NULLKEY;
}
}
散列函数:
根据不同的情况改变算法
int Hash(int key)
{
return key % m; //除留取余法
}
插入元素:
void InsertHash(HashTable* H, int key)
{
int addr = Hash(key); //求散列地址
while (H->elem[addr] != NULLKEY) //不为空则冲突
{
addr = (addr + 1) % m; //开放地址法的线性探测
}
H->elem[addr] = key; //发现有空位后插入
}
查找元素:
int Search(HashTable* H, int key)
{
int addr = Hash(key); //求散列地址
while (H->elem[addr] != key) //不为空则冲突
{
addr = (addr + 1) % m; //开放地址法的线性探测
if (H->elem[addr] == NULLKEY || addr == Hash(key))
{
return false;
}
}
return true;
}
更多推荐
所有评论(0)