数据结构与算法——查找算法

目录

一、查找算法

1.1 分类

二、线性查找(SequenceSearch)

2.1 基本思想

2.2 线性查找算法实现

三、二分查找(BinarySearch)

3.1 基本思想

3.2 二分查找算法实现

四、插值查找(InterpolationSearch)

4.1 基本思想

4.2 期望索引值公式

4.3 插值查找算法实现

五、斐波那契查找(FibonacciSearch)

5.1 基本介绍

5.2 基本思想

5.3 期望索引值公式

5.4 斐波那契查找算法实现


一、查找算法

1.1 分类

  • 线性查找
  • 二分查找
  • 插值查找
  • 斐波那契查找

二、线性查找(SequenceSearch)

2.1 基本思想

逐一比对待排序序列,找出待查找元素的下标。

2.2 线性查找算法实现

代码:

public class SequenceSearch {
    public static void main(String[] args) {
        int arr[] = {8, 9, 1, 7, 2, 3, 5, 4, 6, -1};
        int index = search(arr, 2);
        if (index == -1) {
            System.out.println("序列中不存在该元素。");
        } else {
            System.out.println("该元素下标为:" + index);
        }
    }

    public static int search(int[] arr, int value) {
        //逐一比对待排序序列
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == value) {
                return i;
            }
        }
        return -1;
    }
}

结果: 


三、二分查找(BinarySearch)

3.1 基本思想

先确定有序序列的中间下标,然后向左右两边递归进行二分查找,直到中间下标为待查找元素的下标

3.2 二分查找算法实现

代码:

public class BinarySearch {
    public static void main(String[] args) {
        int arr[] = {-1, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        int index = search(arr, 0, arr.length - 1, 5);
        if (index == -1) {
            System.out.println("序列中不存在该元素。");
        } else {
            System.out.println("该元素下标为:" + index);
        }
    }

    public static int search(int[] arr, int startIndex, int endIndex, int value) {
        if (startIndex > endIndex || value < arr[0] || value > arr[arr.length - 1]) {
            return -1;
        }
        //定义中间元素下标
        int mid = (startIndex + endIndex) / 2;
        //定义中间元素值
        int midVal = arr[mid];

        if (value > midVal) {
            //向右递归
            return search(arr, mid + 1, endIndex, value);
        } else if (value < midVal) {
            //向左递归
            return search(arr, startIndex, mid - 1, value);
        } else {
            return mid;
        }
    }
}

结果:


四、插值查找(InterpolationSearch)

4.1 基本思想

类似于二分查找,但改变了每次查找的期望索引值。

4.2 期望索引值公式

Expectation = startIndex + (endIndex - startIndex) * (value - arr[startIndex]) / (arr[endIndex] - arr[startIndex])

4.3 插值查找算法实现

代码:

public class InterpolationSearch {
    public static void main(String[] args) {
        int arr[] = {-1, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        int index = search(arr, 0, arr.length - 1, 5);
        if (index == -1) {
            System.out.println("序列中不存在该元素。");
        } else {
            System.out.println("该元素下标为:" + index);
        }
    }

    public static int search(int[] arr, int startIndex, int endIndex, int value) {
        if (startIndex > endIndex || value < arr[0] || value > arr[arr.length - 1]) {
            return -1;
        }
        //定义期望元素下标
        int expectation = startIndex + (endIndex - startIndex) * (value - arr[startIndex]) / (arr[endIndex] - arr[startIndex]);
        //定义期望元素值
        int expectationVal = arr[expectation];

        if (value > expectationVal) {
            //向右递归
            return search(arr, expectationVal + 1, endIndex, value);
        } else if (value < expectationVal) {
            //向左递归
            return search(arr, startIndex, expectationVal - 1, value);
        } else {
            return expectationVal;
        }
    }
}

结果:


五、斐波那契查找(FibonacciSearch)

5.1 基本介绍

斐波那契查找算法又称黄金分割查找算法,黄金分割点是指把一条线段分割成两部分,使其中一部分与全长之比等于另一部分与该部分之比,该比值的近似值为0.618。

相邻两个元素之比无限接近黄金分割值的数列被称为斐波那契数列。

5.2 基本思想

类似于二分查找,但改变了每次查找的期望索引值,该期望索引值位于黄金分割点附近。

5.3 期望索引值公式

Expectation = startIndex + F(k - 1) - 1,F表示斐波那契数列。

  • 由斐波那契数列F(k) = F(k - 1) + F(k - 2)的性质可得:(F(k) - 1) = (F(k - 1) - 1) + (F(k - 2) - 1) + 1,该式说明只要有序序列的长度为F(k) - 1,则可以将该序列分成长度为F(k - 1) - 1和F(k - 2) - 1的两部分,期望索引值的下标为startIndex + F(k - 1) - 1。
  • 当有序序列的长度不为F(k) - 1时,需要将该序列的长度增加至F(k) - 1。

5.4 斐波那契查找算法实现

代码:

public class FibonacciSearch {

    //定义斐波那契数列的长度
    public static int maxSize = 20;

    public static void main(String[] args) {
        int arr[] = {-1, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        int index = search(arr, 5);
        if (index == -1) {
            System.out.println("序列中不存在该元素。");
        } else {
            System.out.println("该元素下标为:" + index);
        }
    }

    public static int search(int[] arr, int value) {
        //定义头指针
        int startIndex = 0;
        //定义尾指针
        int endIndex = arr.length - 1;
        //定义期望元素下标
        int expectation = 0;
        //定义斐波那契分割数值的下标
        int k = 0;
        //定义斐波那契数列
        int[] f = fibonacci();
        //获取斐波那契分割数值
        while (endIndex > f[k] - 1) {
            k++;
        }
        //有序序列长度不足时增加其长度,存入临时数组中,不足部分使用arr数组末尾的值进行填充
        int[] temp = Arrays.copyOf(arr, f[k]);
        for (int i = endIndex + 1; i < temp.length; i++) {
            temp[i] = arr[endIndex];
        }

        while (startIndex <= endIndex) {
            expectation = startIndex + f[k - 1] - 1;
            //定义期望元素值
            int expectationVal = arr[expectation];

            if (value > expectationVal) {
                //向右查找
                startIndex = expectation + 1;
                //右边的有序序列有f[k-2]个元素,可拆分成f[k-2]=f[k-3]+f[k-4],k-2作为新的斐波那契分割数值的下标
                k -= 2;
            } else if (value < expectationVal) {
                //向左查找
                endIndex = expectation - 1;
                //左边的有序序列有f[k-1]个元素,可拆分成f[k-1]=f[k-2]+f[k-3],k-1作为新的斐波那契分割数值的下标
                k--;
            } else {
                //判断查找到的元素下标是否位于增加出的部分,是则返回数组末尾下标
                if (expectation <= endIndex) {
                    return expectation;
                } else {
                    return endIndex;
                }
            }
        }
        return -1;
    }

    //获取斐波那契数列
    public static int[] fibonacci() {
        int[] f = new int[maxSize];
        f[0] = 1;
        f[1] = 1;
        for (int i = 2; i < maxSize; i++) {
            f[i] = f[i - 1] + f[i - 2];
        }
        return f;
    }
}

结果:

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值