首页 > 其他 > 详细

散列表

时间:2020-03-30 21:37:17      阅读:71      评论:0      收藏:0      [点我收藏+]

散列表(Hash table,也叫哈希表)是一种通过将键(key)映射为值(value)从而实现快速查找的数据结构。

也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。
 
一个通俗的例子是,为了查找电话簿中某人的号码,可以创建一个按照人名首字母顺序排列的表(即建立人名 x 到首字母f(x)的一个函数关系),在首字母为W的表中查找“王”姓的电话号码,显然比直接查找就要快得多。这里使用人名作为关键字,“取首字母”是这个例子中散列函数的函数法则f(),存放首字母的表对应散列表。关键字和函数法则理论上可以任意确定。
基本概念
  • 若关键字为 k,则其值存放在f(k)的存储位置上。由此,不需比较便可直接取得所查记录。称这个对应关系 f 为散列函数,按这个思想建立的表为散列表。
  • 对不同的关键字k可能得到同一散列地址,即k1!=k2,而f(k1)=f(k2),这种现象称为冲突(或碰撞,英语:Collision)。具有相同函数值的关键字对该散列函数来说称做同义词。综上所述,根据散列函数f(k)和处理冲突的方法将一组关键字映射到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“像”作为记录在表中的存储位置,这种表便称为散列表,这一映射过程称为散列造表或散列,所得的存储位置称散列地址。
  • 若对于关键字集合中的任一个关键字,经散列函数映象到地址集合中任何一个地址的概率是相等的,则称此类散列函数为均匀散列函数(Uniform Hash function),这就使关键字经过散列函数得到一个“随机的地址”,从而减少冲突。

 

实现散列表的方法有很多种,在此介绍一种简单、常见的实现方式。

我们使用一个链表构成的数组与一个散列函数来实现散列表。当插入键(字符串或几乎其他所有数据类型)和值时,我们按照如下方法操作。

(1)首先,计算键的散列值。键的散列值通常为int或者long型。请注意,不同的键可能有相同的散列值。

(2)之后,将散列值映射为数组的索引。可以使用类似于hash(key) % array_length 的方式完成这一步骤。

(3)此数组索引处存储的元素是一系列由键和值为元素组成的链表。将映射到此索引的键和值存储在这里。由于存在冲突,我们必须使用链表。

 

时间复杂度

如果冲突发生很多次,最坏的情况下的时间复杂度是O(N) ,其中N是键的数量。

但是我们通常假设一个不错的实现

 

构造散列函数的方法

散列函数能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快定位。

  • 直接定址法:取关键字或关键字的某个线性函数值为散列地址。即hash(k)=k 或hash(k)=ak+b, 其中ab为常数(这种散列函数叫做自身函数)
  • 数字分析法:假设关键字是以r为基的数,并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。
  • 平方取中法:取关键字平方后的中间几位为哈希地址。通常在选定哈希函数时不一定能知道关键字的全部情况,取其中的哪几位也不一定合适,而一个数平方后的中间几位数和数的每一位都相关,由此使随机分布的关键字得到的哈希地址也是随机的。取的位数由表长决定。
  • 折叠法:将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址。
  • 除留余数法:取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址。即 hash(k)=k mod p, p<=m。不仅可以对关键字直接取模,也可在折叠法、平方取中法等运算之后取模。对p的选择很重要,一般取素数或m,若p选择不好,容易产生冲突。

 

散列表

原文:https://www.cnblogs.com/stringarray/p/12600944.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!