🧡数据结构与算法🧡从零到有系列《九》查找算法

225 阅读2分钟

这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战

查找算法

在java程序中一般常用到四种查找方式。顺序查找(线性),二分查找,插值查找,斐波那契查找

 

1. 线性查找算法

线性查找又称顺序查找,是一种最简单的查找方法,它的基本思想是从第一个记录开始,逐个比较记录的关键字,直到和给定的K值相等,则查找成功;

image.png

2. 二分查找算法

二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列

2.1 二分查找算法原理

image.png

2.2 二分查找代码

/**
* author:韩国庆

 * date:2021/3/15 15:33

 * version:1.0

 */

public class Sort {

 

    public static void main(String[] args) {

        int[] arrays = {1,4,6,8,9,10,20};

        int startIndex = 0;

        int endIndex = arrays.length-1;

        System.out.println(search(arrays,startIndex,endIndex,8));;

 

    }

 

    public static int search(int[] arrays,int start,int end,int val){

        if (start>end){

            return -1;

        }

        int mid = (start+end)/2;

        int midVal = arrays[mid];

        if (val>midVal){

            return search(arrays,mid+1,end,val);

        }else if (val<midVal){

            return search(arrays,start,mid-1,val);

        }else {

            return mid;

        }

 

    }

}

3. 插值查找算法

插值查找,有序表的一种查找方式。插值查找是根据查找关键字与查找表中最大最小记录关键字比较后的查找方法。插值查找基于二分查找,将查找点的选择改进为自适应选择,提高查找效率。  

3.1 插值查找算法原理

image.png

当我们从字典中查找 “algorithm” 这个单词的时候,我们肯定不会傻傻地像二分查找一样首先从中间开始。相反,我们会从首字母为 a 的地方开始查找,然后根据第二个字母在字母表中的位置,找到相应的位置再继续查找,这样重复这个过程,直到我们查找到这个单词。  

3.1.1 插值查找代码

/**

 * author:韩国庆

 * date:2021/3/15 15:33

 * version:1.0

 */

public class Sort {

 

    public static void main(String[] args) {

        int[] arrays = {1,4,6,8,9,10,20};

        int startIndex = 0;

        int endIndex = arrays.length-1;

        System.out.println(insertSearch(arrays,startIndex,endIndex,8));;

 

    }

 

    /**

     * 插值查找

     */

    public static int insertSearch(int[] arr,int left,int right,int searchVal){

 

        /**

         * 判断,防止越界,searchVal<array[0] ,searchVal>array[arr.length-1]

         */

        if (left>right || searchVal<arr[0] || searchVal>arr[arr.length-1]){

            return -1;

        }
        int mid = left+(right-left)*(searchVal-arr[left])/(arr[right]-arr[left]);

        int midVal = arr[mid];

        if (searchVal>midVal){

            return insertSearch(arr,mid+1,right,searchVal);

        }else if (searchVal<midVal){

            return insertSearch(arr,left,mid-1,searchVal);

        }else {

            return mid;

        }

 

 

}

}

4. 黄金分割法算法(斐波那契算法)

4.1 介绍

在介绍斐波那契查找算法之前,先介绍一下很它紧密相连的一个概念——黄金分割。黄金比例又称黄金分割,是指事物各部分间一定的数学比例关系,即将整体一分为二,较大部分与较小部分之比等于整体与较大部分之比,其比值约为1:0.618或1.618:1。因此被称为黄金分割。斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89…….(从第三个数开始,后边每一个数都是前两个数的和)。然后我们会发现,随着斐波那契数列的递增,前后两个数的比值会越来越接近0.618,利用这个特性,我们就可以将黄金比例运用到查找技术中。

image.png

4.1.1 黄金分割法代码

package com.bjpowernode.sort;

 

import java.time.Year;

import java.util.Arrays;

 

/**

 * author:韩国庆

 * date:2021/3/19 14:09

 * version:1.0

 */

public class FibonacciSearch {

 

    public static void main(String[] args) {

        int[] arrays = {1, 4, 6, 8, 9, 10, 20};

        System.out.println(sort(arrays, 20));

 

    }
    
    /**

     * 黄金分割算法

     */

    public static int sort(int[] arrays, int key) {

 

        int low = 0;

        int hight = arrays.length - 1;

 

        /**

         * 表示斐波那契分割数值下标

         */

        int k = 0;

 

        /**

         * 存放mid值的

         */

        int mid = 0;

 

        int[] fib = fbnq();

 

        while (hight > fib[k] - 1) {

            k++;

        }

 

        /**

         * 因为fib[k]值可能大于arrays的长度,因此我们需要使用Arrays类构造一个新的数组temp,并且指向它。没有值的地方

         * 使用0填充

         */

        int[] temp = Arrays.copyOf(arrays, fib[k]);
        for (int i = hight + 1; i < temp.length; i++) {

            temp[i] = arrays[hight];

        }

 

        /**

         * 使用while循环处理,找到我们的key

         */

        while (low <= hight) {

            mid = low + fib[k - 1] - 1;

            if (key < temp[mid]) {

                hight = mid - 1;

 

                /**

                 * 前面元素+后面的元素 = 全部元素

                 * f[k-1] + f[k-2] = f[k]

                 */

                k--;

            } else if (key > temp[mid]) {

                low = mid + 1;

 

                k -= 2;

            } else {//找到的

                if (mid <= hight) {

                    return mid;

                } else {

                    return hight;

                }

            }
            }

 

        return -1;

    }

 

    public static int[] fbnq() {

        int[] fib = new int[20];

        fib[0] = 1;

        fib[1] = 1;

        for (int i = 2; i < fib.length; i++) {

            fib[i] = fib[i - 1] + fib[i - 2];

        }

        return fib;

    }

 

}