数据结构基础:P11.4-散列查找--->散列表的性能分析

本系列文章为浙江大学陈越、何钦铭数据结构学习笔记,前面的系列文章链接如下
数据结构基础:P1-基本概念
数据结构基础:P2.1-线性结构—>线性表
数据结构基础:P2.2-线性结构—>堆栈
数据结构基础:P2.3-线性结构—>队列
数据结构基础:P2.4-线性结构—>应用实例:多项式加法运算
数据结构基础:P2.5-线性结构—>应用实例:多项式乘法与加法运算-C实现
数据结构基础:P3.1-树(一)—>树与树的表示
数据结构基础:P3.2-树(一)—>二叉树及存储结构
数据结构基础:P3.3-树(一)—>二叉树的遍历
数据结构基础:P3.4-树(一)—>小白专场:树的同构-C语言实现
数据结构基础:P4.1-树(二)—>二叉搜索树
数据结构基础:P4.2-树(二)—>二叉平衡树
数据结构基础:P4.3-树(二)—>小白专场:是否同一棵二叉搜索树-C实现
数据结构基础:P4.4-树(二)—>线性结构之习题选讲:逆转链表
数据结构基础:P5.1-树(三)—>堆
数据结构基础:P5.2-树(三)—>哈夫曼树与哈夫曼编码
数据结构基础:P5.3-树(三)—>集合及运算
数据结构基础:P5.4-树(三)—>入门专场:堆中的路径
数据结构基础:P5.5-树(三)—>入门专场:File Transfer
数据结构基础:P6.1-图(一)—>什么是图
数据结构基础:P6.2-图(一)—>图的遍历
数据结构基础:P6.3-图(一)—>应用实例:拯救007
数据结构基础:P6.4-图(一)—>应用实例:六度空间
数据结构基础:P6.5-图(一)—>小白专场:如何建立图-C语言实现
数据结构基础:P7.1-图(二)—>树之习题选讲:Tree Traversals Again
数据结构基础:P7.2-图(二)—>树之习题选讲:Complete Binary Search Tree
数据结构基础:P7.3-图(二)—>树之习题选讲:Huffman Codes
数据结构基础:P7.4-图(二)—>最短路径问题
数据结构基础:P7.5-图(二)—>哈利·波特的考试
数据结构基础:P8.1-图(三)—>最小生成树问题
数据结构基础:P8.2-图(三)—>拓扑排序
数据结构基础:P8.3-图(三)—>图之习题选讲-旅游规划
数据结构基础:P9.1-排序(一)—>简单排序(冒泡、插入)
数据结构基础:P9.2-排序(一)—>希尔排序
数据结构基础:P9.3-排序(一)—>堆排序
数据结构基础:P9.4-排序(一)—>归并排序
数据结构基础:P10.1-排序(二)—>快速排序
数据结构基础:P10.2-排序(二)—>表排序
数据结构基础:P10.3-排序(二)—>基数排序
数据结构基础:P10.4-排序(二)—>排序算法的比较
数据结构基础:P11.1-散列查找—>散列表
数据结构基础:P11.2-散列查找—>散列函数的构造方法
数据结构基础:P11.3-散列查找—>冲突处理方法

文章目录

  • 前言
  • 一、散列表的性能分析
    • 1.1 线性探测法的查找性能
    • 1.2 平方探测法和双散列探测法的查找性能
    • 1.3 期望探测次数与装填因子α的关系。
    • 1.4 分离链接法的查找性能
    • 1.5 总结


前言

前面对一些具体的散列表例子,我们也做过一些性能分析,主要是分析它的平均查找长度。而平均查找长度又分为两种情况,一个是成功的,一个是不成功的。对于散列表的查找来讲,它的性能主要受三个因素的影响
①散列函数是否均匀;
②处理冲突的方法;
③散列表的装填因子α。
所以,我们下面要分析不同的冲突解决方法以及不同的填装因子对查找效率的影响。我们有很多理论上的结果,先来看一下。


一、散列表的性能分析

1.1 线性探测法的查找性能

可以证明,线性探测法的期望探测次数满足下列公式:
数据结构基础:P11.4-散列查找--->散列表的性能分析_第1张图片
α=0.5

插入操作和不成功查找的期望ASLu=0.5*(1+1/(1-0.5)2)=2.5
成功查找的期望ASLs=0.5*(1+1/(1-0.5))=1.5

对于之前的一个例子

散列表如下所示:
在这里插入图片描述
其中,装填因子α=9/13=0.69
期望ASLu=0.5*(1+1/(1-0.69)^2)=5.70
期望ASLs=0.5*(1+1/(1-0.69))=2.11次(例中的ASLs=2.56)


1.2 平方探测法和双散列探测法的查找性能

可以证明,平方探测法和双散列探测法的期望探测次数满足下列公式:
数据结构基础:P11.4-散列查找--->散列表的性能分析_第2张图片
α=0.5

插入操作和不成功查找的期望ASLu=1/(1-0.5)=2
成功查找的期望ASLs=-1/0.5*ln(1-0.5)≈1.39

对于之前的一个例子

散列表如下所示:
在这里插入图片描述
其中,装填因子α=9/11=0.82
期望ASLu=1/(1-0.82)≈5.56
期望ASLs=-1/0.5*ln(1-0.5)≈2.09次(例中的ASLs=2)


1.3 期望探测次数与装填因子α的关系。

在线性探测跟双散列探测的情况下,查找的次数可以利用前面的公式计算出来,那么就有以下曲线:
数据结构基础:P11.4-散列查找--->散列表的性能分析_第3张图片
从这条曲线中我们可以得到以下结论:

①当装填因子α<0.5的时候,各种探测法的期望探测次数都不大,也比较接近。
②随着 α 的增大,线性探测法的期望探测次数增加较快,不成功查找和插入操作的期望探测次数比成功查找的期望探测次数要大
③合理的的最大装入因子α应该不超过0.85


1.4 分离链接法的查找性能

所有地址链表的平均长度定义成装填因子α,α有可能超过1。不难证明,其期望探测次数 为:
在这里插入图片描述
α=1

插入操作和不成功查找的期望ASLu=1+e^(-1)=1.37
成功查找的期望ASLs=1+1/2=1.5

对于之前的一个例子

散列表如下所示:
数据结构基础:P11.4-散列查找--->散列表的性能分析_第4张图片
其中,装填因子α=14/11≈1.27
期望ASLu=1.27+e^(-1.27)≈1.55
期望ASLs=1+1.27/2≈1.64次(例中的ASLs=1.36)


1.5 总结

散列查找的特点

适合于关键字直接比较计算量大的问题:它的一个很大的优点就是它不像搜索树和平衡二叉树查找跟问题的规模有关。散列表通过散列函数计算出位置,然后在这个位置上去找。当不发生冲突的时候,我们基本上是一次成功。如果你的冲突处理方法或者散列函数设计得好,这个冲突也可以减少到个位数。所以散列查找跟问题规模没有关系。
适合于关键字直接比较计算量大的问题:散列查找在很多情况下是用于字符串变量名的管理,比如web地址名。当我们的 keyword是字符串的时候,如果一个字符一个字符去查找,效率低。那么我们通过设计一个函数把它变成数字,再进行比较,就方便得多。
散列方法是一个以空间换时间的策略:散列查找中有一个装填因子,装填因子反应了散列表的占有率。装填因子如果小的话,意味着我们冲突少。所以散列查找实际上是以空间换时间的一种策略。
散列方法的存储对关键字是随机的,不便于顺序查找关键字,也不适合于范围查找,或最大值最小值查找:对于二分法查找或者搜索树查找我们可以做很多事情。比如我想找最大值、最小值或某个范围内的数,这在搜索树或者平衡二叉树里面是容易实现的,但是在散列表里没办法做。如果我们的问题不在乎去找最大值、最小值、某个范围内的数,那么散列表就是一个比较好的解决方案。


开放地址法

①散列表是一个数组,存储效率高,查找也方便。
②散列表有聚集现象


分离链接法

①散列表是顺序存储和链式存储的结合,入口是一个数组,数组里面有个指针指向一个单项链表。而一旦发生冲突,到链表里去找的时候,链表必须从头到尾一个个往后看。所以冲突比较多的时候,这个链表会变得很长,查找和存储效率自然会降低。
②删除操作是比较容易实现的,直接再链表中把它拿掉就行了,不会存在继续占用空间的情况。因此关键字删除不需要懒惰删除法,从而没有存储垃圾。
③太小的α可能导致空间浪费,大的α又将付出更多的时间代价。不均匀的链表长度导致时间效率的严重下降。

你可能感兴趣的:(数据结构基础,数据结构,散列表,算法,c算法,c语言)