在java中,常用的查找有4种
线性查找、二分查找/折半查找、插值查找、斐波那契查找
package Search;
import java.util.Arrays;
//线性查找
public class SequenceSearch {
public static void main(String[] args) {
int[] arr = {
2,46,12,77,30};
System.out.println(Arrays.toString(search(arr, 30)));
}
public static int[] search(int[] arr,int value){
//逐一比对,发现相同值时返回下标
int index = 0;
int [] temp = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
if (value==arr[i]){
temp[index]=i;
index++;
}
}
return temp;
}
}
二分查找的前提:一个有序数组
思路分析
1、首先确定数组中间元素的下标
2、用要查找的值与之比较
3、根据大小选择左右递归
什么时候需要结束递归:当left>right
代码实现
package Search;
//二分查找
public class BinarySearch {
public static void main(String[] args) {
//二分查找必须是有序数组
int[] arr = {
1, 3, 5, 7, 9};
int left = 0;
int right = arr.length - 1;
System.out.println(binary(arr, left, right, 9));
}
public static int binary(int[] arr, int left, int right, int findValue) {
if (left > right) {
return -1;
}
int mid = (left + right) / 2;
if (findValue < arr[mid]) {
return binary(arr, left, mid - 1, findValue);
} else if (findValue > arr[mid]) {
return binary(arr, mid + 1, right, findValue);
} else return mid;
}
}
思考:一个有序数组中有多个相同的findValue,如何返回所有的值
代码实现
package Search;
import java.util.ArrayList;
import java.util.Arrays;
//二分查找
public class BinarySearch {
public static void main(String[] args) {
//二分查找必须是有序数组
int[] arr = {
1, 3, 5, 7, 9, 9, 9, 9};
int left = 0;
int right = arr.length - 1;
ArrayList arrayList = binary2(arr, left, right, 9);
System.out.println(arrayList);
}
public static int binary(int[] arr, int left, int right, int findValue) {
if (left > right) {
return -1;
}
int mid = (left + right) / 2;
if (findValue < arr[mid]) {
return binary(arr, left, mid - 1, findValue);
} else if (findValue > arr[mid]) {
return binary(arr, mid + 1, right, findValue);
} else return mid;
}
public static ArrayList binary2(int[] arr, int left, int right, int findValue) {
if (left > right) {
return new ArrayList<Integer>();//不能用null,否则打印的时候会报空指针异常
}
int mid = (left + right) / 2;
if (findValue < arr[mid]) {
return binary2(arr, left, mid - 1, findValue);
} else if (findValue > arr[mid]) {
return binary2(arr, mid + 1, right, findValue);
} else {
ArrayList<Integer> list = new ArrayList<>();
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 list;
}
}
}
对二分查找中的mid的值进行优化,从而更加快速的定位到想找的数
插值查找在数据量较大,且连续的情况下,比二分查找会快很多
package Search;
//插值查找
import java.util.ArrayList;
import java.util.Arrays;
public class InsertValueSearch {
public static void main(String[] args) {
int[] arr = new int[100];
for (int i = 0; i < 100; i++) {
arr[i] = i + 1;
}
// System.out.println(Arrays.toString(arr));
System.out.println(insertSearch(arr, 0, arr.length - 1, 25));
}
public static ArrayList insertSearch(int[] arr, int left, int right, int findValue) {
if (left > right || findValue < arr[left] || findValue > arr[right]) {
//多种结束条件判断提高效率
return new ArrayList<Integer>();//返回一个空数组代表未找到
}
int mid = left + (findValue - arr[left]) / (arr[right] - arr[left]) * (right - left);
if (findValue < arr[mid]) {
//左递归
return insertSearch(arr, left, mid - 1, findValue);
} else if (findValue > arr[mid]) {
//右递归
return insertSearch(arr, mid + 1, right, findValue);
} else {
int temp = mid - 1;
ArrayList<Integer> list = new ArrayList<>();
while (true) {
if (temp < 0 || arr[temp] != findValue) {
break;
}
list.add(temp);
temp -= 1;
}
list.add(mid);
while (true) {
if (temp > arr.length - 1 || arr[temp] != findValue) {
break;
}
list.add(temp);
temp += 1;
}
return list;
}
}
}