2020-08-26

插值查找算法

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

插值查找原理:

(1)插值查找类似于二分查找,不同的是自适应的mid的值不一样。
(2)二分查找的mid = (left + right) / 2
插值查找的 mid = left + (right-left)*(findVal - arr[left])/(arr[right]-arr[left])
在这里插入图片描述

(3)插值查法对于数据量大,数据分布比较均匀的时候,使用插值查法效率较高。
但在数据分布不均匀的时候,使用此方法查找不一定好。

例子(从1 2 3 .......100)的数组查找100,此时需要查找的次数为:
由 mid = left + (right-left)*(findVal - arr[left])/(arr[right]-arr[left])得,
mid = 0 + (99 - 0) * (100-1) / (100-1) = 99
所以最后只需要查找一次即可把100找出来,所以当数据分布均匀,数据量大的时候,插值查找效率较高

实现代码:

package com.java;

import java.util.ArrayList;
import java.util.List;

public class InsertValueSearch {
    public static void main(String[] args) {
        int[] arr = {-1,-1,23,54,88,95,123,153,175};
        System.out.println(insertValueSearch(arr, 0, arr.length - 1, -1));
    }
    //定义插值查找法
    public static List insertValueSearch(int[]arr,int left,int right,int findVal)
    {
        //当左索引大于右索引或者需查找的值小于最小值或者大于最大值时,退出
        if (left > right||findVal<arr[0]||findVal>arr[arr.length-1])
            return null;
        //求出mid
        int mid = left + (right-left)*(findVal - arr[left])/(arr[right]-arr[left]);
        //此时需查找的值小于arr[mid],向左递归
        if (findVal<arr[mid])
            return insertValueSearch(arr,left,mid-1,findVal);
        //此时需查找的值大于arr[mid],向右递归
        else if (findVal>arr[mid])
            return insertValueSearch(arr,mid+1,right,findVal);
        else
        {
            //此时找到需要查找的值,但要进行进一步处理,因为这个值在arr[mid]中有可能会重复
            //所以要从mid左、右两边查找是否还有相同的值

            //定义一个ArrayList,把相同的值放入
            List<Integer> list = new ArrayList<>();
            int temp = mid - 1;//定义一个辅助指针,帮助寻找
            //从mid左边开始寻找是否还有相同的值
            while (true)
            {
                //当temp<0或者findVal != arr[mid]时,退出循环
                if (temp<0 || findVal != arr[temp]) break;
                //把找到值的索引放入list中
                list.add(temp);
                temp -= 1;//左移
            }
            //把mid放入list中
            list.add(mid);

            //从mid右边开始寻找是否还有等于findVal的值
            temp = mid + 1;//初始化temp
            while (true)
            {
                //当temp>arr.length-1或者findVal != arr[mid]时,退出循环
                if (temp>arr.length-1||findVal!=arr[temp])
                    break;
                list.add(temp);
                temp+=1;
            }
            return list;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/zzFZJ_/article/details/108238994