前言
写个笔记记录下学习的查找算法。
查找是在大量的信息中寻找一个特定的信息元素,在某个容器中找到某数据所使用的算法,就是查找算法。
一、线性查找
给定一个查找值,在查找的容器中逐个查找给定值。
线性查找是最简单的查找算法。
代码实现:
创建一个数组{1, 9, 24, 20, 16, 14, 265}存储数据,遍历数组对比查到对应数据,拿出数据的坐标,得到数据。
package com.datastructure.search;
/**
* @author Hacah
* @date 2020/11/10 22:08
*/
public class SeqSearch {
public static void main(String[] args) {
int[] arr = {1, 9, 24, 20, 16, 14, 265};
int i = seqSearch(arr, 14);
System.out.println(i);
}
/**
* 线性查找,返回对应数据在数组中的下标
* @param arr 查找数组
* @param seaInt 要查找的数据
* @return
*/
public static int seqSearch(int[] arr,int seaInt) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == seaInt) {
return i;
}
}
return -1;
}
}
二、二分查找
二分查找使用分治思想,它是一种高效的查找方法。充分利用了元素间的次序关系。
实现思想
1.数组必须有序,把数组的数据按中间数分两段,判断小于、大于、等于,如果等于就找到了。2.如果查找数大于中间数就向中间数的右边找,小于就向中间数的左边找。3.重复步骤,直到找到数据。
查找算法在很多场景下运用广泛,若是对比线性查找二分查找是一个减少时间消耗,提高效率的好算法。
注:折半查找的前提条件是需要有序表顺序存储,对于静态查找表,一次排序后不再变化,折半查找能得到不错的效率。但对于需要频繁执行插入或删除操作的数据集来说,维护有序的排序会带来不小的工作量,那就不建议使用。——《大话数据结构》
图解实现
假设要找16,定义两个变量left,right存储一段数组的左边和右边下标
通过 (left + right) / 2得到中值midIndex。
比较midIndex与我们要找的16,由于13小于16所以向左边寻找,就如下图。
得到 (left + right) / 2中值midIndex是4,所以如下图。
比较midIndex与查找的数据,两个数相等,返回数据16的下标4,完成查询。
代码实现
创建数组{11, 45, 5, 5, 945, 248, 52, 93, 945},实现二分查找算法找到945的位置。
package com.datastructure.search;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @author Hacah
* @date 2020/11/12 22:57
*/
public class BinarySearch {
public static void main(String[] args) {
int[] arr = {11, 45, 5, 5, 945, 248, 52, 93, 945};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
// int a = binarySearch(0, arr.length - 1, arr, 52);
// System.out.println(a);
ArrayList arrayList = binarySearchs(0, arr.length - 1, arr, 945);
System.out.println(arrayList);
}
/**
* 二分查找法
*
* @param left 左指针
* @param right 右指针
* @param arr 数组
* @param value 查找的值
*/
public static int binarySearch(int left, int right, int[] arr, int value) {
int midIndex = (left + right) / 2;
int midValue = arr[midIndex];
if (left <= right) {
if (value < midValue) {
return binarySearch(left, midIndex - 1, arr, value);
} else if (value > midValue) {
return binarySearch(midIndex + 1, right, arr, value);
} else if (value == midValue) {
return midIndex;
}
}
return -1;
}
/**
* 查询多个结果
* @param left
* @param right
* @param arr
* @param value
* @return
*/
public static ArrayList binarySearchs(int left, int right, int[] arr, int value) {
int midIndex = (left + right) / 2;
int midValue = arr[midIndex];
if (left <= right) {
if (value < midValue) {
return binarySearchs(left, midIndex - 1, arr, value);
} else if (value > midValue) {
return binarySearchs(midIndex + 1, right, arr, value);
} else if (value == midValue) {
ArrayList list = new ArrayList<>();
list.add(midIndex);
// midValue的左边
int temp = midIndex - 1;
while (temp >= 0 && value == arr[temp]) {
list.add(temp);
temp--;
}
// midValue的右边
int tempR = midIndex + 1;
while (tempR <= right && value == arr[tempR]) {
list.add(tempR);
tempR++;
}
return list;
}
}
return null;
}
}
适用场景
•二分查找元素较多的数列•二分查找前提必须数列有序,无序需要排序,确认是否代价符合实际。