【数据结构与算法】->数据结构->散列表(中)->工业级散列表的设计

本文深入探讨了工业级散列表的设计,包括如何设计散列函数以减少冲突,处理装载因子过大,避免低效扩容策略,以及选择冲突解决方法。文章强调了散列函数的随机性和均匀分布的重要性,动态扩容的均摊成本,以及链表法和开放寻址法的优缺点。通过分析HashMap的实现,阐述了初始大小、装载因子、红黑树优化等关键点,为设计高效稳定的散列表提供了指导。
摘要由CSDN通过智能技术生成

Ⅰ 前言

在散列表(上)中我介绍了散列表的思想和基本内容,我们知道,散列表的查询效率并不能笼统地说成是 O(1),它和散列函数、装载因子、散列冲突等都有关系。如果散列函数设计得不好,或者装载因子过高,都可能导致散列冲突发生的概率升高,查询效率下降。

在极端情况下,有些恶意的攻击者,还有可能通过精心构造的数据,使得所有的数据经过散列函数之后,都散列到同一个槽里。如果我们使用的是基于链表的冲突解决方法,这个时候散列表就会退化成链表,查询的时间复杂度就从 O(1) 退化到 O(n)。

如果散列表中有 10 万个数据,退化后的散列表查询的效率就下降了 10 万倍。如果原来运行 100 次查询只需要 0.1 秒,现在就需要 1 万秒。这样就有可能因为查询操作消耗大量 CPU 或者线程资源,导致系统无法响应其他请求,从而达到拒绝服务攻击(DoS)的目的,这也就是散列表碰撞攻击的基本原理。

所以这篇文章就主要讲解一下工业级散列表的设计,避免在散列冲突的情况下,散列表性能的急剧下降,并且抵抗散列碰撞攻击。

【数据结构与算法】->数据结构->散列表(上)->散列表的思想&散列冲突的解决

Ⅱ 如何设计散列函数

散列函数的好坏,决定了散列表冲突的概率大小,也直接决定了散列表的性能。那什么才是好的散列表?主要有以下几点。

第一,散列函数的设计不能太复杂。过于复杂的散列函数,势必会消耗很多计算时间,也间接地影响到散列表的性能。

第二,散列函数生成的值要尽可能随机并且均匀分布,这样才能避免或者最小化散列冲突,而且即便出现散列冲突,散列到每个槽里的数据也会比较平均,不会出现某个槽内数据特别多的情况。

在实际开发中,我们还需要综合考虑各种因素。这些因素有关键字的长度、特点、分布、还有散列表的大小等。散列函数各式各样,我举几个比较常用的简单散列函数的设计方法。

第一种就是第一节里我写过的学生运动会的例子,我们通过分析参赛编号的特征,把编号后两位作为散列值。我们还可以用类似的散列函数处理手机号码,因为手机号码前几位重复的可能性很大,但是后几位比较随机,所以我们可以取手机号的后四位作为散列值。这种散列函数的设计方法,我们一般叫作 数据分析法

第二种就是 Word 的单词拼写检查功能,这里面的散列函数,我们可以这样设计:将单词中每个字母的 ASCII 码值进位相加,然后再和散列表的大小求余、取模,作为散列值。比如,英语单词 “one”,我们转化出来的散列值就是下面这样👇
在这里插入图片描述
实际上,散列函数的设计方法还有很多,比如直接寻址法、平方取中法、折叠法、随机数法等,大家可以自行去了解。

Ⅲ 如何处理装载因子过大

装载因子越大,说明散列表中的元素越多,空闲位置越少,散列冲突的概率就越大。不仅插入数据的过程要多次寻址或者拉很长的链,查找的过程也会因此变得很慢。

对于没有频繁插入和删除的静态数据集合来说,我们很容易根据数据的特点、分布等,设计出完美的、极少冲突的散列函数,因为毕竟之前数据都是已知的。

对于动态散列表来说,数据集合是频繁变动的,我们事先无法预估将要加入的数据个数,所以我们也无法事先申请一个足够大的散列表。随着数据慢慢加入,装载因子就会慢慢变大。当装载因子大到一定程度之后,散列冲突就会变得不可接受。这个时候,我们就需要进行动态扩容,申请一个更大的散列表,将数据都搬移到这个新散列表中。

假设每次扩容我们都申请一个原来散列表大小两倍的空间,如果原来散列表的装载因子是 0.8,那经过扩容以后,新散列表的装载因子就下降为原来的一半,变成了 0.4。

针对数组的扩容,数据搬移操作比较简单。但是,针对散列表的扩容,数据搬移操作要复杂很多。因为散列表的大小变了。数据的存储位置也变了,所以我们需要通过散列函数重新计算每个数

湖北工业大学的836《数据结构》科目是一个重要的专业基础课程考试内容,旨在评估考生对数据结构的基本原理、算法设计及分析能力的理解程度。虽然具体的历年试题内容可能会有所变动,并随教学大纲的不同而有所不同,但是从一般的数据结构课程来看,这类考试通常涵盖以下几个方面: ### 主要考察内容 1. **基本数据结构**:如数组、链表、栈、队列等。题目可能涉及这些数据结构的操作、应用和性能分析。 2. **高数据结构**:包括树(二叉树、AVL树、B树等)、图、堆、散列表等。此类数据结构常用于解决特定的问题,如查找、排序和优化问题。 3. **算法设计与分析**:常见的算法有排序(冒泡排序、快速排序、归并排序)、查找(顺序查找、二分查找)、动态规划、贪心算法、回溯等。题目通常会要求设计算法解决实际问题,以及分析算法的时间复杂度和空间复杂度。 4. **问题解决技能**:通过设计程序解决给定的实际问题或理论问题,需要具备良好的逻辑思维能力和编码实践能力。 ### 准备建议 - **系统学习教材**:首先,熟悉教材的内容,了解每种数据结构的特点、操作方及其应用场景。 - **做练习题**:通过做大量的习题和历年真题来巩固知识点,提高解题速度和准确率。 - **深入理解算法分析**:掌握各种算法的分析技巧,能熟练地计算时间复杂度和空间复杂度。 - **复习常见面试题**:由于很多院校的研究生入学考试题目会参考计算机科学领域的经典面试题,因此提前准备一些经典面试题也是很有帮助的。 - **参与讨论和组队学习**:与其他同学一起讨论难题,共享资源和经验可以极大地提升学习效率。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值