一看就懂-图解二分查找和线性查找

前言

写个笔记记录下学习的查找算法。

查找是在大量的信息中寻找一个特定的信息元素,在某个容器中找到某数据所使用的算法,就是查找算法。

一、线性查找

给定一个查找值,在查找的容器中逐个查找给定值。

线性查找是最简单的查找算法。

代码实现:

创建一个数组{1, 9, 24, 20, 16, 14, 265}存储数据,遍历数组对比查到对应数据,拿出数据的坐标,得到数据。

package com.datastructure.search;

/**
 * @author Hacah
 * @date 2020/11/10 22:08
 */
public class SeqSearch {

    public static void main(String[] args) {
        int[] arr = {1, 9, 24, 20, 16, 14, 265};
        int i = seqSearch(arr, 14);
        System.out.println(i);
    }

    /**
     * 线性查找,返回对应数据在数组中的下标
     * @param arr  查找数组
     * @param seaInt 要查找的数据
     * @return
     */
    public static int seqSearch(int[] arr,int seaInt) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == seaInt) {
                return i;
            }
        }
        return -1;
    }
}

二、二分查找

二分查找使用分治思想,它是一种高效的查找方法。充分利用了元素间的次序关系。

实现思想

1.数组必须有序,把数组的数据按中间数分两段,判断小于、大于、等于,如果等于就找到了。2.如果查找数大于中间数就向中间数的右边找,小于就向中间数的左边找。3.重复步骤,直到找到数据。

查找算法在很多场景下运用广泛,若是对比线性查找二分查找是一个减少时间消耗,提高效率的好算法。

注:折半查找的前提条件是需要有序表顺序存储,对于静态查找表,一次排序后不再变化,折半查找能得到不错的效率。但对于需要频繁执行插入或删除操作的数据集来说,维护有序的排序会带来不小的工作量,那就不建议使用。——《大话数据结构》

图解实现

假设要找16,定义两个变量left,right存储一段数组的左边和右边下标

通过 (left + right) / 2得到中值midIndex。

比较midIndex与我们要找的16,由于13小于16所以向左边寻找,就如下图。

得到 (left + right) / 2中值midIndex是4,所以如下图。

比较midIndex与查找的数据,两个数相等,返回数据16的下标4,完成查询。

代码实现

创建数组{11, 45, 5, 5, 945, 248, 52, 93, 945},实现二分查找算法找到945的位置。

package com.datastructure.search;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * @author Hacah
 * @date 2020/11/12 22:57
 */
public class BinarySearch {

    public static void main(String[] args) {
        int[] arr = {11, 45, 5, 5, 945, 248, 52, 93, 945};
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
//        int a = binarySearch(0, arr.length - 1, arr, 52);
//        System.out.println(a);
        ArrayList arrayList = binarySearchs(0, arr.length - 1, arr, 945);
        System.out.println(arrayList);

    }


    /**
     * 二分查找法
     *
     * @param left  左指针
     * @param right 右指针
     * @param arr   数组
     * @param value 查找的值
     */
    public static int binarySearch(int left, int right, int[] arr, int value) {
        int midIndex = (left + right) / 2;
        int midValue = arr[midIndex];

        if (left <= right) {
            if (value < midValue) {
                return binarySearch(left, midIndex - 1, arr, value);
            } else if (value > midValue) {
                return binarySearch(midIndex + 1, right, arr, value);
            } else if (value == midValue) {
                return midIndex;
            }
        }

        return -1;
    }


    /**
     * 查询多个结果
     * @param left
     * @param right
     * @param arr
     * @param value
     * @return
     */
    public static ArrayList binarySearchs(int left, int right, int[] arr, int value) {
        int midIndex = (left + right) / 2;
        int midValue = arr[midIndex];

        if (left <= right) {
            if (value < midValue) {
                return binarySearchs(left, midIndex - 1, arr, value);
            } else if (value > midValue) {
                return binarySearchs(midIndex + 1, right, arr, value);
            } else if (value == midValue) {
                ArrayList list = new ArrayList<>();
                list.add(midIndex);
                // midValue的左边
                int temp = midIndex - 1;
                while (temp >= 0 && value == arr[temp]) {
                    list.add(temp);
                    temp--;
                }
                // midValue的右边
                int tempR = midIndex + 1;
                while (tempR <= right && value == arr[tempR]) {
                    list.add(tempR);
                    tempR++;
                }
                return list;
            }
        }

        return null;
    }
}

适用场景

•二分查找元素较多的数列•二分查找前提必须数列有序,无序需要排序,确认是否代价符合实际。

你可能感兴趣的:(一看就懂-图解二分查找和线性查找)