插值查找算法

在均匀分布的有序数列中,会比二分查找次数少很多

思想跟二分查找一直,都是找到其中一个值,小了往左找,大了往右找

区别是:

  • 二分查找,不管查找的值是多少,每次都跟最中间的值比较
  • 插值查找也叫自适应查找,会找到比较靠近查找值的一边

代码也跟二分查找差不多,就公式不同,不过因为公式复杂了一些,需要一些判断条件来保证它的正确性

二分查找

public static int binarySearch(int[] arr,int key) {
		if(arr == null || key > arr[arr.length-1] || key < arr[0] ) {
			return -1;
		}
		int left = 0;
		int right = arr.length-1;
		int mid = (left+right)/2;
		while(left<=right) {
			if(key > arr[mid]) {
				left = mid + 1;
			}else if(key < arr[mid]) {
				right = mid - 1;
			}else {
				return mid;
			}
			mid = (left+right)/2;
		}
		return -1;
	}

插值查找

public static int interpolationSearch(int[] arr,int left,int right,int key) {
		//这个判断一方面是能把在范围外的数快速return-1,
		//另一方面是保证在范围内,也就保证了后面计算公式得到的mid值不会越界,
		//也就是保证(key-arr[left])/(arr[right]-arr[left])它的结果范围在[0,1]
		if(arr == null || key > arr[right] || key < arr[left] ) {
			return -1;
		}
		//保证arr[right]-arr[left]不为0,否则会发生算术异常
		if(arr[right] == arr[left]) {
			if(key == arr[left]) {
				return left;
			}
			return -1;
		}
		//插值公式
		int mid = left + (right-left)*(key-arr[left])/(arr[right]-arr[left]);
		if(key > arr[mid]) {
			left = mid + 1;
		}else if(key < arr[mid]) {
			right = mid - 1;
		}else {
			return mid;
		}
		if(left <= right) {
			return interpolationSearch(arr,left,right,key);
		}
		return -1;
	}

测试数组

int[] arr = new int[10000];
arr[0] = 1;
for(int i=1;i<arr.length;i++) {
    arr[i] = arr[i-1] + (int)(Math.random()*5);
}

查找次数比较

二分查找次数:9
查找结果index=18
插值查找次数:2
查找结果index=18
==============
二分查找次数:13
查找结果index=0
插值查找次数:1
查找结果index=0
==============
二分查找次数:13
查找结果index=-1
插值查找次数:3
查找结果index=-1
==============
二分查找次数:14
查找结果index=-1
插值查找次数:3
查找结果index=-1
==============
二分查找次数:14
查找结果index=37
插值查找次数:3
查找结果index=37
==============
二分查找次数:13
查找结果index=50
插值查找次数:2
查找结果index=50
==============
二分查找次数:13
查找结果index=24
插值查找次数:2
查找结果index=24
==============
二分查找次数:13
查找结果index=21
插值查找次数:2
查找结果index=21
==============
二分查找次数:13
查找结果index=9
插值查找次数:3
查找结果index=9
==============
二分查找次数:14
查找结果index=-1
插值查找次数:3
查找结果index=-1
==============

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值