基本查找( 顺序查找 )
举个例子 基本查找( 顺序查找 )
从零开始以此往后查找,查找到就返回当前索引,并结束查找
public static void main(String[] args) {
// 定义这个数组
int[] arr = {131,127,147,81,103,23,7,79,81};
// 查找81
int number = 81;
// 调用函数 进行查找 arr 是数组 number 要查找的数字
ArrayList<Integer> list = BaseSearch(arr, number);
// 打印这个集合。因为查找到的数组不只是一个,,集合里存放查找元素所在的索引
System.out.println(list);
}
private static ArrayList<Integer> BaseSearch(int[] arr, int number) {
ArrayList<Integer> list = new ArrayList<>();
// 循环遍历
for (int i = 0; i < arr.length; i++) {
// 如果数值与要查找的number 数值一样就把所在的索引加入到集合
if(arr[i] == number){
list.add(i);
}
}
// 返回集合
return list;
}
二分查找
前提条件:数组中的数据必须是有序的
核心逻辑:每次排掉数组一半的范围
min 和 max 表示当前查找的范围
mid 表示 当前元素的索引
如果 mid索引的元素 大于查找的元素 缩小范围,max = mid - 1
如果 mid索引的元素 小于查找的元素 缩小范围,mix = mid + 1
举个例子(二分查找)
public static void main(String[] args) {
// 定义这个数组
int[] a = {10,22,38,46,59,62,75,83,91,100};
// 查找91
int num = BaseSearch(a, 91);
//打印查找到的索引
System.out.println(num);
}
private static int BaseSearch(int[] arr, int number) {
// 定义开始 和 结束标签 的变量
int max = arr.length - 1;
int min = 0;
while (true){
// 这个已经放到循环里面,每次都要重新给mid 定位置 mid 就等于 当前范围的中间范围
int mid = (max + min) / 2;// 中间值
// 表示查询不到了
if(min > max){
return -1;
}
// 如果 mid索引的元素 大于查找的元素 缩小范围,max = mid - 1
if(arr[mid] > number){
max = mid - 1;
// 如果 mid索引的元素 小于查找的元素 缩小范围,mix = mid + 1
}else if(arr[mid] < number){
min = mid + 1;
// 就找到了
}else if(arr[mid] == number){
return mid; // 结束循环
}
}
}
改进:我想让mid 尽量偏向可能的值
public static void main(String[] args) {
// 定义这个数组
int[] a = {10, 22, 38, 46, 59, 62, 75, 83, 91, 100};
// 查找91
int num = BaseSearch(a, 91);
//打印查找到的索引
System.out.println(num);
}
private static int BaseSearch(int[] arr, int number) {
// 定义开始 和 结束标签 的变量
int max = arr.length - 1;
int min = 0;
while (true) {
// 改进
//查找数值-数组中最小的数值
//数组中最大数-数组中最小数
double may_value = (double) (number - arr[min]) / (arr[max] - arr[min]);
// 最小索引 - may_value * (最大索引-最小索引)
int mid = (int) (min + may_value * (max - min));
// 这个已经放到循环里面,每次都要重新给mid 定位置 mid 就等于 当前范围的中间范围
// int mid = (max + min) / 2; 中间值
// 表示查询不到了
if (min > max) {
return -1;
}
// 如果 mid索引的元素 大于查找的元素 缩小范围,max = mid - 1
if (arr[mid] > number) {
max = mid - 1;
// 如果 mid索引的元素 小于查找的元素 缩小范围,mix = mid + 1
} else if (arr[mid] < number) {
min = mid + 1;
// 就找到了
} else if (arr[mid] == number) {
return mid; // 结束循环
}
}
}
分块查找
条件:
分块的个数 = 数组的长度开根号
块内无序,块间有序,第一块的最大值一定是比第二个块的最小值要小
举个例子(分块查找)
public class block {
public static void main(String[] args) {
// 创建数组
int[] arr = {16,5,9,12,21,18,
32,23,37,26,45,34,
50,48,61,52,73,66
};
// 创建对象
Pin p1 = new Pin(21,0,6);
Pin p2 = new Pin(45,7, 12);
Pin p3 = new Pin(73,13,18);
// 把对象封装成数组
Pin[] box = {p1,p2,p3};
// 我们查找91
// 调用函数
int index = indexOf(box,arr,45);
System.out.println(index);
}
private static int indexOf(Pin[] box, int[] arr, int number) {
// 获得块索引
int index = findIndex(box, number);
// 检查是不是 -1
if(index < 0){
return -1;
}
// 因为已经获得准确位置勒,所以只需要遍历这个范围就可以勒
for (int i = box[index].getStartIndex(); i < box[index].getEndIndex(); i++) {
if(arr[i] == number){
return i;
}
}
return -1;
}
// 这个方法用来确定数值在那一块中
private static int findIndex(Pin[] box, int number) {
// 基本查找
// 遍历这个对象
for (int i = 0; i < box.length; i++) {
// 查看块的最大值是不是大于等于这个数字
if(box[i].getMax() >= number){
// 返回当前索引
return i;
}
}
return -1;
}
}
// 定义 类
class Pin{
private int max; // 最大值
private int startIndex; // 开始索引和结束索引
private int endIndex;
public Pin() {
}
public Pin(int max, int startIndex, int endIndex) {
this.max = max;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
public int getMax() {
return max;
}
public void setMax(int max) {
this.max = max;
}
public int getStartIndex() {
return startIndex;
}
public void setStartIndex(int startIndex) {
this.startIndex = startIndex;
}
public int getEndIndex() {
return endIndex;
}
public void setEndIndex(int endIndex) {
this.endIndex = endIndex;
}
}