开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第二十二天,点击查看活动详情
前言:上一文大家了解到了二分查找算法,接下来给大家详细解说插值查找并温故一下二分查找的思路~
二分查找 / 折半查找
- 必须是顺序的数组,若是无序的,则需要先排序(小到大 / 大到小)
思路
(以下是排序已为由小到大)
-
首先确定该数组的中间下标
- mid = (left + right)/ 2
-
然后让需要查找的数 findValue 和 arr[mid] 进行比较
- findValue > mid[arr] :说明要查找的数在 mid 的右边,应该向右查找(向右递归查找)
- findValue < mid[arr] :说明要查找的数在 mid 的左边,应该向左查找(向左递归查找)
- findValue = mid[arr] :说明已经找到,则返回
-
退出递归
- 找到目标退出递归
- 找不到退出递归 (==left > right==)
插值查找
-
也是得用在==有序数组==上
-
插值查找每次从自适应mid处开始查找
-
将折半查找中的求mid 索引的公式 , low 表示左边索引left, high表示右边索引right. key 就是 findValue
int mid = low + (high - low) * (key - arr[low]) / (arr[high] - arr[low]) ;
对应前面的代码公式: int mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left])
特点
- 可以一次就能查找想要的结果
- 与二分查找相比, 想过肯定的好很多的
使用场景
- 对于数据量较大,关键字分布比较均匀的查找表来说,采用插值查找, 速度较快
- 关键字分布不均匀的情况下,该方法不一定比折半查找要好
/**
* @author Kcs 2022/9/6
*/
public class InsertValueSearch {
public static void main(String[] args) {
//1 ~ 100 数组
int[] array = new int[100];
for (int i = 0; i < 100; i++) {
array[i] = i + 1;
}
int index = insertValueSearch(array, 0, array.length - 1, 50);
System.out.println("index = " + index);
}
/**
* 插值查找算法
* @param array 查找的数组
* @param left 左边 索引
* @param right 右边索引
* @param findValue 查找的值
* @return index
*/
public static int insertValueSearch(int[] array, int left, int right, int findValue) {
System.out.println("查找了!!!!");
//不符合,则退出 优化查找,防止mid越界。自适应的查找
if (left > right || findValue < array[0] || findValue > array[array.length - 1]) {
return -1;
}
//求出mid
int mid = left + (right - left) * (findValue - array[left]) / (array[right] - array[left]);
//中间的值
int midValue = array[mid];
if (findValue > midValue) {
//向右递归查找
return insertValueSearch(array, mid + 1, right, findValue);
} else if (findValue < midValue) {
//向左递归查找
return insertValueSearch(array, left, mid - 1, findValue);
} else {
//相等
return mid;
}
}
}