查找算法——插值查找
- 基本介绍:插入算法是采用了自适应mid的二分查找,更加快速
- 原理介绍:将二分查找中求mid索引的公式变成:mid = left + (key -arr[left]) / (arr[right] - arr[left]) * (right - left),其中key为所需要查找的值。将key待查找值与总长度作比较,然后转化成对应的索引长度。
- 弥补二分查找的缺陷:当用二分法查找一组有序数列的初始值时,会通过多次递归,必须将索引递归到底。但是插值查找会根据所要查找的数字的值相对于整个有序数组所在的区间索引所在的位置确定他的索引。
- 代码实现:
package insertsearch;
import java.util.ArrayList;
import java.util.List;
public class InsertSearch {
public static void main(String[] args) {
int[] arr = {1, 4, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19};
System.out.println(insertSearch(arr, 0, arr.length - 1, 0));
}
public static List<Integer> insertSearch(int[] arr, int left, int right, int searchVal) {
int mid = left + (searchVal - arr[left]) / (arr[right] - arr[left]) * (right - left);
if (left > right || searchVal > arr[right - 1] || searchVal < arr[left]) {
return new ArrayList<Integer>();
}
if (arr[mid] < searchVal) {
return insertSearch(arr, mid + 1, right, searchVal);
} else if (arr[mid] > searchVal) {
return insertSearch(arr, left, mid - 1, searchVal);
} else {
List<Integer> list = new ArrayList<>();
int temp = mid - 1;
while (arr[temp] == arr[mid] && temp >= 0) {
list.add(temp);
temp--;
}
list.add(mid);
temp = mid + 1;
while (arr[temp] == arr[mid] && temp <= right) {
list.add(temp);
temp++;
}
return list;
}
}
}
分析与总结:
- 对于不在有序序列之内的数字,比如比最小值还小的数,会出现mid<0的情况,所以提前排除这种情况。首先对所需要搜索的数字进行判断,是否在对应的区间之内。
- 在折中算法的基础上加上自适应mid确实能够有效改善算法本身
- 注意:
- 对于数据量较大,关键字分布比较均匀的查找表来说,采用插值查找速度比较快
- 关键字分布不均匀就是情况而定了