二分查找
二分查找,顧名思義就是折半查找。前提是數組必須是有序的。每次將查找的數和數組的中間值進行比較,如果要查找的數比中間值小就左遞歸繼續查找,如果要查找的數比中間值大,就右遞歸繼續查找,如果要查找的數存在,最終就是反覆遞歸後的中間值。
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;
}
}
}
如有錯誤,還望指出,我將及時改正。