JAVA代码实现二分查找和插值查找

二分查找

二分查找,顾名思义就是折半查找。前提是数组必须是有序的。每次将查找的数和数组的中间值进行比较,如果要查找的数比中间值小就左递归继续查找,如果要查找的数比中间值大,就右递归继续查找,如果要查找的数存在,最终就是反复递归后的中间值。

package com.search.BinarySerach;

import java.util.ArrayList;
import java.util.List;

public class BinarySearchDemo2 {

	public static void main(String[] args) {
		int[] arr = { 1, 3, 5, 7, 7, 7, 7, 9, 11, 13, 15 };
		List<Integer> binarySearch = binarySearch(arr, 0, arr.length - 1, 7);
		System.out.println("7的下标为:" + binarySearch.toString());

	}

	/**
	 * 二分查找
	 * 
	 * @param arr     原数组
	 * @param left    每次查找的左边
	 * @param right   每次查找的右边
	 * @param findVal 要查找的值
	 * @return
	 */
	public static List<Integer> binarySearch(int[] arr, int left, int right, int findVal) {
		if (left > right) {
			return new ArrayList<Integer>();
		}
		// 1.先得到中间值和下标
		int mid = (left + right) / 2;
		int midVal = arr[mid];
		// 2.中间值和要查找的值进行比较
		if (midVal > findVal) {// 如果中间值大于要查找的值,那就向左递归查找
			return binarySearch(arr, left, mid - 1, findVal);
		} else if (midVal < findVal) {// 如果中间值小于要查找的值,那就向右递归查找
			return binarySearch(arr, mid + 1, right, findVal);
		} else {// 当中间值等于查找的值时,说明找到了
				// 可能要查找的值有多个,定义一个集合存放要查找的值的所有下标
			List<Integer> list = new ArrayList<Integer>();
			// 先向左扫描
			int temp = mid - 1;
			while (temp >= 0 && arr[temp] == midVal) {
				list.add(temp);
				temp--;
			}
			// 左边扫描完毕后,将中间值的下标存放到集合中
			list.add(mid);
			// 再向右扫描
			temp = mid + 1;
			while (temp <= arr.length - 1 && arr[temp] == midVal) {
				list.add(temp);
				temp++;
			}
			return list;
		}

	}

}

插值查找

插值查找类似于二分查找,就是将查找方式换了。二分查找是mid=(left+right)/2这种折半的方式,而插值查找是根据要查找的数定义自适应的划分线:mid = left + (left + right) * (findVal - arr[left]) / (arr[right] - arr[left])。其他步骤和二分查找一样。
注意:
1.对于数据量较大,数字分布比较均匀的查找表来说,插值查找速度较快;
2.关键字分布不均匀的情况下,该方法不一定比折半查找要好。

package com.search.insertSearch;

import java.util.ArrayList;
import java.util.List;

public class InsertSearchDemo2 {

	public static void main(String[] args) {
		int[] arr = { 1, 3, 5, 7, 7, 7, 7, 9, 11, 13, 15 };
		List<Integer> binarySearch = insertSearch(arr, 0, arr.length - 1, 7);
		System.out.println("7的下标为:" + binarySearch.toString());

	}

	public static List<Integer> insertSearch(int[] arr, int left, int right, int findVal) {
		if (left > right) {
			return new ArrayList<Integer>();
		}
		// 先得到划分线的值和下标
		int mid = left + (left + right) * (findVal - arr[left]) / (arr[right] - arr[left]);
		int midVal = arr[mid];
		// 比较划分线处的值和要查找的值
		if (findVal < midVal) {
			return insertSearch(arr, left, mid - 1, findVal);
		} else if (findVal > midVal) {
			return insertSearch(arr, mid + 1, right, findVal);
		} else {
			List<Integer> list = new ArrayList<Integer>();
			// 先向左扫描
			int temp = mid - 1;
			while (temp >= 0 && arr[temp] == midVal) {
				list.add(temp);
				temp--;
			}
			// 将划分线的值放进去
			list.add(mid);
			// 再向右扫描
			temp = mid + 1;
			while (temp <= arr.length - 1 && arr[temp] == midVal) {
				list.add(temp);
				temp++;
			}
			return list;
		}
	}

}

如有错误,还望指出,我将及时改正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章