您的位置:首页 > 其它

005-二分搜索-分治法-《算法设计技巧与分析》M.H.A学习笔记

2016-06-27 16:30 260 查看
二分搜索又称折半查找,用于在排序好的序列表中进行搜索,搜索效率高,可在最坏的情况下用O(log n)完成搜索任务。

基本思想:

将n个元素分成个数大致相同的两半,取a[n/2]与欲查找的x作比较,如果x=a[n/2]则找到x,算法终止。如
果x<a[n/2],则我们只要在数组a的左半部继续搜索x(这里假设数组元素呈升序排列)。如果x>a[n/2],则我们只要在数组a的右
半部继续搜索x。

伪代码:

 


C++代码:

[cpp] view
plain copy

 





int binSearch(const int *Array,int start,int end,int key)  

{  

    int left,right;  

    int mid;  

    left=start;  

    right=end;  

   

    while(left<=right)  

    {  

        mid=(left+right)/2;  

        if(key==Array[mid])  return mid;  

        else if(key<Array[mid]) right=mid-1;  

        else if(key>Array[mid]) left=mid+1;  

    }  

    return -1;  

    //找不到就返回-1  

}  

“最小化最大值”:

这一算法运用在stl的两个函数中:

lower_bound

给定长度为n的单调不下降数列a0,a1,…,an−1和一个数k,求满足ai≥k条件的最小的i。不存在的情况下输出 n。

upper_bound

给定长度为n的单调不下降数列a0,a1,…,an−1和一个数k,求满足ai >k条件的最小的i。不存在的情况下输出 n。

 

C++代码:


两种写法(区别在判断截止的条件,本质上并没有分别):

1.

[cpp] view
plain copy

 





while( rb > lb )  

{       

int m = (lb + rb) / 2;  

if( ok(m) ) rb = m;  

else lb = m + 1;  

}  

// 答案为: lb == rb  

2.

[cpp] view
plain copy

 





while( rb - lb > 1 )  

{     

int m = (lb + rb) / 2;      

 if( ok(m) ) rb = m;      

else lb = m;  

}  

// 跳出循环时 lb + 1 == rb  

// 答案为 rb<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>  


贴两个常用的代码:

[cpp] view
plain copy

 





// 在arr的[sl, sr)下标范围内查找左起第一个>=target的元素,找到返  

// 回所在下标, 否则返回sr(区间最右元素下标+1)  

int LowerBound(int *arr, int sl, int sr, int target) {  

      int l = sl, r = sr - 1, mid;  

      while (l <= r) {  

             mid = (l +r) >>1;  

if (arr[mid] < target) l = mid + 1;  

             else r = mid;  

      }  

      return (l == r ? r : sr);  

}  

[cpp] view
plain copy

 





// 在arr的[sl, sr)下标范围内查找左起第一个>target的元素,找到返  

// 回所在下标, 否则返回sr(区间最右元素下标+1)  

int UpperBound(int *arr, int sl, int sr, int target) {  

      int l = sl, r = sr - 1, mid;  

      while (l <= r) {  

             mid = (l +r) >>1;  

if (arr[mid] <= target) l = mid + 1;  

             else r = mid;  

      }  

      return (l == r ? r : sr);  

}  

浮点数的二分搜索

关键在于截止条件,我们需要比较的是两个数的接近程度而不是大小abs(l-r)>=1e-10,当然我们可以直接指定循环次数,如100次,可以达到2−100≈10−30 的精度范围。

 

二分搜索的算法分析:

书中这一段写得很清楚,就直接截屏了:

 


这里的j就是搜索树的高度,即查找的复杂度为O(log n)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息