参考:https://www.cnblogs.com/lsqin/p/9342929.html
源码:https://github.com/sunrui849/selectAlgorithm
目录:顺序查找
插值查找
算法简介
插值查找是根据要查找的关键字key与查找表中最大最小记录的关键字比较后的 查找方法,其核心就在于插值的计算公式 (key-a[low])/(a[high]-a[low])*(high-low)。
时间复杂度o(logn)但对于表长较大而关键字分布比较均匀的查找表来说,效率较高。
算法思想
基于二分查找算法,将查找点的选择改进为自适应选择,可以提高查找效率。当然,差值查找也属于有序查找。
注:对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比折半查找要好的多。反之,数组中如果分布非常不均匀,那么插值查找未必是很合适的选择。注意处理当a[high]-a[low]时为0的情况。
复杂度分析
时间复杂性:如果元素均匀分布,则O(log log n)),在最坏的情况下可能需要 O(n)。
空间复杂度:O(1)。
算法实现
/**
* 非递归写法
* ************注意java实现时,要使用除法保留小数,否则每次middle都只加一*************
* @param list
* @param selectValue
* @return
*/
private static int select(List<Integer> list, int selectValue) {
if (list == null || list.isEmpty()){
return -1;
}
int start = 0;
int end = list.size() - 1;
while (end > start){
int middle = start + (int)Math.floor(division((selectValue - list.get(start)),(list.get(end) - list.get(start))) * (end - start));
if (list.get(middle) > selectValue){
end = middle - 1;
} else if ((list.get(middle) < selectValue)){
start = middle + 1;
} else {
return middle;
}
}
return -1;
}
/**
* 除法,保留两位小数
*/
private static double division(int value1,int value2) {
if (value2 == 0){
return 0;
}
BigDecimal v1 = new BigDecimal(value1);
BigDecimal v2 = new BigDecimal(value2);
return v1.divide(v2,2, RoundingMode.HALF_UP).doubleValue();
}