查找算法介绍
在 java 中,我们常用的查找有四种:
1) 顺序(线性)查找
2) 二分查找/折半查找
3) 插值查找
4) 斐波那契查找
一、线性(顺序)查找算法
源代码:OrderSearch.java
1、题意说明
有一个数列: {1,8,10, 89,1000,1234} ,判断数列中是否包含此名称【顺序查找】 要求: 如果找到了,就提
示找到,并给出下标值。
2、代码实现
说明:就是普通的遍历查找,找到返回下标,没有找到返回-1,之后判断即可
package search;public class OrderSearch {public static void main(String[] args) {int[] arr = {1,8,10, 89,1000,1234};int search = orderSearch(arr, 134);if(search != -1) {System.out.println("找到对应下标,下标为:"+search);}else {System.out.println("没有找到对应下标");}}/**** @Description 顺序查找* @auther changlu* @date Aug 21, 202010:16:13 AM* @param arr 数组* @param value 查找值* @return 返回下标*/public static int orderSearch(int[] arr,int value) {for(int i=0;i<arr.length;i++) {if(value == arr[i]) {return i;//找到返回下标}}return -1;//没有找到}}
运行结果:
二、二分查找算法
源代码(优化前+优化后):BinarySearch.java
1、二分查找算法的思路

2、题意描述
请对一个有序数组进行二分查找 {1,8,10,89,1000,1234} ,输入一个数看看该数组是否存在此数,并且求出下 标,如果没有就提示”没有这个数”。
3、代码实现(递归解决,只能查找一个指定值的下标)
说明:找到值返回下标,没有找到返回-1
package search;public class BinarySearch {public static void main(String[] args) {int[] arr = {1,8,10, 89,1000,1234};int binarySearch = binarySearch(arr, 0, arr.length-1, 1234);if(binarySearch != -1) {System.out.println("找到该值,下标为:"+binarySearch);}else {System.out.println("没有找到该值!");}}public static int binarySearch(int[] arr,int left,int right,int findValue) {if(left>right) {return -1;}int mid = (left+right)/2;if(findValue == arr[mid]) {return mid;}else if(findValue < arr[mid]) {return binarySearch(arr, left, mid-1, findValue);}else {return binarySearch(arr, mid+1, right, findValue);}}}
运行结果:
4、代码优化(递归,能够查找多个指定值的下标)
情况说明:
对于上一个代码实现还有着缺陷的地方,只能查找最左边第一个的值,如果有连续多个相同值的话就无法找到,所以这里进行优化:
在找到第一个值的情况下,通过左右依次向前向后循环判断添加到list集合中,再进行返回。
思路分析:
代码实现:
说明:可以看到在第三个else也就是访问到第一个指定值时进行前后循环判断遍历即可
package search;import java.util.ArrayList;import java.util.List;public class BinarySearch {//能够将多个相同的值的下标存放到list集合中返回public static List<Integer> binarySearch2(int[] arr,int left,int right,int findValue) {if(left>right) {return new ArrayList<>();//如果没有找到对应值,返回空的list集合}int mid = (left+right)/2;if(findValue > arr[mid]) {return binarySearch2(arr, mid+1, right, findValue);}else if(findValue < arr[mid]) {return binarySearch2(arr, left, mid-1, findValue);}else {//创建一个list集合用来存放对应值下标List<Integer> list = new ArrayList<>();//向左进行查找int temp = mid-1;while(true) {//如果temp值小于0或不等于查找的值直接break退出if(temp<0||arr[temp] != findValue) {break;}list.add(temp--);//符合要求添加下标}list.add(mid);//添加mid之前符合的值的下标再添加mid的下标//向右进行查找temp = mid+1;while(true) {//如果temp值小于0或不等于查找的值直接break退出if(temp>=arr.length||arr[temp] != findValue) {break;}list.add(temp++);//符合要求添加下标}//返回集合return list;}}}
测试代码:
package search;import java.util.ArrayList;import java.util.List;public class BinarySearch {public static void main(String[] args) {int[] arr = {1,8,10, 1000,1000,1000,1234};List<Integer> list = binarySearch2(arr, 0, arr.length-1, 1111);System.out.println("list中的下标为:"+list);}}
运行结果:
三、插值查找算法(优化二分法)
1、原理介绍

主要核心:int mid = left+(findValue-arr[left])*(right-left)/(arr[right]-arr[left]);
**
2、 举例说明插值查找算法 1-100 的数组

3、代码实现
说明:主要是对于mid查找作了优化,是根据查找值通过斜率的方式来查找,两个注意点说明。
① 对于判断left>right这里,增加两个条件必须有就是判断查找值是否越界,如果不做处理会出现越界情况
② 对于mid求值更加复杂一些,可以看上面原理介绍进行记忆
//使用差值查找public static int binarySearch3(int[] arr, int left, int right, int findValue) {//在差值查找中不能设置超过指定范围的值,可能会出现越界问题if (left > right || findValue<arr[0] || findValue>arr[arr.length-1]) {//修改点1return -1;}int mid = left+(findValue-arr[left])*(right-left)/(arr[right]-arr[left]);//修改点2if (findValue == arr[mid]) {return mid;} else if (findValue < arr[mid]) {return binarySearch1(arr, left, mid - 1, findValue);} else {return binarySearch1(arr, mid + 1, right, findValue);}}
测试代码:
package search;import java.util.ArrayList;import java.util.List;public class BinarySearch {public static void main(String[] args) {int[] arr = {1,8,10, 89,1000,1234};int binarySearch = binarySearch3(arr, 0, arr.length-1, 1);if(binarySearch != -1) {System.out.println("找到该值,下标为:"+binarySearch);}else {System.out.println("没有找到该值!");}}}
运行结果:
四、斐波那契(黄金分割法)查找算法(不太明白)
1、斐波那契(黄金分割法)查找基本介绍

2、斐波那契(黄金分割法)原理



3、斐波那契查找应用案例
题目说明:请对一个有序数组进行斐波那契查找 {1,8,10,89,1000,1234} ,输入一个数看看该数组是否存在此数,并且求 出下标,如果没有就提示”没有这个数”。
说明:这里包含两个方法,一个方法是获取到前20位斐波那契数,第二个方法是通过斐波那契数组来寻找黄金分割点进行值的查找。
package search;import java.util.Arrays;public class FibonacciSearch {private static int maxSize = 20;//创建一个斐波那契数组public static int[] fib(){int[] f = new int[maxSize];f[0] = 1;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[] a, int key) {int low = 0;int high = a.length - 1;int k = 0;// 表示斐波那契分割数值的下标int mid = 0;int[] f = fib();// 获取到斐波那契数组// 获取到斐波那契while (high > f[k] - 1) {k++;}// 重新生成一个新的指定为f数组中的长度大小数组,多余的使用a数组的最后一位填充int[] temp = Arrays.copyOf(a, f[k]);// 举例:// temp={1,8,10,89,1000,1234,0,0} =>{1,8,10,89,1000,1234,1234,1234,}for (int i = high + 1; i < temp.length; i++) {temp[i] = temp[high];}while (low <= high) {System.out.println("查找");mid = low + f[k - 1] - 1;if (key < temp[mid]) {// 如果实际值再左边high = mid-1;k--;}else if(key>temp[mid]) {//这是往后面查找low = mid+1;k-=2;}else {//找到的情况//需要确定,返回的是哪个下标if(mid<=high) {return mid;}else {return high;}}}return -1;//没有找到}}
测试代码:
package search;import java.util.Arrays;public class FibonacciSearch {public static void main(String[] args) {int[] arr = {1,8,10,89,1000,1234};int fibSearch = fibSearch(arr, 1234);System.out.println(fibSearch);}}
运行结果:5
整理者:长路 时间:2020/8/21-2020/8/24
