二分查找

**
二分查找算法的前置条件是,一个已经排序好的序列(在本篇文章中为了说明问题的方便,假设这个序列是升序排列的),这样在查找所要查找的元素时,首先与序列中间的元素进行比较,如果大于这个元素,就在当前序列的后半部分继续查找,如果小于这个元素,就在当前序列的前半部分继续查找,直到找到相同的元素,或者所查找的序列范围为空为止.

时间复杂度: O(lgN)

int bSearch(int *a,int len,int target)
{
    int low = 0;
    int high = len-1;
    int mid;
//注意此处是low<=high不是low<high
    while(low<=high)
    {
        mid = low+((high-low)>>1);
        if (a[mid] == target)
            return mid;
        else if(a[mid] > target)
            high = mid-1;
        else
            low = mid+1;
    }
    return -1;
}

上面的程序的问题在于:
1.如果序列当中有多个元素相同时,查找的时候不见得每次都会返回第一个元素的位置。
2.每次循环体当中都有三种情况,两次比较,有没有办法减少比较的数量,进一步优化程序。

《编程珠玑》中给出了解决这个问题的算法,如下:

int bSearch(int *a,int len,int target)
{
    int low = -1;
    int high = len;
    int mid;

    while(low+1 != high)
// 这个循环维持的条件是 low < high &&a[low]<target<a[high],
//所以最后若可以找到目标,则只剩下两个数,并满足a[low]<target<a[high],要查找的数就是high.
    {
        mid = low+((high-low)>>1);
        if(a[mid] < target)
//必须保证a[low]<target<=a[high],所以low=mid.
//若low = mid+1,则可能出现a[low] <=target
            low = mid;
        else
            high = mid;
    }
    if(high >= len || a[high] != target)
        high = -1;
    return high;

}

上面的算法不好理解,也可以使用下面这种。

int bSearch(int *a,int len,int target)
{
    int low = 0;
    int high = len-1;
    int mid;
    int last =-1;
//定义一个last来记录查找到的元素最后一次出现的位置。
//赋初始值为-1,当所要查找的元素不存在时,就能直接返回-1.
    while(low<=high)
    {
        mid = low+((high-low)>>1);
        if (a[mid] < target)
            low = mid+1;
        else if(a[mid] > target)
            high = mid-1;
        else
        {
            last =mid;
            high = mid-1;
        }
    }
    return last;
}

另外,若要求的是找到大于某个数的第一个数,则可以使用如下方法:

int bSearch(int *a,int len,int target)
{
    int low = 0;
    int high = len-1;
    int mid;
    int last = -1;
    while(low<=high)
    {
        mid = ((high-low)>>1)+low;
        if (a[mid] > target)
        {
            last = mid;
            high = mid-1;
        }
        else
            low = mid+1;
    }
    return last;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 介绍 当我们想在一个数组中查找一个元素的时候,最简单的方法莫过于顺序查找了,不过顺序查找有一个致命的缺点,就是它的...
    ghwaphon阅读 946评论 0 12
  • 1 前言 二分查找本身是个简单的算法,但是正是因为其简单,更容易写错。甚至于在二分查找算法刚出现的时候,也是存在b...
    __七把刀__阅读 1,416评论 0 1
  • 二分查找 二分查找算法是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好...
    JasonDing阅读 1,541评论 0 3
  • 二分查找二分查找 又称折半查找,要求数组必须是有序的数列,是一种有序查找算法。二分查找的时间复杂度是O(log n...
    VV木公子阅读 1,311评论 0 12
  • 国庆后的某天,我又拖着行李箱背着电脑踏上出差的旅途。于是我平生第一次见到了自杀。 当我从车站二楼搭乘电梯下去的时候...
    千分之一阅读 638评论 3 11