vlambda博客
学习文章列表

二分查找法(折半查找法)

一、算法介绍

二分查找法:也称折半查找法,是一种效率较高的查找方法,存在一定的局限性。

局限性:适用于有序数组、有序链表等查找,例如:Array,List。


二、算法原理

二分查找法(折半查找法)

基本原理

第一步:设定需要查找的元素key,再设定low和high两个临时指针分别指向左边第一个元素和右边最后一个元素。

第二步:因为数据是有序的,先根据low和high计算出数据的中位数mid,把数据分割成左右两部分,左边部分数据都是小于中位数,右边部分数据都是大于中位数的。

第三步:判断key是大于还是小于mid。如果key>mid,先移动low指针到(mid+1)的位置,再根据low和high重新计算中位数。如果key<mid,先移动high指针到(mid-1)的位置,再根据low和high重新计算中位数。如果key=mid,直接返回key的元素下标。

第四步:不断重复比较key和mid的大小,再移动low或high指针,重新计算数据的中位数,直到查找到key或循环停止。


算法步骤图解

二分查找法(折半查找法)


源数据为:int[] nums = {1, 2, 3, 4, 6, 7, 10, 12};

第一步:设定key=10、左指针low=0、右指针high=(nums.length-1)=7。

第二步:根据low=0和high=7计算数据的中位数mid=3,中位数值为nums[3]=4,再比较key和中位数的大小。

第三步:判断10>4、把low移动到(mid+1)的位置。再根据low=4和high=7计算数据的中位数mid=5,中位数值为num[5]=7,再比较key和中位数的大小。

第四步:判断10>7,把low移动到(mid+1)的位置。再根据low=6和high=7计算数据的中位数mid=6,中位数值为nums[6]=10,再比较key和中位数的大小。

第五步:判断10=10,说明查找到元素了,直接终止计算并返回元素下标。


中位数计算方式

方式一:int mid = (low+high)/2; // (low+high)可能会超过int的最大值,导致整型溢出

方式二:int mid = low + ((high-low)>>1); // 也可能出现问题。

方式三:int mid = (low+high)>>>1; // 得到左中位数,推荐写法。

方式四:int mid = (low+high+1)>>>1; // 得到右中位数,推荐写法。


三、算法源码

二分查找法(折半查找法)
/**
 * 二分法查找(折半查找法)
 * @param nums
 * @param key
 * @return
 */

public static int binarySearch(int[] nums, int key) {
    if (nums == null) {
        return -1;
    }

    int low = 0// 起始位置
    int high = nums.length-1// 结束位置

    while (low <= high) {
        int mid = (low + high) >>> 1// 得到左中位数,推荐写法

        if (nums[mid] < key) { // key>mid, 把左指针往右移动
            low = mid + 1;
        } else if (nums[mid] > key) { // key<mid, 把右指针往左移动
            high = mid - 1;
        } else {
            return mid; // 查找到元素, 返回
        }
    }
    return -1;
}



博学之,审问之,慎思之,明辨之,笃行之。

--《中庸》