查找算法介绍
在 java 中,我们常用的查找有四种:
1) 顺序(线性)查找
2) 二分查找/折半查找
3) 插值查找
4) 斐波那契查找
1、线性查找算法
有一个数列: {1,8, 10, 89, 1000, 1234} ,判断数列中是否包含此名称【顺序查找】 要求: 如果找到了,就提 示找到,并给出下标值
/*** 这里我们实现的线性查找是找到一个满足条件的值,就返回*/
public static int seqSearch(int[] arr, int value) {
// 线性查找是逐一比对,发现有相同值,就返回下标
for (int i = 0; i < arr.length; i++) {
if(arr[i] == value) {
return i; }
}
return -1;
}
2、二分查找:
private static void lookUp() {
// 二分查找
int arr[] = { 1, 8, 10, 89,1000,1000, 1234 };
int num = BinarySearch(arr, 1000);
System.out.println(num);
}
/**
* 二分查找
* @param arr
* @param value
* @return
*/
private static int BinarySearch(int[] arr, int value) {
// 最小索引
int min = 0;
// 最大索引
int max = arr.length - 1;
// 中间值
int middle = (max + min) / 2;
while (min <= max){
if(value > arr[middle]) {
min = middle + 1;
}else if(value < arr[middle]) {
max = middle - 1;
}else if(arr[middle] == value) {
// 如果数组中有多个相同的数据,怎么都找到
moreNum(arr, value, middle);
return middle;
}
middle = (min + max) / 2;
}
return - 1;
}
/**
* 多个数据
*/
private static void moreNum(int[] arr, int value, int middle) {
/**
* * 思路分析
* // * 1. 在找到 mid 索引值,不要马上返回
* // * 2. 向 mid 索引值的左边扫描,将所有满足 value = 1000, 的元素的下标,加入到集合 ArrayList
* // * 3. 向 mid 索引值的右边扫描,将所有满足value = 1000, 的元素的下标,加入到集合 ArrayList
* // * 4. 将 Arraylist 返回
*/
// 如果数组中有多个相同的数据,怎么都找到
ArrayList list = new ArrayList();
list.add(middle);
// 向左查找
int cur = middle - 1;
while (true){
// 下标要大于0, 因为二分查找都是有序的,如果相邻的这个不是要找的值,直接break 跳出
if(cur < 0 || arr[cur] != value ) {
break;
}
list.add(cur);
// 左移
cur -=1;
}
// 向右边查找
cur = middle + 1;
while (true){
if(cur > arr.length - 1 || arr[cur] != value) {
break;
}
list.add(middle);
middle += 1;
}
for(int i = 0; i < list.size(); i++) {
//打印结果:
// 一共有2 :5
// 一共有2 :4
System.out.println("一共有" + list.size() + " :"+ list.get(i));
}
}
3、插值查找
1)插值查找原理介绍
插值查找算法类似于二分查找,不同的是插值查找每次从自适应 mid 处开始查找。
2)将折半查找中的求 mid 索引的公式 , low 表示左边索引 left, high 表示右边索引 right. key 就是前面我们讲的 findVal
3) int mid = low + (high - low) * (key - arr[low]) / (arr[high] - arr[low]) ;/插值索引/
对应前面的代码公式:
int mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left])
4)举例说明插值查找算法 1-100 的数组
代码实现
private static void lookUp() {
// 插值查找
int arr[] = { 1, 8, 10, 89,1000,1000, 1234};
int findVal = 1234;
int postion = insertSearch(arr, findVal);
System.out.println(postion);
}
// arr 有序的数组
private static int insertSearch(int[] arr, int findVal) {
int left = arr[0];
int right = arr.length - 1;
// 坐标下标不能超过右边下标, 查找的值必须是 大于等于 最小值 兵器小于等于最大只
while (left <= right && findVal >= arr[left] && findVal <= arr[right]){
// 自适应mid
int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);
int midVal = arr[mid];
if(findVal > midVal) {
left = mid + 1;
}else if(findVal < midVal) {
right = mid - 1;
}else {
return mid;
}
}
return -1;
}