C语言数据结构与算法---散列表(哈希表)的查找

文章目录

  • 一. 散列表的基本概念
  • 二. 散列函数的构造方法
    • 1. 要求
    • 2. 方法
  • 三. 散列函数的实现

一. 散列表的基本概念

基本思想:记录的存储位置与关键字之间存在对应关系

优点:查找效率高
缺点:空间效率低

散列方法: 选取某个函数,依该函数按关键字计算元素的存储位置,并按此存放;查找时,由同一个函数对给定 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;
}

你可能感兴趣的:(数据结构与算法(C语言))