zoukankan      html  css  js  c++  java
  • 基础算法之二分查找总结

    本博客是我在做题和看书遇到各种情况的总结。

    参考了书,邓俊辉老师编写的《数据结构(C++语言版)(第3版)》,同时还有网友的总结(以下会给出相应的链接)。

     一、查找等于目标元素的位置(若是多个,只要求找到即可)

     1 /二分查找的主体
     2 int binarySearch(int A[], int n, int target)
     3 {
     4     int lo = 0, hi = n;  //n为数组的A元素的个数
     5     
     6     while (lo < hi)
     7     {
     8         int mid = lo + (hi - lo)/2;
     9         if (A[mid] == target)
    10             return mid;
    11         else if (target < A[mid])
    12             hi = mid;
    13         else
    14             lo = mid + 1;
    15     }
    16     return -1;
    17 }

     这里关于右边界hi的取值值得注意的有几点:

    1)在while循环外面的hi=n,说明是前开后闭型([0,n) ),那么在while循环中的hi的取值应构成前开后闭型([ lo,mid )),此时while循环的条件为lo<hi

    2)在while循环外面的hi=n-1,说明是前开后闭型([0,n-1]),那么在while循环中的hi的取值应构成前开后闭型([ lo,mid-1]),此时while循环的条件为lo<=hi 

    这里不是说,其他情况下的使用,就不能使用,只是有时候会出错。

    二、查找重复元素的第一个值的下标,若是没有重复元素则返回第一个不小于目标值的下标

     1 //二分查找的主体
     2 int binarySearch(int A[], int n, int target)
     3 {
     4     int lo = 0, hi = n;
     5     
     6     while (lo < hi)
     7     {
     8         int mid = lo + (hi - lo)/2;
     9         
    10         if (A[mid] < target)
    11             lo = mid + 1;
    12         else
    13             hi = mid;
    14     }
    15     return hi;
    16 }

    :这里的hi值也可以像一种那样变化,要对应的变化。只不过这样改变以后,在不存在目标值的情况下,返回的是第一个小于目标值(从目标值往左数)的下标。

    三、查找重复元素的最后一个下标,或者不存在目标值时,第一个小于目标值的下标。这种情况,邓老师书上有严格的证明。

     1 //二分查找的主体
     2 int binarySearch(int A[], int n, int target)
     3 {
     4     int lo = 0, hi = n;
     5     
     6     while (lo < hi)
     7     {
     8         int mid = lo + (hi - lo)/2;
     9         
    10         if (A[mid] <= target)
    11             lo = mid + 1;
    12         else
    13             hi = mid;
    14     }
    15     return --lo;    //必须减减
    16 }

    注意:第二种和第三种的区别在于if条件判断语句的差别,和返回值的区别,

    四、将二、三结合就可以求出存在多个目标值时,目标值所在的区间。详情见search for a range

    版本一的进化版是斐波那契查找,这和二分查找的主要区别在于中间点mid是使用斐波那契进行选择的,版本三的各分支的平均查更好些,详情请见参考书。

    总结

    针对二分查找,值得注意的是区间的选取(见第一种情况下的说明);要是求目标值给定条件下(第一个或最后一个)下的下标,可以通过变化while循环中的if条件内的等号所在来实现。

    下面给出第三种情况下测试程序,第一、二中可以通过变化数组A所含的值来实现。

     1 #include<iostream>
     2 #include<vector>
     3 
     4 using namespace std;
     5 
     6 int binarySearch(int A[], int n, int target);
     7 
     8 int main()
     9 {
    10     int A[] = { 0,1,2,3,4,4,4,4,5,6,7,8,9 };
    11     int target = 4;
    12     int res = binarySearch(A, 13, target);    
    13     cout << "目标值的下标是:" << res << endl;
    14     return 0;
    15 }
    16 
    17 //二分查找的主体
    18 int binarySearch(int A[], int n, int target)
    19 {
    20     int lo = 0, hi = n;
    21     
    22     while (lo < hi)
    23     {
    24         int mid = lo + (hi - lo)/2;
    25         
    26         if (A[mid] <= target)
    27             lo = mid + 1;
    28         else
    29             hi = mid;
    30     }
    31     return --lo;    //必须减减
    32 }
    33 
    34 
    35 /*
    36     int A[] = { 0,1,2,3,4,4,4,4,5,6,7,8,9 },target=4时,返回值为7
    37     int A[] = { 0,1,2,4,4,4,4,5,6,7,8,9 },target=3时,返回值为2
    38     int A[] = { 0,1,2,4,4,4,4,5,6,7,8,9 },target=3,返回lo时,返回值为3
    39 */

    若是各位看官发现什么问题,多多留言哈,共同进步~

    参考:

    http://www.61mon.com/index.php/archives/187/

    http://blog.csdn.net/sunmenggmail/article/details/7540970

    http://www.cnblogs.com/luoxn28/p/5767571.html

    http://www.cnblogs.com/grandyang/p/6854825.html

  • 相关阅读:
    Linux中创建Daemon进程的三种方法【转】
    Linux 内核定时器使用 二 高精度定时器 hrtimer 的用例【转】
    使用 Qemu 虚拟 ARM64 平台演示 kdump 崩溃转存【转】
    自旋锁 spin_lock、 spin_lock_irq 以及 spin_lock_irqsave 的区别【转】
    Linux中的spinlock机制[四]
    Linux中的虚拟内存机制和内存映射【转】
    那些情况该使用它们spin_lock到spin_lock_irqsave【转】
    Linux内核中的软中断、tasklet和工作队列详解【转】
    Linux 读写memory操作,devmem直接访问物理内存地址【转】
    Linux性能之DVFS/cpufreq【转】
  • 原文地址:https://www.cnblogs.com/love-yh/p/7147212.html
Copyright © 2011-2022 走看看