二分查找(递归和非递归),插值查找数据

有三种常用的方法找到需要找到值的下标—顺序查找,二分查找,插值查找
顺序查找:很明显,就是从开始到后面开始遍历,找到就退出,并返回下标。
没找到就返回-1.
下面是代码:

public static int seqSearch(int[] arr,int value) {
		for (int i = 0; i < arr.length; i++) {
			if(arr[i]==value) {
				return i+1;
			}
		}
		return -1;
	}

二分查找:有个缺点,就是必须要先得到排好序的数列。下面步骤是由小到大排序的,要是从大到小就处理相反即可。
步骤:先找到中间下标mid,每次用mid对应的数值跟要查找的值比较,如果等于就直接返回对应下标,如果小于查找值就向左边处理,大于就向右边处理。

代码如下:递归方法。

	public static int binarySearch(int[] arr,int left,int right,int findValue) {
		if(left>right) {
			return -1;
		}
		
		int mid=(left+right)/2;
		int midVal=arr[mid];
		if(findValue>midVal) {
			return binarySearch(arr, mid+1, right, findValue);
		}else if(findValue<midVal){
			return binarySearch(arr, left, mid-1, findValue);
		}else {
			return mid;
		}
	}
	

非递归方法:与递归的区别就是用while循环,直到找到return。

	public static int binarySearch(int[] arr,int left,int right,int findValue) {
		if(left>right) {
			return -1;
		}
		int mid = (left+right)/2;
		while(left <= right){
			if(arr[mid] = findValue){
				return mid-1;
			}
			if(arr[mid] > findValue){
				right = mid - 1;
			}
			if(arr[mid] < findValue){
				left = mid +1;
			}
		}
	}

但是有可能这个有序数列中不止这一个数据和查找的数据相同,哪就是在处理等于情况下再做处理。(查找多个相同的,将下标放在一个List里面了。)

代码如下:

public static ArrayList<Integer> binarySearch(int[] arr,int left,int right,int findValue) {
		if(left>right) {
			return new ArrayList<Integer>();
		}
		
		int mid=(left+right)/2;
		int midVal=arr[mid];
		if(findValue>midVal) {
			return binarySearch(arr, mid+1, right, findValue);
		}else if(findValue<midVal){
			return binarySearch(arr, left, mid-1, findValue);
		}else {		//值和查找的相同。
			List<Integer> list=new ArrayList<Integer>();
			int temp=mid-1;
			//处理左边的
			while(true) {
				//在这个数组左边范围内
				if(temp<0||arr[temp]!=findValue) {
					break;
				}
				//找到放入。
				list.add(temp);
				temp-=1;
			}
			//处理中间的
			list.add(mid);
			//处理右边的。
			temp=mid+1;
			while(true) {
				//在这个数组右边范围内
				if(temp>arr.length-1||arr[temp]!=findValue) {
					break;
				}
				//找到放入。
				list.add(temp);
				temp+=1;
			}
			return (ArrayList<Integer>) list;
		}
	}

插值查找:如果要查找这个顺序的数列的最左边或最右边,哪还要查找log2(n)次,比较麻烦,所以要使用插值查找。
插值查找根二分查找也差不多,只不过那个找中间mid的公式不同,如下:
mid=left+(right-left)*(findValue-arr[left]/(arr[right]-arr[left]));

代码如下:

public static int insertValueSearch(int[] arr,int left,int right,int findValue) {
		if(left>right|| findValue<arr[0]|| findValue>arr[arr.length-1]) {
			return -1;
		}
		int mid=left+(right-left)*(findValue-arr[left]/(arr[right]-arr[left]));
		int midVal=arr[mid];
		if(findValue>midVal) {
			return insertValueSearch(arr, mid+1, right, findValue);
		}else if(findValue<midVal){
			return insertValueSearch(arr, left, mid-1, findValue);
		}else {
			return mid;
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值