将关键字序列(7、8、30、11、18、9、14)散列存储到散列表中。散列表的存储空间是一个下标从0开始的一维数组。散列函数为: H(key) = (key*3) MOD 7,处理冲突采用线性探测再散列法,要求装填(载)因子为0.7。
(1) 请画出所构造的散列表;
(2) 分别计算等概率情况下查找成功和查找不成功的平均查找长度。
一、查找成功平均长度
- 通过公式计算出存放的位置,如果该位置已经有数字了,往后找到一个空的放下。
- 存放示意图
存放位置 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
存放数字 | 7 | 14 | 8 | 11 | 30 | 18 | 9 |
- 查找时候,一次找到的查找长度为1,否则多移动一格查找长度加一。如下表
存放位置 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
存放数字 | 7 | 14 | 8 | 11 | 30 | 18 | 9 | |||
查找长度 | 1 | 2 | 1 | 1 | 1 | 3 | 3 |
- 由此可得查找成功的平均查找长度为:(1+1+1+1+3+3+2)/7 = 12/7
二、查找不成功平均长度
存放位置 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
存放数字 | 7 | 14 | 8 | 11 | 30 | 18 | 9 |
接下来讨论不成功的情况,由上表,计算查找不成功的次数就直接找关键字到第一个地址上关键字为空的距离即可, 但根据哈希函数地址为MOD7,因此初始只可能在06的位置。等概率情况下,查找06位置查找失败的查找次数为:
看地址0,到第一个关键字为空的地址2的距离为3,因此查找不成功的次数为3.
地址1, 到第一个关键为空的地址2的距离为2,因此查找不成功的次数为2.
地址2, 到第一个关键为空的地址2的距离为1,因此查找不成功的次数为1.
地址3,到第一个关键为空的地址4的距离为2,因此查找不成功的次数为2.
地址4,到第一个关键为空的地址4的距离为1,因此查找不成功的次数为1.
地址5,到第一个关键为空的地址2(注意不是地址9,因为初始只可能在0~6之间(因为只有7个数),因此循环回去)的距离为5,因此查找不成功的次数为5.
地址6,到第一个关键为空的地址2(注意不是地址9,因为初始只可能在0~6之间,因此循环回去)的距离为4,因此查找不成功的次数为4.
因此查找不成功的次数表如下表所示
存放位置 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
存放数字 | 7 | 14 | 8 | 11 | 30 | 18 | 9 | |||
查找不成功长度 | 3 | 2 | 1 | 2 | 1 | 5 | 4 |
- 所以查找不成功平均长度:(3+2+1+2+1+5+4)/ 7 = 18/7。
个人总结的有关考研数据结构中平均查找长度ASL的三种计算小技巧:
-
顺序查找法的平均查找长度为:(n+1)/2
-
散列表的查找成功和查找不成功的平均查找长度
技巧(线性探测法和链地址法):
① 查找成功时的比较次数是基于关键字计算的;查找不成功时的比较次数是基于Hash函数计算得到的地址计算的。
②查找成功的计算只有一种情况;查找不成功的计算有两种情况,关键是看题目中是否含有(只将与关键字的比较计算在内)
若没有,查找过程中遇到空位置,则证明查找失败;若有,则查找过程中只需比较关键字即可。注意:①查找成功是除关键字的个数;②查找不成功是除mod后的数值
-
折半查找成功和查找不成功的平均查找长度:
以折半查找的方式,将逐个查找出来的数值建立判定树,根据判定树求查找成功和查找不成功的平均查找长度。
注意:①查找成功是除关键字个数;②查找不成功是除关键字个数加1
个人的理解就是这样,希望能够帮到部分同在考研的研友们!
线性探测再散列
例如 哈希函数为: H(key) = key %13,key 为关键字,采用开放地址法中的线性探测再散列解决冲突,依次输入
11 个关键字,16,74,60,43,54,90,46,31,29,88,77,构造哈希表
如图,例如 16%13=3,将16放入3号位置,29%13 = 3,将29放入3号位置,而此时3号位已经有元素。
就顺着表往后放,直到6号没有元素,29放入6号。
二次探测再散列
例如 哈希函数为: H(key) = key %13,key 为关键字,采用开放地址法中的二次探测再散列解决冲突,依次输入
10 个关键字,36,21,45,17,29,55,35,61,40,78,构造哈希表
对于29%13=3,将29放入3号位置, 55%13=3,此时3号位置已经有元素,
则查找 3 + 1^2 = 4,有元素
查找 3 - 1^2 = 2 ,没有则放入,如果还有元素则查找3 + 2^2, 3-2^2… 3+k^2, 3 - k^2。
ASL(Average Search Length),即平均查找长度,在查找运算中,由于所费时间在关键字的比较上,所以把平均需要和待查找值比较的关键字次数称为平均查找长度。
它的定义是这样的:
其中n为查找表中元素个数,Pi为查找第i个元素的概率,通常假设每个元素查找概率相同,Pi=1/n,Ci是找到第i个元素的比较次数。
当然,有查找成功,就有查找不成功,即要查找元素不在查找表中。针对不同查找方式的查找成功与不成功,我接下来会说,这也是一我一开始有点乱的地方。
一个算法的ASL越大,说明时间性能差,反之,时间性能好,这也是显而易见的。
- 在_顺序查找(Sequence Search)_表中,查找方式为从头扫到尾,找到待查找元素即查找成功,若到尾部没有找到,说明查找失败。所以说,Ci(第i个元素的比较次数)在于这个元素在查找表中的位置,如第0号元素就需要比较一次,第一号元素比较2次…第n号元素要比较n+1次。所以Ci=i;所以
可以看出,顺序查找方法查找成功的平均 比较次数约为表长的一半。**当待查找元素不在查找表中时,也就是扫描整个表都没有找到,即比较了n次,查找失败**
-
折半查找(Binary Search),首先待查找表是有序表,这是折半查找的要求。在折半查找中,用二叉树描述查找过程,查找区间中间位置作为根,左子表为左子树,右子表为右子树,,因为这颗树也被成为判定树(decision tree)或比较树(Comparison tree)。查找方式为(找k),先与树根结点进行比较,若k小于根,则转向左子树继续比较,若k大于根,则转向右子树,递归进行上述过程,直到查找成功或查找失败。在n个元素的折半查找判定树中,由于关键字序列是用树构建的,所以查找路径实际为树中从根节点到被查结点的一条路径,因为比较次数刚好为该元素在树中的层数。所以Pi为查找k的概率,level(Ki)为k对应内部结点的层次。而在这样的判定树中,会有n+!种查找失败的情况,因为将判定树构建为完全二叉树,又有n+1个外部结点(用Ei(0<=i<=n)表示),查找失败,即为从根结点到某个外部结点也没有找到,比较次数为该内部结点的结点数个数之和,所以,qi表示查找属于Ei中关键字的概率,level(Ui)表示Ei对应外部结点的层次。所以,在一颗有n个结点判定树中,总数,所以判定树高度为的满二叉树,第i层上结点个数为,查找该层上的结点需要进行i次比较,因此,在等概率情况下ASL为 看个例子会更好理解。
-
例:给11个数据元素有序表(2,3,10,15,20,25,28,29,30,35,40)采用折半查找。则ASL成功和不成功分别是多少?
-
首先画出判定树,
-
查找成功时总会找到途中某个内部结点,所以成功时的平均查找长度为 即25查找一次,成功,10,30要查找2次,成功,2,15,28,35要查找3次,成功,3,20,29,40要查找4次,成功。 而不成功的平均查找长度为 ,为什么这么算呢,因为内部结点都能查找成功,而查找不成功的就是那些空的外部结点,所以到查询到2的左孩子,15的左孩子,28的左孩子,35的左孩子,3的左右孩子,20的左右孩子,29的左右孩子,40的左右孩子时,都是查找不成功的时候。如我要找1,比25小,转向左子树,比较一次,比10小,转左子树,2次,比2 小,转左子树,3次,此时2无左子树,所以失败。所以 。
-
哈希表中的ASL 查找成功的平均查找长度是指查找到哈希表中已有关键字的平均探测次数。而查找不成功的平均查找长度是指在哈希表中找不到待查的元素,最后找到空位置元素的探测次数平均值。
-
例:散列表长度为13,地址空间为0~12,散列函数H(k) =K mod 13,关键字序列{19,14,23,01,68,20,84,27,55,11,10,79} 所以线性探测结果为:
各位可以手动算一下,加深理解~
根据探测次数,
当然成功的很好理解,12个元素,每个元素的探测次数之和除以12就行。而不成功的计算是这样的。散列表长度为13,根据定义,假设待查关键字不在散列表中,要一直找到空元素才算查找失败。
如H[0]为空,与待查找元素不等,不成功,比较一次,H[1],此时H[1]的元素与原本放在H[1]的元素不等**(假设不在散列表在之中,但也不是空的**),继续向后比,与H[2]比也不等,继续向后,一直到H[12],也不等,继续向后时,回到H[0],为空,也不等,查找失败,总计比较13次,然后计算第二号元素,一样的比较,一直把每个位置都统计一遍,从而得出ASL不成功的.