笔者曾连续写过多篇文章分析对分查找最优解问题,然而值得注意的是:虽然各地的联考卷和模拟卷多次出现对分查找最优解问题,但在历年选考真题卷中,却极少出现此类问题(2019年4月第12题是个特例),高考考查的仍然是最基础的对分查找特定值问题。
教材提供了一个经典的对分查找特定值算法代码,其他习题中也出现过相关变例。经过广泛分析和比较,笔者总结了对分查找特定值问题的三大类共九种代码形式,列表分析如下:
又如,在函数bs3中,右边界初值R=n,若查找过程中R的值一直不变,则m无法指向R,当循环结束后L=R,需要比较a(R)是否等于key。
有人也许会问,在函数bs2中,若查找过程中R的值一直不变,则m同样无法指向R,那为什么循环结束后不需要比较a(R)是否等于key呢?原因在于此时右边界初值R=n+1,若R的值不变,虽然m没有指向过R,但是它能指向[1,n]区间内所有可能的下标。如果在循环体外比较a(R)是否等于key,纯属画蛇添足,反而会出现下标越界错误。
由此可见,不同的循环条件对应不同的代码模式,m左偏或右偏只对模式2的循环体语句有影响;L和R的初值不同,对循环体内的代码没有影响,但是会影响循环体外的代码,循环体中没有查找过的元素,需要在循环体外单独比较。
函数bs1、bs2、bs4和bs6中,对L和R取初值合适,能让m指向[1,n]区间内所有可能的下标,体现了既不遗漏、又不越界原则,是值得推荐的写法,其他几种变例则稍有逊色。
参考代码:
'函数bs的功能是在数组a中查找特定值key,若找到则返回该元素下标,否则返回-1Const n = 6Dim a(1 To n) As IntegerPrivate Function bs1(key As Integer) As Integer L= 1: R = n Do While L <= R m = (L + R) \ 2 '或m = (L + R + 1) \ 2 If a(m) = key Then bs1 = m: Exit Function ElseIf a(m) < key Then L = m + 1 Else R = m - 1 End If Loop bs1 = -1End Function Private Function bs2(key As Integer) As Integer L= 1: R = n + 1 Do While L < R m = (L + R) \ 2 If a(m) = key Then bs2 = m: Exit Function ElseIf a(m) < key Then L = m + 1 Else R = m End If Loop bs2 = -1End Function Private Function bs3(key As Integer) As Integer L= 1: R = n Do While L < R m = (L + R) \ 2 If a(m) = key Then bs3 = m: Exit Function ElseIf a(m) < key Then L = m + 1 Else R = m End If Loop If a(R) = key Then bs3 = R Else bs3 = -1End Function Private Function bs4(key As Integer) As Integer L= 0: R = n Do While L < R m = (L + R + 1) \ 2 If a(m) = key Then bs4 = m: Exit Function ElseIf a(m) < key Then L = m Else R = m - 1 End If Loop bs4 = -1End Function Private Function bs5(key As Integer) As Integer L= 1: R = n Do While L < R m = (L + R + 1) \ 2 If a(m) = key Then bs5 = m: Exit Function ElseIf a(m) < key Then L = m Else R = m - 1 End If Loop If a(L) = key Then bs5 = L Else bs5 = -1End Function Private Function bs6(key As Integer) As Integer L= 0: R = n + 1 Do While L + 1 < R m = (L + R) \ 2 '或m = (L + R +1) \ 2 If a(m) = key Then bs6 = m: Exit Function ElseIf a(m) < key Then L = m Else R = m End If Loop bs6 = -1End Function Private Function bs7(key As Integer) As Integer L= 1: R = n Do While L + 1 < R m = (L + R) \ 2 '或m = (L + R + 1) \ 2 If a(m) = key Then bs7 = m: Exit Function ElseIf a(m) < key Then L = m Else R = m End If Loop If a(L) = key Then bs7 = L ElseIf a(R) = key Then bs7 = R Else bs7 = -1 End IfEnd Function Private Function bs8(key As Integer) As Integer L= 1: R = n + 1 Do While L + 1 < R m = (L + R) \ 2 '或m = (L + R + 1) \ 2 If a(m) = key Then bs8 = m: Exit Function ElseIf a(m) < key Then L = m Else R = m End If Loop If a(L) = key Then bs8 = L Else bs8 = -1End Function Private Function bs9(key As Integer) As Integer L= 0: R = n Do While L + 1 < R m = (L + R) \ 2 '或m = (L + R + 1) \ 2 If a(m) = key Then bs9 = m: Exit Function ElseIf a(m) < key Then L = m Else R = m End If Loop If a(R) = key Then bs9 = R Else bs9 = -1End Function
需要本文word版的,可以加入“选考VB算法解析”知识星球参与讨论和下载文件,“选考VB算法解析”知识星球汇集了数量众多的同好,更多有趣的话题在这里讨论,更多有用的资料在这里分享。
我们专注选考VB算法,感兴趣就一起来!
相关优秀文章:
阅读代码和写更好的代码
最有效的学习方式
选考VB算法解析之2018年11月高考真题卷第16题
对分查找算法模型分类及示例分析
对分查找最优解问题分析
再谈对分查找最优解问题