数据结构与算法之美-10 |二分查找

一、二分查找的思想

二分查找针对的是一个有序的数据集合,查找思想有点类似分治思想。每次都通过跟区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为 0。
二分查找的效率非常之高,时间复杂度为O(log(N)),这是一个相当惊人的时间复杂度。

二、二分查找的递归和非递归实现

一.递归实现

递归调用方法实现

二.非递归实现

while循环实现

三.递归和非递归的代码实现

package binarysearch;

public class binarySearchDemo {


    public static void main(String[] args) {
        //已经排好序的数组
        int[] MergeArray = {8, 11, 19, 23, 27, 33, 45, 55, 67, 98};//
        //需要寻找得值
        int tagret1 = 67;
        int tagret2 = 8;
        //排序方法
        binarySearchByRecursion(MergeArray, tagret2, 0, MergeArray.length - 1);

        binarySearchByWhile(MergeArray, tagret1, 0, MergeArray.length - 1);
    }

    //递归算法
    public static void binarySearchByRecursion(int[] MergeArray, int tagret, int indexlow, int indexhigt) {

        //1如果目标数据小于当前范围最小数据。2目标数据大于当前范围最大数据
        if (tagret > MergeArray[indexhigt] || tagret < MergeArray[indexlow]) {
            return;
        }
        int indexMiddle = indexlow + (indexhigt - indexlow) / 2;

        if (MergeArray[indexMiddle] > tagret) {
            binarySearchByRecursion(MergeArray, tagret, indexlow, indexMiddle - 1);
        } else if (MergeArray[indexMiddle] < tagret) {
            binarySearchByRecursion(MergeArray, tagret, indexMiddle + 1, indexhigt);
        } else if (MergeArray[indexMiddle] == tagret) {
            System.out.printf("找到目标数据" + MergeArray[indexMiddle]);
        } else {
            System.out.println("目标数据不在数据范围内");
        }
    }

    //WHILE查找
    public static void binarySearchByWhile(int[] MergeArray, int tagret, int indexlow, int indexhigt) {

        if (indexlow > indexhigt) {
            return;
        }
        while (indexlow <= indexhigt) {

            int indexMiddle = indexlow + (indexhigt - indexlow) / 2;
            if (indexhigt == indexlow && indexhigt - indexlow == 0) {
                if (MergeArray[indexMiddle] == MergeArray[indexlow]) {
                    System.out.printf("找到目标数据" + MergeArray[indexMiddle]);
                    return;
                }
            } else if (MergeArray[indexMiddle] > tagret) {
                indexhigt = indexMiddle - 1;
            } else if (MergeArray[indexMiddle] < tagret) {
                indexlow = indexMiddle + 1;

            } else if (MergeArray[indexMiddle] == tagret) {
                System.out.printf("找到目标数据" + MergeArray[indexMiddle]);
                return;
            } else {
                System.out.println("目标数据不在数据范围内");
                return;
            }
        }
    }
}

三、二分查找的易错点

一.循环退出条件

注意是 low<=high,而不是 low

二.mid 的取值

改进的方法是将 mid 的计算方式写成 low+(high-low)/2。更进一步,如果要将性能优化到极致的话,可以将这里的除以 2 操作转化成位运算 low+((high-low)>>1)。

三.low 和 high 的更新

low=mid+1,high=mid-1。注意这里的 +1 和 -1,如果直接写成 low=mid 或者 high=mid,就可能会发生死循环。比如,当 high=3,low=3 时,如果 a[3]不等于 value,就会导致一直循环不退出。

四、二分查找的局限性

一.二分查找依赖的是顺序表结构

二分查找只能用在数据是通过顺序表来存储的数据结构上。如果你的数据是通过其他数据结构存储的,则无法应用二分查找。

二.二分查找针对的是有序数据

二分查找对这一点的要求比较苛刻,数据必须是有序的。如果数据没有序,需要先排序。

三.数据量太小不适合二分查找

如果要处理的数据量很小,完全没有必要用二分查找,顺序遍历就足够了。比如我们在一个大小为 10 的数组中查找一个元素,不管用二分查找还是顺序遍历,查找速度都差不多。只有数据量比较大的时候,二分查找的优势才会比较明显。

四.数据量太大也不适合二分查找

二分查找的底层需要依赖数组这种数据结构,而数组为了支持随机访问的特性,要求内存空间连续,对内存的要求比较苛刻。比如有 1GB 大小的数据,如果希望用数组来存储,那就需要 1GB 的连续内存空间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值