十大基础实用算法补全——二分查找(BinSearch)

算法简介

算法前提

二分查找法主要是解决在“一堆数中找出指定的数”这类问题。

而想要应用二分查找法,这“一堆数”必须有一下特征:

  1. 存储在数组中
  2. 有序排列

所以如果是用链表存储的,就无法在其上应用二分查找法了。

至于是顺序递增排列还是递减排列,数组中是否存在相同的元素都不要紧。不过一般情况,我们还是希望并假设数组是递增排列,数组中的元素互不相同。

基本思想

  二分查找法在算法家族大类中属于“分治法”,分治法基本都可以用递归来实现的。
  不过所有的递归都可以自行定义stack来解递归,所以二分查找法也可以不用递归实现,而且它的非递归实现甚至可以不用栈,因为二分的递归其实是尾递归,它不关心递归前的所有信息。
  
步骤:

  1. 由边界low、high,求出中间下标mid;
  2. 比较array[mid]与目标值,由结果缩小范围;
  3. 找到则退出,未找到重复1、2步骤直到 范围size为1且仍不为目标值

代码实现

#include 

/*
    非递归方式实现对有序表的二分查找,找到返回下标
    array[]:有序表
    low:低位
    high:高位
    target:目标元素
*/
int BinSearchWithoutRecursion(int array[], int low, int high, int target)
{
    while (low <= high)
    {
        int mid = (low + high) / 2;

        if (array[mid] > target)//中值大于目标值,则中值为高位
        {
            high = mid - 1;
        }
        else if (array[mid] < target)//中值小于目标值,则中值为低位
        {
            low = mid + 1;
        }
        else
        {
            return mid; //找到返回
        }
    }
    return -1;  //没找到返回
}

/*
递归方式实现对有序表的二分查找,找到返回下标
array[]:有序表
low:低位
high:高位
target:目标元素
*/
int BinSearchWithRecursion(int array[], int low, int high, int target)
{
    if (low <= high)
    {
        int mid = (low + high) / 2;

        if (array[mid] > target)
        {
            return BinSearchWithRecursion(array, low, mid - 1, target);
        }
        else if (array[mid] < target)
        {
            return BinSearchWithRecursion(array, mid + 1, high, target);
        }
        else
        {
            return mid; 
        }
    }
    return -1;
}
int main()
{
    int array[6] = { 1,2,3,4,5,6 };
    int index = BinSearchWithoutRecursion(array, 0, 5, 2);
    printf("位置为%d,值为%d\n", index, array[index]);

    index = BinSearchWithRecursion(array, 0, 5, 2);
    printf("位置为%d,值为%d\n", index, array[index]);

    return 0;
}

运行结果:


复杂度分析

二分查找的时间复杂度即为while循环的次数。

总共有n个元素, 渐渐跟下去就是n,n/2,n/4,….n/2^k,其中k就是循环的次数 。
由于你n/2^k取整后>=1,
可得k=log2n,(是以2为底,n的对数)
所以时间复杂度可以表示O()=O(logn)


缺陷

  二分查找法的O(log n)让它成为十分高效的算法。不过它的缺陷却也是那么明显的。就在它的限定之上:

  必须有序,我们很难保证我们的数组都是有序的。当然可以在构建数组的时候进行排序,可是又落到了第二个瓶颈上:它必须是数组。

  数组读取效率是O(1),可是它的插入和删除某个元素的效率却是O(n)。因而导致构建有序数组变成低效的事情。

  解决这些缺陷问题更好的方法应该是使用二叉查找树了,最好自然是自平衡二叉查找树了,既能高效的(O(n log n))构建有序元素集合,又能如同二分查找法一样快速(O(log n))的搜寻目标数。
  
  原文地址:二分查找法的实现和应用汇总
  


  如果有什么错误之处或建议,请在评论区告诉我,谢谢!

你可能感兴趣的:(十大基础实用算法,二分查找,算法)