前奏
前奏:插值查找是一种对折半查找算法的一种升级版,也是一种自适应查找算法(按照对应查找的值,设置对应的比例中间值查找)
思路
核心思路就是,当前元素位置差 left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);
注意:如果left和right都指向了同一个元素的时候就要注意在添加一个判断条件searchElement<arr[left]||searchElement>arr[right])否者会出现算数异常
注意事项
1:对于数据量较大,各个之间的相依数值跨距(数值差)不是很大,分布均匀(如:100,200,300,400),采用插值查找算法,速度较快
2:如果与第一条事项相反就用折半查找
3:动态计算比例注意:如果你查找的值及整个有序数组的长度很如:千万 这时候千万别用int类型 至少要转换成long 类型不然动态计算比例会出现运算异常
4:循环判断时候注意:searchElement<arr[left]||searchElement>arr[right]),这个递归判断条件非常的重要
图解1
代码
注意:动态计算超大数据长度的数组时 有可能会出现 栈溢出情况 需谨慎使用
int[] newArray = new int[60000000];
for (int i = 0; i < 60000000; i++) {
newArray[i] =(int) (Math.random() * 60000000);
}
Long startTime=System.currentTimeMillis();
//获取排序后内容信息
QuickSortDemo.quickSortTheDataDigPit(newArray,0,newArray.length-1);
Long endTime=System.currentTimeMillis();
System.out.println(endTime-startTime+"耗时(排序时间)");
long [] newArray2=new long[newArray.length];
for(int index=0;index<newArray.length;index++){
newArray2[index]=newArray[index];
}
startTime=System.currentTimeMillis();
System.out.println(insertValueSearch(newArray2,0,newArray.length-1,59992312)+"==动态比例查找");
endTime=System.currentTimeMillis();
System.out.println(endTime-startTime+"耗时(毫秒)");
startTime=System.currentTimeMillis();
System.out.println(search(newArray2,59992312)+"==线性查找索引");
endTime=System.currentTimeMillis();
System.out.println(endTime-startTime+"耗时(毫秒)");
//注意:searchElement<arr[left]||searchElement>arr[right]),这个递归判断条件非常的重要
//编写插值查找算法
//说明:插值查找算法,也要求数组是有序的
/**
*
* @param arr 数组
* @param left 左边索引
* @param right 右边索引
* @param findVal 查找值
* @return 如果找到,就返回对应的下标,如果没有找到,返回-1
*/
public static int insertValueSearch(long[] arr, int left, int right, int findVal) {
//注意:findVal < arr[0] 和 findVal > arr[arr.length - 1] 必须需要
//否则我们得到的 mid 可能越界
if (left > right || findVal < arr[0] || findVal > arr[arr.length - 1]) {
return -1;
}
// 求出mid, 自适应
int mid = new Long(left + (right-left)*(findVal - arr[left])/(arr[right] - arr[left])).intValue();
long midVal=arr[mid];
if (findVal > midVal) { // 说明应该向右边递归
return insertValueSearch(arr, mid + 1, right, findVal);
} else if (findVal < midVal) { // 说明向左递归查找
return insertValueSearch(arr, left, mid - 1, findVal);
} else {
return mid;
}
}