一、散列表基本概念
散列表又称哈希表,是一种以关键字直接寻址为核心的高效查找结构。顺序查找、折半查找、二叉树、B 树等查找方式,都需要通过关键字多次比较才能确定元素位置,查找效率依赖比较次数;而散列表完全打破 "比较式查找" 逻辑,通过散列函数(哈希函数),直接将元素的关键字映射为数组下标,一步定位存储位置,实现近似 O (1) 的平均时间复杂度查找,是所有查找结构中效率最高的类型。
散列表的核心思想:位置 = H (key)。以一片连续存储空间(数组)作为基础表,利用哈希函数计算关键字对应的存储地址,将元素直接存入该地址;查找时,对目标关键字执行相同哈希运算,直接访问对应地址读取元素,最大限度减少查找开销。理想状态下,每个关键字对应唯一地址,无需任何比较,存取瞬间完成。
二、散列函数与设计原则
散列函数是散列表的核心,作用是将任意长度、任意形式的关键字,压缩映射为合法的数组下标。优秀的散列函数必须满足三大原则:计算简单高效、地址分布均匀、尽量减少冲突。
常用散列函数:
除留余数法(考试最常考)
公式:H(key)=key mod p
要求:p 取小于表长的质数或无公因数合数,能最大程度避免地址集中堆积,分布均匀,计算简单,适用性最强。
直接定址法
直接以关键字本身或线性运算结果作为地址,适合关键字连续分布的场景,无冲突,适用范围窄。
数字分析法
提取关键字中分布随机的数位作为地址,适用于已知规律的固定关键字集合。
平方取中法
对关键字平方后截取中间几位作为地址,通过平方打乱原始规律,分散地址。
三、哈希冲突的本质
哈希冲突:不同关键字,经过哈希函数计算,得到相同存储地址,即
key 1=key 2,但 H(key 1)=H(key 2 )
冲突无法完全避免:关键字范围无限,散列表存储空间有限,有限地址映射无限关键字,必然存在碰撞。因此,散列表设计分为两大核心:合理的哈希函数 + 完善的冲突处理方法,二者缺一不可,也是散列表学习的重点难点。
四、两大冲突解决方法
- 开放定址法
原理:当目标地址被占用时,按照固定规则向后探测,寻找表中空闲位置存入元素,所有数据全部存储在原始散列表数组内。常见探测方式:
线性探测:冲突时依次向后 + 1 寻址,简单易实现,但易产生堆积现象,连续位置被占用,降低查找效率;
二次探测:以平方步长跳跃寻址,缓解线性堆积;
双重哈希:使用第二个哈希函数计算步长,地址分布更均匀。
开放定址法特点:结构紧凑、无需额外空间,但删除元素不能直接清空(会截断探测路径),只能做删除标记,操作受限。
- 链地址法(拉链法)
原理:散列表每个数组单元不直接存数据,而是作为单链表头结点;所有哈希地址相同的元素,全部挂载在同一条链表中。发生冲突时,直接追加到链表尾部,互不干扰。
特点:完全杜绝堆积问题,插入删除灵活,仅冲突位置消耗链式空间;查找时先定位数组下标,再遍历短链表,平均效率极高,是实际工程中最常用的方式。
五、散列表的查找过程
计算目标关键字哈希地址;
访问该地址单元,若关键字相等,查找成功;
若不相等或存在冲突,根据冲突解决策略继续探测 / 遍历链表;
遍历至空闲位置或链表末尾仍无匹配元素,判定查找失败。
散列表查找效率不依赖元素总数,只取决于:哈希函数优劣、冲突处理方式、装填因子。
六、装填因子
装填因子公式:元素个数散列表长度α 越小:数组空闲单元多,冲突概率低,查找越快,空间利用率低;α越大:空间利用率高,元素拥挤,冲突剧增,查找效率急剧下降。
一般规范:散列表装填因子控制在 0.6~0.9 之间,平衡空间与效率。开放定址法因易堆积,装填因子需更小;链地址法容忍度更高,可适当增大。
七、散列表的优缺点总结
优点
平均查找、插入、删除时间复杂度 O(1),效率碾压顺序查找、折半查找、树形查找;
寻址逻辑简单,无需关键字多次比较;
适合海量数据高频增删、快速检索场景。
缺点
无法支持有序遍历、范围查询,仅适合精准匹配;
哈希冲突会退化效率,最坏情况退化为线性查找;
存储空间存在冗余,开放定址法利用率受装填因子限制;
关键字必须可哈希,部分复杂数据类型映射困难。
八、整体总结
散列表是一种直接寻址的高效查找结构,区别于传统比较类查找,依靠哈希函数实现关键字到存储地址的直接映射。哈希冲突是固有问题,通过开放定址法、链地址法可有效解决;装填因子直接决定整体性能。在计算机系统中,哈希表广泛应用于缓存、字典、数据库索引、集合去重等场景,是数据结构中实用性最强的结构之一。虽然无法实现有序操作,但在精准查询场景下,无可替代。