插值查找
简介
插值查找是根据查找关键字与查找表中最大最小记录关键字比较后的查找方法。插值查找基于二分查找,将查找点的选择改进为自适应选择,提高查找效率。适合于关键字值分布均匀的集合,前提是集合的数据是有序的。
公式:left表示左边索引,right表示右边索引,value为查找值。int mid = left+(right - left)*(value- arr[left]) / (arr[right] - arr[left]);
代码
/**
* @param arr 数组
* @param left 数组左边的索引
* @param right 数组右边的索引
* @param value 要查找的数字
* @return 找到值的下标,没找到就返回空集合
*/
public static List<Integer> insertValueSearch (int[] arr,int left,int right,int value) {
System.out.println("插值查找======");
if (left > right || value < arr[0] || value > arr[arr.length - 1]) {
return new ArrayList<>();
}
int mid = left+(right - left)*(value- arr[left]) / (arr[right] - arr[left]);
int midValue = arr[mid];
if (value > midValue) {
return insertValueSearch(arr,mid + 1,right,value);
} else if (value < midValue) {
return insertValueSearch(arr,left,mid - 1,value);
} else {
List<Integer> list = new ArrayList<>();
list.add(mid);
int temp = mid - 1;
//向左递归
while (temp >= 0 && arr[temp] == value) {
list.add(temp);
temp -= 1;
}
temp = mid + 1;
//向右递归
while (temp <= arr.length - 1 && arr[temp] == value) {
list.add(temp);
temp += 1;
}
return list;
}
}
测试
int[] arr = new int[50];
for (int i = 0; i < 50; i++) {
arr[i] = i + 1;
}
List<Integer> list = insertValueSearch(arr,0,arr.length - 1,1);
if (!list.isEmpty()) {
System.out.println("list = " + Arrays.toString(list.toArray()));
} else {
System.out.println("没有找到");
}
}
在看看二分查找
/**
* @param arr 数组
* @param left 数组左边的索引
* @param right 数组右边的索引
* @param value 要查找的数字
* @return 找到值的下标,没找到就返回空集合
*/
public static List<Integer> binarySearch2 (int[] arr, int left, int right, int value) {
System.out.println("二分查找=========");
if (left > right || value < arr[0] || value > arr[arr.length - 1]) {
return new ArrayList<>();
}
int mid = (left + right) / 2;
int midValue = arr[mid];
if (value > midValue) {
return binarySearch2(arr,mid + 1,right,value);
} else if (value < midValue) {
return binarySearch2(arr,left,mid - 1,value);
} else {
List<Integer> list = new ArrayList<>();
list.add(mid);
int temp = mid - 1;
//向左递归
while (temp >= 0 && arr[temp] == value) {
list.add(temp);
temp -= 1;
}
temp = mid + 1;
//向右递归
while (temp <= arr.length - 1 && arr[temp] == value) {
list.add(temp);
temp += 1;
}
return list;
}
}
相比之下还是有提高的