查找算法

一、线性查找

  源码:线性查找

1,思路

  线性查找又称顺序查找,是一种最简单的查找方法,它的基本思想是从第一个记录开始,逐个比较记录的关键字,直到和给定的K值相等,则查找成功;若比较结果与文件中n个记录的关键字都不等,则查找失败。

2,特点

  • 按顺序查找,数组(集合)可以无序  
  • 时间复杂度:O(N)

3,代码实现

/**
 * 线性查找找到一个满足条件的值就返回
 */
public static int seqSearch(int[] arr, int value) {
    // 线性查找是逐一比对,发现有相同值,就返回下标
    for (int i = 0; i < arr.length; i++) {
        if (arr[i] == value) {
            return i;
        }
    }
    return -1;
}
View Code

二、二分查找(折半)

  源码:二分查找

1,思路

1)定义两个辅助指针:left、right ,待查找的元素在 arr[left]~arr[right] 之间
2)eft 初始值为 0 ,right 初始值为 arr.length - 1
3)将数组分成两半:int mid = (left + right) / 2; ,取数组中间值与目标值 findVal 比较
    如果 mid > val,说明待查找的值在数组左半部分,令right = mid-1 递归查
    如果 mid < val ,说明待查找的值在数组右半部分,令left = mid+1递归查
    如果 mid == val,查找到目标值,返回mid即可
4)未找到目标值:left > right ,直接返回-1

2,特点

  • 数组(集合)必须有序
  • 时间复杂度:O(log2N)

3,代码实现

/**
 * 二分查找算法
 */
public static int binarySearch(int[] arr, int left, int right, int val) {
    if (left > right) {
        return -1;
    }
    int mid = (left + right) / 2;
    if (val > arr[mid]) {
        return binarySearch(arr, mid + 1, right, val);
    } else if (val < arr[mid]) {
        return binarySearch(arr, left, mid - 1, val);
    } else {
        return mid;
    }
}
View Code

三、插值查找

  源码:插值查找

1,介绍

  • 插值查找算法类似于二分查找, 不同的是插值查找每次从自适应 mid 处开始查找。
  • 求mid的公式为:int mid = low + (high - low) * (key - arr[low]) / (arr[high] - arr[low])

  

2,思路

基本与二分查找相同,不同之处为:
1,求mid的公式不同:int mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left])
2,判断未找到目标:left>right || val< arr[left] || val> arr[right]

3,特点

  • 数组(集合)必须有序
  • 对于数据量较大,关键字分布比较均匀(最好是线性分布)的查找表来说,采用插值查找,速度较快
  • 时间复杂度:O(log2(log2N))

4,代码实现

public static int insertValSearch(int[] arr,int left , int right,int val) {
    System.out.println("插值查找~~");
    if (left > right || arr[left] > val || arr[right] < val) {
        return -1;
    }
    int mid = left + (right - left) * (val - arr[left]) / (arr[right] - arr[left]);
    if (val > arr[mid]) {
        return insertValSearch(arr, mid + 1, right, val);
    } else if (val < arr[mid]) {
        return insertValSearch(arr, left, mid - 1, val);
    }else {
        return mid;
    }
}
View Code

四、斐波拉契查找算法

  源码:斐波拉契查找算法

1,思路 

 参考:斐波拉契查找简介

2,特点

  • 如果要查找的记录在右分区,则左分区的数据都不用再判断了,不断反复进行下去,对处于当中的大部分数据,其工作效率要高一些。所以,尽管斐波那契查找时间复杂度也为O(logn),但就平均性能来说,斐波那契查找要优于折半查找。可惜如果是最坏的情况,比如这里的key=1,那么始终都处于左分区在查找,则查找效率要低于折半查找。左分区要比右分区大嘛。
  • 时间复杂度:O(log2N)

3,代码

/**
 * 查找
 */
public static int fibonacciSearch(int[] arr, int val) {
    int left = 0;
    int right = arr.length - 1;
    int[] f = fib();
    int k = 0;
    while (right > f[k] - 1) {
        k++;
    }
    //拷贝临时数组  比原始数组长的部分会直接用0补齐
    int[] temp = Arrays.copyOf(arr, f[k]);
    //将长于arr部分用高位值补齐
    for (int i = right + 1; i < temp.length; i++) {
        temp[i] = arr[right];
    }
    int mid = 0;
    while (left <= right) {
        mid = left + f[k - 1] - 1;
        if (val < temp[mid]) {
            //向左找
            right = mid - 1;
            k--;
        } else if (val > temp[mid]) {
            //向右找
            left = mid + 1;
            k -= 2;
        } else {
            if (mid < right) {
                return mid;
            } else {
                //如果查到的是扩容之后的数值,就直接返right
                return right;
            }
        }

    }
    return -1;
}
View Code
posted @ 2020-12-09 22:19  MXC肖某某  阅读(409)  评论(0编辑  收藏  举报