IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 009.查找手机电话簿【散列表】 -> 正文阅读

[数据结构与算法]009.查找手机电话簿【散列表】

1. 散列表

顺序存储的结构类型需要一个一个地按顺序访问元素,当总量很大且我们所要访问的元素比较靠后时,顺序存储的结构类型性能就比较低。而散列表是一种空间换时间的存储结构,也是提升效率的一种比较常用的方式。由于它所需空间太大,所以通常需要使用者在“效率”和“占空间大小”二者之间权衡。

1.1 什么是散列表

利用字典查找汉字的过程就是散列表的思想。散列表,又叫作哈希表,是通过给定的关键字直接访问到具体对应值的数据结构。简单的说,就是把关键字映射到一个表中的位置来直接访问记录,以加快访问速度。通常把关键字称为Key,把对应的记录称为Value,把存放记录的数组叫作散列表。

1.2 散列函数

散列函数又称为哈希函数,给定一个输入 x (任何数据),它都会算出相应的输出 H(x)(一般为数字)。散列表具有如下特征:

  • 输入 x 可以是任意字符串
  • 输出结果 H(x) 的长度是固定的
  • 计算 H(x) 的过程是高效的
  • 尽可能输入一个 x 就能得出唯一的 H(x)

散列函数之所以最终会输出数字,是因为散列函数计算出的数字需要用来做索引。

1.3 解决散列表的冲突

1.3.1 开放定址法

开放定址法就是当数据的散列地址遇到冲突,系统就会去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,系统将记录存入该散列地址。

H(i)=(H(key)+d(i)) MOD m
  • key: 要存储的数据
  • H(key):散列函数
  • m:散列表长度
  • d(i):增长序列
  • MOD:%

其中,d(i) 有三种取法:

  • 线性探测法:d(i)=1,2,3,4,…,m-1
  • 平方探测法:d(i)=12,22,32,42,… 或 d(i)=-12,-22,-32,-42,…
  • 伪随机探测法:d(i)=伪随机数序列

线性探测法:以线性的方式向散列表后面寻找空的存储位置,一旦找到位置就将数据放进去。

平方探测法:线性探测法有一个缺点,就是相类似的键值经常会聚集在一起。当多个数据键值类似时,它们就会聚集,会产生冲突。为了防止这样的事情发生,在线性的基础上做了改进,使用平方探测法:d(i)=12,22,32,…

伪随机探测法:伪随机探测法指 d(i) 采用随机函数计算得到的。如果设置的随机种子相同,则不断调用随机数可以生成不会重复的数列。在查找时,用同样的随机种子每次得到的数据是相同的,相同的数据产生相同的d(i) ,相同的 d(i) 就会得到相同的散列地址。

1.3.2 链地址法

链地址法就是将经过散列函数得到的相同的数值(索引值)放在同一个位置,就在这个位置存储为一个单链表。用专业术语描述就是将相同的键映射到同一个位置。散列表中只存储头指针,相同的数据放到同义词子表。

对于可能会造成很多冲突的散列函数来说,链地址法提供了绝不会出现找不到地址的保障,但这种方法也带来了缺点:查找数据时增加了遍历单链表的时间。

1.3.3 再散列函数法

再散列函数法就是一开始就先设置一些散列函数(比如除留取余、平方取中、折叠等等),如果使用第一种散列函数出现冲突就改用第二种,如果第二种也出现冲突就改用第三种,一直到没有冲突为止。

虽然再散列函数法不易产生聚集,但是从步骤上看,明显增加了计算时间。

1.3.4 建立公共溢出区法

建立公共溢出区法就是将散列表分为基本表和溢出表两部分,凡是与基本表发生冲突的,都存放在溢出表中。

这种方法在查找数据时,在散列函数计算出索引位置后,先与基本表的相应位置做比较,如果相等,就查找成功;如果不相等,就到溢出表中进行顺序查找。就相对查询而言,在少量数据冲突的情况下,公共溢出区法对查找数据的速度来说是比较快的。

1.3.5 解决冲突方法的比较

方法优点缺点
线性探测法简单易懂容易造成大量元素在相邻的散列地址上聚集,降低查询效率
平方探测法避免出现聚集问题不能探测到散列表上所有的单元,但至少探测到一半的单元
伪随机探测法随机产生散列地址用同样的随机种子,将得到相同的数列
链地址法1. 对于记录总数频繁可变的情况,处理的比较好
2. 记录存储在结点时,动态分配内存,不浪费内存
3. 删除记录,处理方便
存储记录随机分布,散列表跳转访问速度慢
在散列函数法不易产生聚集增加了计算时间
建立公共溢出区冲突数据少时,查询速度快多增加了一个散列表

元素少,用开放定址法,冲突少,速度快;元素多,用链地址法。

1.4 散列表的性能

负载因子:也称为填装因子,负载因子度量的是散列表中有多少位置是空的。

a=n/m
  • a:负载因子
  • n:散列表中键值的个数
  • m:散列表的大小

负载因子值=1,说明每个元素都有自己的位置。
负载因子值<1,说明还有空位置。
负载因子值>1,说明位置不足,需要调整长度,增加散列表中的位置。

总结:负载因子越低,发生冲突的可能性越小,散列表的性能越高。

时间性能:在理想的情况下,散列表执行各种操作的时间都是 O(1),也就是常量时间。即使有 1 亿条数据,它的运行时间也是相同的,所以说在各种条件相同的情况下,散列表的查询速度最快。

2. 查找手机电话簿

散列表广泛应用于查找,例如查找员工信息,学生信息,电话簿等等。下边列举如何快速查找到联系人的信息。

# 创建散列表
# TelephoneBook=dict()
# TelephoneBook={}
TelephoneBook=dict(阿美='187-6667-****',阿彪='186-****-4544',爸爸='136-9475-****',白雪='136-1231-****',陈明='178-****-9490')
print("电话薄信息如下:")
# 输出完整散列表
print(TelephoneBook)
print('')

print("查找联系人“白雪”的信息:")
# 查找白雪信息并输出
print("姓名:白雪 电话号码:",TelephoneBook['白雪'])
print('')

# 添加“彩虹”信息
TelephoneBook['彩虹']="188-****-5556"
print("添加彩虹之后的完整电话薄:")
# 输出添加之后的完整散列表
print(TelephoneBook)
print('')

# 修改“阿彪”信息
TelephoneBook['阿彪']="178-****-5555"
print("修改阿彪之后的完整电话薄:")
# 输出修改之后的完整散列表
print(TelephoneBook)
print('')

# 删除“白雪”信息
del TelephoneBook['白雪']
print("删除白雪之后的完整电话薄:")
# 输出删除之后的完整散列表
print(TelephoneBook)

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-09-15 02:14:52  更:2022-09-15 02:16:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 17:54:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码