一:插值查找
代码公式:int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);
1.1 基本概念
插值查找,有序表的一种查找方式。插值查找是根据查找关键字与查找表中最大最小记录关键字比较后的查找方法。插值查找基于二分查找,将查找点的选择改进为自适应选择,提高查找效率。插值查找是在二分查找的基础上进行的改进,二分查找每次将查找的范围缩小一半,即mid=(low+high) / 2
可以看出,折半查找是一种机械式的查找方式,不是自适应的。因此, 在数值分布相对均匀的查找表中, 我们将计算mid的方式改为自适应的查找,即mid=low+(key-a[low])/(a[high]-a[low])*(high-low)
能够有效提高查找的效率
1.2 基本思想
- 插值查找类似平时我们查字典的时候,查一个以 s 开头的单词时,绝对不会用二分查找,从字典的中间第一页开始,因为我们知道它的大概位置是在字典的较后面部分,所以可以从后面的某处查起。我们先从首字母 s 的地方开始查找,然后再根据第二个字母在字母表中的位置,找到对应位置再继续查找,这样重复这个过程,直到找到我们查找的这个单词这就是插值查找的基本思想
- 插值查找除了要求查找的数据是顺序存储的有序数据外,还要求根据元素的关键字在数据中均匀分布,这样就可以按照比例插值
1.3 原理介绍
- 插值查找算法类似于二分查找,不同的是插值查找每次从自适应mid处开始查找。
- 将折半查找中的求mid 索引的公式 , low 表示左边索引left, high表示右边索引right,key 就是前面我们讲的 findValue
二:代码实现
package com.sysg.dataStructuresAndAlgorithms.find;
/**
* 插值查找
*/
public class InsertValueSearch {
public static void main(String[] args) {
int[] array = new int[100];
for (int i = 0; i < 100; i++) {
array[i] = i + 1;
}
int index = insertValueSearch(array, 0, array.length - 1, 5);
System.out.println(index);
}
/**
* 插值查找算法
*
* @param array 原始数组
* @param left 左节点
* @param right 右节点
* @param findValue 需要查找的值
* @return 如果找到,就返回查找值得下标。如果找不到就返回-1
*/
public static int insertValueSearch(int[] array, int left, int right, int findValue) {
if (left > right || findValue < array[0] || findValue > array[array.length - 1]) {
return -1;
}
//求出middle,自适应的值
int middle = left + (right - left) * (findValue - array[left]) / (array[right] - array[left]);
//获取中间值
int middleValue = array[middle];
if (findValue > middleValue) {
//如果需要查找的值大于中间值,则向右递归
return insertValueSearch(array, middle + 1, right, findValue);
} else if (findValue < middleValue) {
//如果需要查找的值小于中间值,则向左递归
return insertValueSearch(array, left, middle - 1, findValue);
} else {
return middle;
}
}
}