【算法】哈希表介绍 | 哈希表的链式地址法代码实现(C/C++)

创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡>𖥦<)!!
主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步!
更多算法分析与设计知识专栏:算法分析🔥
给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ

在这里插入图片描述


一、哈希表介绍

哈希表(HashMap、unordered_map)又称为散列表,是一种可以对已经存储的数据进行快速查找的数据结构,它可以根据键(Key)值直接进行访问。
举几个栗子:

在电话簿中,每个电话号码对应一个名字,在查找某个人的电话号码时根据姓名即可进行快速查找,这实际上就利用了哈希思想,键是电话号码,值是名字。

如果要对某字符串进行反复搜索的操作,每次都遍历字符串效率太低,使用哈希思想将字符进行分组(例如分为256组),然后将每个字符按照规则存储(将字符串中的每个字符通过哈希函数进行映射),在后续对字符查找时即可通过关键字key进行快速查找到字符的存储位置,可以在常数时间内进行查找、插入和删除操作。

哈希表主要利用了分组的思想,采用散列(映射)技术

哈希表的增删查时间复杂度都是O(1)

散列技术

散列技术是一种可以用于快速查找的存储技术,通过散列函数(哈希函数)将一组数据按照特征建立对应关系。查找时只需要根据对应关系找到关键字key的映射,映射到内存中的一个位置。

二、哈希表的创建

1.确定哈希函数

哈希函数可以根据数据的情况不同进行不同的设计,最好要满足容易计算并且根据数据特征均匀分布

例如:
按照数据类型分组:

  • 将字符按照ASCLL码分为256组
  • 将班级同学按照省份分组

取余法:
通过将关键字除以一个素数取余数作为哈希表中的位置

p = key%m

2.哈希冲突的解决方案

在理想情况下,不同的键值能够映射到不同的索引,但是在实际中,可能存在不同的键值映射到相同的索引的情况,这种情况称为哈希冲突

举个栗子:
如果现在要存放Tianxi这个字符串,通过对取余法存入到哈希表中,如下图所示:
T i a n 都依次正常存入了,到字符x时发现索引0已经被字符T占用了:image.png

这就是不同的键映射到相同的索引,即哈希冲突,要解决哈希冲突有例如下面的方法:

i.开放定址法

当发生冲突时,使用某种探查技术在散列表中形成一个探查序列
可以分为:

  • 线性探测

发生冲突时,线性探测会按照步长依次探测下一个位置,直到找到空位或找到目标元素为止

  • 线性补偿探测

线性补偿探测是线性探测的一种改进版本。它同样按照一定的步长探测哈希表中的下一个位置,但是当连续探测若干个位置都发生冲突时,它会增加步长的大小(每次增加一定大小),能够加快探测速度

沿此序列逐个单元地查找,直到找到一个开放的地址为止,例如可以将上面的x存入key = 5中
image.png

ii.链式地址法

拉链法中,哈希表中每个键对应的值都为一个链表的头节点,当发生哈希冲突时,新的键值对会被插入到相应的链表中。
如下图所示,字符x发生哈希冲突时将其加入到链表头节点中:
image.png

当哈希冲突较为频繁时,链表可能会变得很长,导致查找效率下降


链式地址取余法代码实现(C/C++)

  • 1.申请表头 表头初始化
  • 2.取余获得索引位置 元素入表
  • 3.节点空间申请 头添加
#define MOD 6

typedef struct Node
{
	int val;
	struct Node* pNextNode;
}ListNode;

ListNode** createHash(int arr[], int length)
{
	if (arr == NULL || length <= 0) return NULL;
	//申请表头
	ListNode** pHash = (ListNode**)malloc(sizeof(ListNode*) * MOD);
	memset(pHash, 0, sizeof(ListNode*) * MOD);
	//元素入表
	int nIndex;
	for (int i = 0; i < length; i++)
	{
		//获得索引位置
		nIndex = arr[i] % MOD;
		//节点空间申请
		ListNode* pTempNode = NULL;
		pTempNode = (ListNode*)malloc(sizeof(ListNode));
		pTempNode->val = arr[i];

		//头添加
		pTempNode->pNextNode = pHash[nIndex];
		pHash[nIndex] = pTempNode;
	}
	return pHash;
}

三、哈希表的使用

  • 1.取余获得索引位置
  • 2.遍历链表
void HashSearch(ListNode** pHash, int target)
{
	if (pHash == NULL)return;
	int nIndex = target % MOD;
	ListNode* pTempNode = pHash[nIndex];
	while (pTempNode)
	{
		if (pTempNode->val == target)
		{
			printf("success!\n");
			return;
		}
		else
		{
			pTempNode = pTempNode->pNextNode;
		}
	}
	printf("fail!\n");
	return;
}

测试代码:

110查询成功,100查询失败

image.png
在这里插入图片描述

大家的点赞、收藏、关注将是我更新的最大动力! 欢迎留言或私信建议或问题。
大家的支持和反馈对我来说意义重大,我会继续不断努力提供有价值的内容!如果本文哪里有错误的地方还请大家多多指出(●'◡'●)
### IntelliJ IDEA 中通义灵码 AI 功能介绍 IntelliJ IDEA 提供了一系列强大的工具来增强开发体验,其中包括与通义灵码 AI 相关的功能。这些功能可以帮助开发者更高效地编写代码并提高生产力。 #### 安装通义灵码插件 为了使用通义灵码的相关特性,在 IntelliJ IDEA 中需要先安装对应的插件: 1. 打开 **Settings/Preferences** 对话框 (Ctrl+Alt+S 或 Cmd+, on macOS)。 2. 导航到 `Plugins` 页面[^1]。 3. 在 Marketplace 中搜索 "通义灵码" 并点击安装按钮。 4. 完成安装后重启 IDE 使更改生效。 #### 配置通义灵码服务 成功安装插件之后,还需要配置通义灵码的服务连接信息以便正常使用其提供的各项能力: - 进入设置中的 `Tools | Qwen Coding Assistant` 菜单项[^2]。 - 填写 API Key 和其他必要的认证参数。 - 测试连接以确认配置无误。 #### 使用通义灵码辅助编程 一旦完成上述准备工作,就可以利用通义灵码来进行智能编码支持了。具体操作如下所示: ##### 自动补全代码片段 当输入部分语句时,IDE 将自动提示可能的后续逻辑,并允许一键插入完整的实现方案[^3]。 ```java // 输入 while 循环条件前半部分... while (!list.isEmpty()) { // 激活建议列表选择合适的循环体内容 } ``` ##### 解释现有代码含义 选中某段复杂的表达式或函数调用,右键菜单里会有选项可以请求通义灵码解析这段代码的作用以及优化意见。 ##### 生产测试案例 对于已有的业务逻辑模块,借助于通义灵码能够快速生成单元测试框架及初始断言集,减少手动构建的成本。 ```python def test_addition(): result = add(2, 3) assert result == 5, f"Expected 5 but got {result}" ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天喜Studio

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值