【算法】- 查找 - 散列表查询(哈希表)

文章目录


前言

散列技术:在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key)
哈希表:采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表


一、哈希表的思想

创建哈希表结构体:创建哈希表数据结构HashTable,用来存放散列地址和该散列表存放的数据个数。

cpp 复制代码
//创建哈希表结构
typedef struct HashTable
{
	int count;//记录哈希表中元素个数
	int* elem;//创建哈希表
}HashTable;

初始化哈希表:初始化哈希表主要还是动态开辟存放数据的数组,再初始化count的个数,并将哈希表中的值赋值为空,这里用NULLKEY标志来表示为空。

cpp 复制代码
//初始化哈希表
void InitHashTable(HashTable* HT)
{
	int i;
	m = MAXSIZE;
	//动态开辟内存
	HT->elem = (int*)malloc(m * sizeof(int));
	HT->count = MAXSIZE;
	for (i = 0; i < m; i++)
	{
		HT->elem[i] = NULLKEY;
	}

}

插入哈希表:插入哈希表,通过哈希函数Hash来计算出散列地址,判断该地址是否为NULLKEY,是的话就直接插入,不是的话就将散列地址赋值为下一个地址,继续判断,直到找到了就执行插入操作。

cpp 复制代码
//哈希表的插入
void InsertHashTable(HashTable* HT, int key)
{
	int addr;
	addr = Hash(key);//求散列地址
	while (HT->elem[addr] != NULLKEY)
	{
		addr = (addr + 1) % m;
	}
	HT->elem[addr] = key;
}

查询哈希表:先通过哈希函数获得散列地址,再通过散列地址查询访问。在查询时如果通过散列地址找到的值和key值不等,则散列地址找到下一个操作,直到循环一圈或则通过地址找到的地址为NULLKEY就返回查找失败,成功则返回查找成功。

cpp 复制代码
//哈希表查找
int SearchHash(HashTable HT, int key)
{
	int addr = Hash(key);
	int begin = addr;
	while (HT.elem[addr] != key)
	{
		addr = (addr + 1) % m;
		if (HT.elem[addr] == NULLKEY || addr == begin)
			return 0;
	}
	return 1;
}

二、哈希表

cpp 复制代码
#define MAXSIZE 12
#define NULLKEY -32768
#include <iostream>
using namespace std;

//哈希表查找

//创建哈希表结构
typedef struct HashTable
{
	int count;//记录哈希表中元素个数
	int* elem;//创建哈希表
}HashTable;

int m = 0;

//初始化哈希表
void InitHashTable(HashTable* HT)
{
	int i;
	m = MAXSIZE;
	//动态开辟内存
	HT->elem = (int*)malloc(m * sizeof(int));
	HT->count = MAXSIZE;
	for (i = 0; i < m; i++)
	{
		HT->elem[i] = NULLKEY;
	}

}

//散列函数
int Hash(int key)
{
	return key % m;
}

//哈希表的插入
void InsertHashTable(HashTable* HT, int key)
{
	int addr;
	addr = Hash(key);//求散列地址
	while (HT->elem[addr] != NULLKEY)
	{
		addr = (addr + 1) % m;
	}
	HT->elem[addr] = key;
}

//哈希表查找
int SearchHash(HashTable HT, int key)
{
	int addr = Hash(key);
	int begin = addr;
	while (HT.elem[addr] != key)
	{
		addr = (addr + 1) % m;
		if (HT.elem[addr] == NULLKEY || addr == begin)
			return 0;
	}
	return 1;
}

int main()
{
	int i,result,key;
	HashTable HT;
	int arr[MAXSIZE] = { 12,67,56,16,25,37,22,29,15,47,48,34 };
	//初始化哈希表
	InitHashTable(&HT);
	key = 39;
	for (i = 0; i < m; i++)
	{
		InsertHashTable(&HT, arr[i]);
	}
	result = SearchHash(HT,key);

	if (result)
		printf("查找 %d 成功 \n", key);
	else
		printf("查找 %d 失败。\n", key);

	for (i = 0; i < m; i++)
	{
		key = arr[i];
		result = SearchHash(HT, key);
		if (result)
			printf("查找 %d 成功 \n", key);
		else
			printf("查找 %d 失败。\n", key);
	}
	return 0;
}

总结

散列表查找的效率是最高的,因为它的时间复杂度为O(1)。可惜在实际情况中,会产生冲突(不同的数据在同一地址的情况),但散列表查询还是非常值得的。

相关推荐
djarmy2 小时前
MAIN.c(1): warning C318: can’t open file ‘STC8G.H’ 报错 解决 分析
c语言·开发语言·mongodb
李永奉4 小时前
中科蓝讯SDK开发-BT893x 面条耳机连接vivo手机后连接APP端,最后手机端设置页面手动断开蓝牙连接,此时耳机端假断开
c语言·开发语言·嵌入式硬件·物联网·智能手机·电脑
2601_967760784 小时前
2026年PDF压缩与页码添加工具技术实测:性能、算法与本地化适配深度对比
算法·pdf
不会就选b5 小时前
算法日常・每日刷题--<贪心>7
数据结构·算法·leetcode
moonrailgun5 小时前
用 Node.js 复刻 Codex Astra 的终端星光
前端·javascript·算法
罗西的思考5 小时前
[Agent Memory / 强化学习] MemPO源码学习笔记 ---(1)--- 总体
人工智能·算法·机器学习
lvwangshu6 小时前
图论:LCA、树的直径、树的重心、二分图与 Tarjan 缩点
算法·图论
爱吃苹果的日记本6 小时前
数据结构第一课
c语言·数据结构·数据库·学习·c#
302wanger7 小时前
干与湿:AI 拿走脑力之后,人剩下什么
算法
计算机编程-吉哥8 小时前
脑肿瘤MRI智能识别系统:基于深度学习的像素级脑肿瘤语义分割平台【计算机毕业设计选题推荐】
人工智能·python·深度学习·算法·毕业设计·课程设计·大数据毕业设计选题推荐