设为首页 加入收藏

TOP

2.4.2 折半查找(1)
2014-03-11 13:04:15 来源: 作者: 【 】 浏览:101
Tags:2.4.2 查找

2.4.2  折半查找(1)

查找是一种常见的任务,通常是在数组中查找某个特定项。下面讲述一些具有递归解决方案的查找问题。我们的目标是加深对递归的理解。

本章开始时曾给出高层的折半查找算法,在词典中查找单词。在此将完整地开发该算法,并阐述一些重要编程问题。

回顾前面词典问题的解决方案:
 

  1. search(aDictionary: Dictionary, word: string)  
  2. if (aDictionary is one page in size)  
  3. Scan the page for word  
  4. else  
  5. {  
  6. Open aDictionary to a point near the middle  
  7. Determine which half of aDictionary contains word  
  8. if (word is in the first half of aDictionary)  
  9. search(first half of aDictionary, word)  
  10. else  
  11. search(second half of aDictionary, word)  

注释:折半查找中,每一步解决一半问题

现在稍微调整一下问题--在整型数组anArray中查找指定值target。这个数组与词典一样必须经过排序,否则无法使用折半查找。在此假定:
 

  1. anArray[0]    anArray[1]    anArray[2]    …    anArray[size - 1] 

其中size是数组的大小。对于这个数组问题,折半查找的伪代码如下所示:
 

  1. binarySearch(anArray: ArrayType, target: ValueType)  
  2. if (anArray is of size 1)  
  3. Determine if anArray's value is equal to target  
  4. else  
  5. {  
  6. Find the midpoint of anArray  
  7. Determine which half of anArray contains target  
  8. if (target is in the first half of anArray)  
  9. binarySearch(first half of anArray, target)  
  10. else  
  11. binarySearch(second half of anArray, target)  

从概念上讲,该算法非常合理,但在实现算法前,必须考虑几个细节:

1. 如何将anArray的一半传递给binarySearch的递归调用?可以在每次调用时传递整个数组,但是只让binarySearch查找anArray[first..last],即从anArray[first]到anArray[last]的那部分。因此,还需要向binarySearch传递整数first和last。
 

  1. binarySearch(anArray, first, last, target) 

按此约定,新的中点由下式确定:
 

  1. mid = (first + last) / 2 

于是,binarySearch(first half of anArray, target)成为
 

  1. binarySearch(anArray, first, mid - 1, target) 

而binarySearch(second half of anArray, target)成为
 

  1. binarySearch(anArray, mid + 1, last, target) 

注释:原始数组的两半分别是anArray[first..mid-1]和anArray[first..mid+1],二者都不包含anArray[mid]

2. 如何确定数组的哪一半包含target?if (target is in the first half of anArray)的一种可能实现为
 

  1. if (target < anArray[mid]) 

但是,此处没有检测target和anArray[mid]相等的情况。这个疏忽可能会让该算法丢失target。通过前面的等分算法将anArray分作两半后,这两半都不包含anArray[mid](此时,这两半无法组成原先完整的数组)。因此,必须确定anArray[mid]是不是正在查找的值,因为后面anArray[mid]将不再出现在剩下的一半数组中。等分标准与终止条件(基例)的交互很不容易理解,经常是错误的来源。我们需要重新考虑基例。

注释:判断anArray[mid]是否为查找的目标

3. 如何确定基例?如程序所示,只有在数组大小为1的情况下,binarySearch才终止,这是其唯一的基例。通过更改等分过程,可以将anArray[mid]保留在剩余的一半数组中,从而有可能正确实现折半查找,此时只有一个基例。然而,如果有下面两个不同的基例,程序将更加清晰易懂:

first>last。当原始数组中不存在target时,将到达此基例。

target==anArray[mid]。当target在原始数组中时,将到达该基例。

这些基例与前面提到的基例有所不同。从某种意义上来讲,算法根据到达的基例来确定问题的解。很多查找问题都是这样的。
 

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇2.4.1 逆置数组项 下一篇2.4.2 折半查找(2)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·HTTPS 详解一:附带 (2025-12-26 02:20:37)
·TCP/IP协议到底在讲 (2025-12-26 02:20:34)
·TCP和UDP在socket编 (2025-12-26 02:20:32)
·有没有适合新手练习 (2025-12-26 01:48:47)
·用清华镜像网怎么下 (2025-12-26 01:48:44)