目录
线性查找法
可以是有序的,也可以是无序的。
public class SeqSearch {
public static void main(String[] args) {
int[] arr = new int[]{1, 9, 11, -1, 34, 89};
int res = seqSearch(arr, 34);
}
public static int seqSearch(int[] arr, int n) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == n) {
return i;
}
}
return -1;
}
}
二分查找法
也叫折半查找,数组必须有序。
public class BinarySearch {
public static void main(String[] args) {
int[] arr = new int[]{2, 2, 4, 4, 5};
// int res = binarySearch(arr, 6);
List list = binarySearchPlus(arr, 6);
}
public static int binarySearch(int[] arr, int n) {
int l = 0;
int r = arr.length - 1;
while (l <= r) {
int m = (l + r) / 2;
if (n < arr[m]) {
r = m - 1;
} else if (n > arr[m]) {
l = m + 1;
} else if (n == arr[m]) {
return m;
} else {
return -1;
}
}
return -1;
}
public static ArrayList binarySearchPlus(int[] arr, int n) {
int l = 0;
int r = arr.length - 1;
while (l <= r) {
int m = (l + r) / 2;
if (n < arr[m]) {
r = m - 1;
} else if (n > arr[m]) {
l = m + 1;
} else if (n == arr[m]) {
ArrayList<Integer> list = new ArrayList<>();
list.add(m);
for (int i = m - 1; i >= 0 && n == arr[i]; i++) {
list.add(i);
}
for (int i = m + 1; i < arr.length && n == arr[i]; i++) {
list.add(i);
}
Collections.sort(list);
return list;
} else {
return null;
}
}
return null;
}
}
在不使用递归的方式下进行二分查找
// 非递归实现的二分查找
public static int binarySearch(int[] arr, int target) {
if (arr.length == 0 || target < arr[0] || target > arr[arr.length - 1]) {
return -1;
}
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (target == arr[mid]) {
return mid;
} else if (target < arr[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return -1;
}
插值查找法
二分查找:
插值查找:
适用于数据连续的数组,通过黄金分割点的算法。
public class InsertSearch {
public static void main(String[] args) {
int[] arr = new int[100];
for (int i = 0; i < arr.length; i++) {
arr[i] = i + 1;
}
int res = insertSearch(arr, 50);
}
public static int insertSearch(int[] arr, int key) { // 也要求数组有序
int high = arr.length - 1;
int low = 0;
while (low <= high) {
int mid = low + (high - low) * (key - arr[low]) / (arr[high] - arr[low]);
if (mid < 0) { // 左越界
if (key < arr[0]) {
return -1;
}
mid = 0;
}
if (mid > arr.length - 1) { // 右越界
if (key > arr[arr.length - 1]) {
return -1;
}
mid = arr.length - 1;
}
if (key > arr[mid]) {
low = mid + 1;
} else if (key < arr[mid]) {
high = mid - 1;
} else if (key == arr[mid]) {
return mid;
} else {
return -1;
}
}
return -1;
}
}
斐波那契查找法
也叫黄金分割点查找法,也适用于连续的数组。
public class FibonacciSearch {
public static int maxSize = 20;
public static void main(String[] args) {
int[] arr = new int[]{1, 8, 10, 89, 1000, 1024};
int res = fibSearch(arr, 1025);
}
// 获得一个斐波那契数列
public static int[] fib() {
int[] f = new int[maxSize];
f[0] = f[1] = 1;
for (int i = 2; i < maxSize; i++) {
f[i] = f[i - 1] + f[i - 2];
}
return f;
}
public static int fibSearch(int[] arr, int key) {
int low = 0;
int high = arr.length - 1;
int k = 0;
int mid;
int[] f = fib();
// 获得新数组的大小,新数组的大小大于等于旧数组,并且符合斐波那契数列
while (f[k] - 1 < high) { // 斐波那契数列 大于等于 最大下标
k++;
} // 把原数组扩容成斐波那契大小的数组,然后再找黄金分割点
int[] temp = Arrays.copyOf(arr, f[k]); // new一个f[k]这么大的数组,并把arr拷贝进去
for (int i = high + 1; i < temp.length; i++) {
temp[i] = arr[high];
}
while (low <= high) {
mid = low + f[k - 1] - 1; // 获得黄金分割点
if (key < temp[mid]) {
high = mid - 1;
k--;
} else if (key > temp[mid]) {
low = mid + 1;
/**
* 全部元素=前面元素+后面元素
* f[k]=f[k-1]+f[k-2]
*/
k -= 2;
} else {
if (mid <= high) {
return mid;
} else {
return high;
}
}
}
return -1;
}
}