【数据结构与算法】经典查找算法

1. 顺序查找(无序查找)

算法:
1. 序列无序(有序),适合遍历的数据结构
2. 遍历比对
    public static int sequenceSearch(int[] arr, int a) {
        for (int i = 0; i < arr.length; i++) {
            if (a == arr[i]) return i + 1;
        }
        return -1;
    }

2. 折半查找(有序查找)

算法:
1. 首先数列有序,该算法针对的是有序数列
2. 折半查找,给定值a与中间参考值(mid = low + 1/2 * (high - low),即(low + high) / 2)相比,若小于中间参考值,则给定值存在左侧,否则给定值存在右侧,通过迭代或者递归方式查询元素所在索引
    //二分查找,迭代版本
    public static Integer biSearch(int array[], int a) {
        int low = 0;
        int high = array.length - 1;
        int mid;
        while (low <= high) {
            mid = (low + high) / 2;
            if (array[mid] == a) {
                return mid + 1;
            } else if (a > array[mid]) {
                low = mid + 1; //向右查找
            } else {
                high = mid - 1;//向左查找
            }
        }
        return -1;
    }

    //二分查找,递归版本
    public static int biSearch2(int array[], int a, int low, int high) {
        if (low <= high) {
            int mid = (low + high) / 2;
            if (array[mid] == a)
                return mid;
            if (a < array[mid])
                return biSearch2(array, a, low, mid - 1);
            if (a > array[mid])
                return biSearch2(array, a, mid + 1, high);
        }
        return -1;
    }

 3. 插值查找(有序查找)

算法:
1. 插值查找是折半查找的优化版本,自适应:mid = low + (key - arr[low]) / (arr[high] - arr[low]) * (high - low)
    public static int insertionSearch(int[] arr, int key, int low, int high) {
        if (low <= high) {
            if (arr[low] == key) return low + 1;
            if (arr[high] == key) return high + 1;

            int mid = low + (key - arr[low]) / (arr[high] - arr[low]) * (high - low);
            if (arr[mid] == key)
                return mid + 1;
            if (arr[mid] > key)
                return insertionSearch(arr, key, low, mid - 1);
            if (arr[mid] < key)
                return insertionSearch(arr, key, mid + 1, high);
        }
        return -1;
    }
说明:插值查找又叫自适应查找,和折半查找相比,在数列元素均匀分布时,效率更高

4. 斐波那契查找(有序查找)

算法:
1. 构造斐波那契数列,选出一个合适的容量(选择一个比要排序的数列元素数量大且最近的一个)
2. 构建一个临时数列,将待排序数列放入,若不足用最高位填充
3. 构建参考元素mid=low + f[k - 1] - 1(见图知意,其实就是右侧那部分)
4. 若查找元素比参考元素小,说明查找元素落在左侧子序列,反之则落在右侧子序列
5. 重复步骤3、4,指导找到该查找元素(找不到返回-1)
public static int fibonacciSearch(int[] arr, int key) {
        //获取一个合适的斐波那契F[k]值
        int f[] = fibonacci();
        int k = 0;
        while (arr.length - 1 > f[k] - 1) {
            k++;
        }

        // 构建一个临时数组,若原始数列填充不满,则用原始数列最后一位进行填充
        int[] temp = Arrays.copyOf(arr, f[k]);
        for (int i = arr.length; i < temp.length; i++) {
            temp[i] = arr[arr.length - 1];
        }

        int low = 0;
        int high = arr.length - 1;
        int mid;
        while (low <= high) {
            mid = low + f[k - 1] - 1;
            if (key < temp[mid]) { //目标数据在左侧子序列
                high = mid - 1;
                k = k - 1;
            } else if (key > temp[mid]) { //目标数据在右侧子序列
                low = mid + 1;
                k = k - 2;
            } else {// 找到目标
                if (mid <= arr.length - 1) {
                    return mid;
                } else {
                    return arr.length - 1;//目标找到,但是是用最高位填充的数据,所以返回arr.length - 1
                }
            }
        }
        return -1;
    }

    public static final int MAXSIEZE = 20;

    // 构建一个斐波那契数列(K=20时,F[k]=6765,表示可以容纳6765个元素)
    public static int[] fibonacci() {
        int[] f = new int[MAXSIEZE];
        f[0] = 1;
        f[1] = 1;
        for (int i = 2; i < MAXSIEZE; i++) {
            f[i] = f[i - 1] + f[i - 2];
        }
        return f;
    }
说明:
1. 构建一个斐波那契,一般选择K就够测试的了,生产上则要根据数据量进行选择
2. 当斐波那契F[k]时,mid=low + f[k - 1] - 1,是因为一个数列其实是分成了两部分(如上图)

 

【说明】梳理知识用,有些地方未做验证,请保持怀疑态度

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值