首页 > 编程语言 > 详细

二分算法入门——二分查找

时间:2014-11-06 00:25:23      阅读:226      评论:0      收藏:0      [点我收藏+]

  二分查找,无论是从名字还是理论都十分简单一个算法,其博大精深,简直恐怖。Jon Bentley:90%以上的程序员无法正确无误的写出二分查找代码。

  别人不知道,反正我早上是写了好久,这个查找算法,将查找的复杂度从 o( n ) 降到了 o( logn ) ,当之无愧的的好算法,更是许多高级算法的优化策略之一。

  

  二分查找之基本思路

  虽然二分查找是一个很吊的算法,但是跟很多算法一样,需要使用的基础条件——序列有序!

  先假设一个单调非增序列:1 2 3 4 5 6 ,求找到3的位置,地球人都会马上这么想——一个一个找咯,可是这样很慢!

  于是有人想要加快查找速度,他们发现如果从中间开始找,那么每次比较后就至少可以排除一半的数,这就是二分查找的基本思想——折半。

  1)设置三个指针变量(应该说是指针性质的变量,索引也是可以的)——low ,mid 和 high,并且满足 mid = ( low + high ) / 2;

  2)设置循环,进行target值与mid存储值的比较,根据比较结果更新low或者high;

  3)在 2)中,若出现找到target的情况,则返回mid指针;如果一直找不到,则返回空指针。

  下面是代码:

   

//方法一
int
binary_search(int n, int v) { int low=0,high=n-1,mid; while (low<=high) { mid=(low+high)/2; if (a[mid]==v) return mid; if (a[mid]<v) low=mid+1; if (a[mid]>v) high=mid-1; } return -1; }

  看起来好像没什么问题,实际上在一些情况下 ,答案会很奇怪:1 2 2 4 5,我们如果找2,答案 -> 2 (这是索引啊!)  

  那么问题来了,为什么是返回第二个,而不是第一个呢?其实很简单,当序列出现重复元素时,我们找到了当然是其中“任意”一个啦!

  但是其实往往我们需要处理的序列总是拥有重复元素的,所以,我们需要优化!

  我们先来分析原来的二分查找 —— left < mid <right ,即我们将“=”的情况全部交给mid处理,于是mid会给你各种答案:

  所以,我们不妨按这种规则来二分 —— left <= mid < right !

  我们可以看看代码:

 

//方法二:返回第一个位置
int
lowerBound(const int a[],const int size,const int target) { int low=0,high=size-1,mid; while(low<high) { mid=(low+high)/2; if(a[mid]<target) low=mid+1; else high=mid; } if(a[low]==target) return low; else return -1; }

 

  这里我们会发现两种查找方式一个最明显的不同:方法一是找到答案立即返回,方法二则是一直找到最底部(当成树看)然后再返回!感觉方法二要一

  直找到底部好像会很慢,但是事实证明:方法一才是最慢的,所以我们以后可以抛弃第一种写法啦!

  当然,方法二是返回第一个位置,那么就会有返回最后一个位置的算法啦!

  上代码:

 

//方法三:返回最后一个位置
int
upperBound(const int a[], const int size, const int target) { int low=0,high=size-1,mid; while(low<high) { mid=(low+high)/2+1; if(a[mid]>target) high=mid-1; else low=mid; } if(a[high]==target) return high; else return -1; }

 

  以上就是我们的二分查找算法,参考资料:数据结构与程序设计——C++语言描述(这真是一本好书!)

 

 

  

 

    

 

  

二分算法入门——二分查找

原文:http://www.cnblogs.com/godding/p/4066018.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!