二分查找的学习

来自:http://www.acmerblog.com/ubiquitous-binary-search-5345.html

我们都知道二分查找算法,实际上二分查找以及其扩展应用是很广泛的。这里收集了一些和二分查找有关的有趣问题。强烈建议大家看完问题后最小化浏览器,先尝试自己去解决,然后再看代码,问题都不是太难。

问题1描述

给一个已经排序的数组,其中有N个互不相同的元素。要求使用最小的比较次数找出其中的一个元素。(你认为二分查找在排序数组里找一个元素是最优的算法的吗?)

不需要太多的理论,这是一个典型的二分查找算法。先看下面的代码:

 1 // 返回要查找元素的下标,-1为没有找到
 2 int BinarySearch(int A[], int l, int r, int key)
 3 {
 4     int m;
 5     while( l <= r )
 6     {
 7         m = l + (r-l)/2;
 8 
 9         if( A[m] == key ) //第一次比较
10             return m;
11 
12         if( A[m] < key ) // 第二次比较
13             l = m + 1;
14         else
15             r = m - 1;
16     }
17 
18     return -1;
19 }

理论上,我们最多需要 logN+1 次比较。仔细观察,我们在每次迭代中使用两次比较,除了最后比较成功的一次。实际应用上,比较也是代价高昂的操作,往往不是简单的数据类型的比较。减少比较的次数也是优化的方向之一。

下面是一个比较次数更少的实现:

 1 // 循环不变式: A[l] <= key &  A[r] > key
 2 // 边界: |r - l| = 1
 3 // 输入: A[l .... r-1]
 4 int BinarySearch(int A[], int l, int r, int key)
 5 {
 6     int m;
 7     while( r - l > 1 )
 8     {
 9         m = l + (r-l)/2;
10 
11         if( A[m] <= key )
12             l = m;
13         else
14             r = m;
15     }
16     if( A[l] == key )
17         return l;
18     else
19         return -1;
20 }

在while循环中,我们仅依赖于一次比较。搜索空间( l->r )不断缩小,我们需要一个比较跟踪搜索状态。

需要注意的,要保证我们恒等式(A[l] <= key & A[r] > key)正确,后面还会用到循环不变式。

自己可以实现一下:

 1 #include <stdio.h>
 2 #include <math.h>
 3 #include <queue>
 4 #include <vector>
 5 #include <stack>
 6 #include <map>
 7 #include <string>
 8 #include <string.h>
 9 #include <algorithm>
10 #include <iostream>
11 using namespace std;
12 int binarysearch(int a[],int l,int r,int k){
13     int mid;
14     while(r-l>1){
15         mid=(r+l)/2;
16         if(a[mid]<=k)
17             l=mid;
18         else
19             r=mid;
20     }
21     if(a[l]==k)
22         return l;
23     else
24         return -1;
25 }
26 int main()
27 {
28     int a[10];
29     int n,m,i,j;
30     for(int i=0;i<5;i++){
31         cin>>a[i];
32     }
33     sort(a,a+5);
34     scanf("%d",&n);
35     m=binarysearch(a,0,5,n);
36     if(m!=-1)
37         printf("%d
",a[m]);
38     else
39         cout<<"NO"<<endl;
40     return 0;
41 }
原文地址:https://www.cnblogs.com/wangmengmeng/p/4711243.html