查找算法介绍

在 java 中,我们常用的查找有四种:
1) 顺序(线性)查找
2) 二分查找/折半查找
3) 插值查找
4) 斐波那契查找


一、线性(顺序)查找算法

源代码:OrderSearch.java

1、题意说明

有一个数列: {1,8,10, 89,1000,1234} ,判断数列中是否包含此名称【顺序查找】 要求: 如果找到了,就提
示找到,并给出下标值。

2、代码实现

说明:就是普通的遍历查找,找到返回下标,没有找到返回-1,之后判断即可

  1. package search;
  2. public class OrderSearch {
  3. public static void main(String[] args) {
  4. int[] arr = {1,8,10, 89,1000,1234};
  5. int search = orderSearch(arr, 134);
  6. if(search != -1) {
  7. System.out.println("找到对应下标,下标为:"+search);
  8. }else {
  9. System.out.println("没有找到对应下标");
  10. }
  11. }
  12. /**
  13. *
  14. * @Description 顺序查找
  15. * @auther changlu
  16. * @date Aug 21, 202010:16:13 AM
  17. * @param arr 数组
  18. * @param value 查找值
  19. * @return 返回下标
  20. */
  21. public static int orderSearch(int[] arr,int value) {
  22. for(int i=0;i<arr.length;i++) {
  23. if(value == arr[i]) {
  24. return i;//找到返回下标
  25. }
  26. }
  27. return -1;//没有找到
  28. }
  29. }

运行结果:
QQ截图20200821102055.jpg


二、二分查找算法

源代码(优化前+优化后):BinarySearch.java

1、二分查找算法的思路

QQ截图20200821104621.jpg

2、题意描述

请对一个有序数组进行二分查找 {1,8,10,89,1000,1234} ,输入一个数看看该数组是否存在此数,并且求出下 标,如果没有就提示”没有这个数”。

3、代码实现(递归解决,只能查找一个指定值的下标)

说明:找到值返回下标,没有找到返回-1

  1. package search;
  2. public class BinarySearch {
  3. public static void main(String[] args) {
  4. int[] arr = {1,8,10, 89,1000,1234};
  5. int binarySearch = binarySearch(arr, 0, arr.length-1, 1234);
  6. if(binarySearch != -1) {
  7. System.out.println("找到该值,下标为:"+binarySearch);
  8. }else {
  9. System.out.println("没有找到该值!");
  10. }
  11. }
  12. public static int binarySearch(int[] arr,int left,int right,int findValue) {
  13. if(left>right) {
  14. return -1;
  15. }
  16. int mid = (left+right)/2;
  17. if(findValue == arr[mid]) {
  18. return mid;
  19. }else if(findValue < arr[mid]) {
  20. return binarySearch(arr, left, mid-1, findValue);
  21. }else {
  22. return binarySearch(arr, mid+1, right, findValue);
  23. }
  24. }
  25. }

运行结果:
QQ截图20200821104824.jpg

4、代码优化(递归,能够查找多个指定值的下标)

情况说明:
对于上一个代码实现还有着缺陷的地方,只能查找最左边第一个的值,如果有连续多个相同值的话就无法找到,所以这里进行优化:
在找到第一个值的情况下,通过左右依次向前向后循环判断添加到list集合中,再进行返回。

思路分析:
QQ截图20200821111456.jpg

代码实现:
说明:可以看到在第三个else也就是访问到第一个指定值时进行前后循环判断遍历即可

  1. package search;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class BinarySearch {
  5. //能够将多个相同的值的下标存放到list集合中返回
  6. public static List<Integer> binarySearch2(int[] arr,int left,int right,int findValue) {
  7. if(left>right) {
  8. return new ArrayList<>();//如果没有找到对应值,返回空的list集合
  9. }
  10. int mid = (left+right)/2;
  11. if(findValue > arr[mid]) {
  12. return binarySearch2(arr, mid+1, right, findValue);
  13. }else if(findValue < arr[mid]) {
  14. return binarySearch2(arr, left, mid-1, findValue);
  15. }else {
  16. //创建一个list集合用来存放对应值下标
  17. List<Integer> list = new ArrayList<>();
  18. //向左进行查找
  19. int temp = mid-1;
  20. while(true) {
  21. //如果temp值小于0或不等于查找的值直接break退出
  22. if(temp<0||arr[temp] != findValue) {
  23. break;
  24. }
  25. list.add(temp--);//符合要求添加下标
  26. }
  27. list.add(mid);//添加mid之前符合的值的下标再添加mid的下标
  28. //向右进行查找
  29. temp = mid+1;
  30. while(true) {
  31. //如果temp值小于0或不等于查找的值直接break退出
  32. if(temp>=arr.length||arr[temp] != findValue) {
  33. break;
  34. }
  35. list.add(temp++);//符合要求添加下标
  36. }
  37. //返回集合
  38. return list;
  39. }
  40. }
  41. }

测试代码:

  1. package search;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class BinarySearch {
  5. public static void main(String[] args) {
  6. int[] arr = {1,8,10, 1000,1000,1000,1234};
  7. List<Integer> list = binarySearch2(arr, 0, arr.length-1, 1111);
  8. System.out.println("list中的下标为:"+list);
  9. }
  10. }

运行结果:
QQ截图20200821111731.jpg


三、插值查找算法(优化二分法)

源代码:BinarySearch.java

1、原理介绍

QQ截图20200822173955.jpg

主要核心:int mid = left+(findValue-arr[left])*(right-left)/(arr[right]-arr[left]);
**

2、 举例说明插值查找算法 1-100 的数组

QQ截图20200822174103.jpg

3、代码实现

说明:主要是对于mid查找作了优化,是根据查找值通过斜率的方式来查找,两个注意点说明。
① 对于判断left>right这里,增加两个条件必须有就是判断查找值是否越界,如果不做处理会出现越界情况
② 对于mid求值更加复杂一些,可以看上面原理介绍进行记忆

  1. //使用差值查找
  2. public static int binarySearch3(int[] arr, int left, int right, int findValue) {
  3. //在差值查找中不能设置超过指定范围的值,可能会出现越界问题
  4. if (left > right || findValue<arr[0] || findValue>arr[arr.length-1]) {//修改点1
  5. return -1;
  6. }
  7. int mid = left+(findValue-arr[left])*(right-left)/(arr[right]-arr[left]);//修改点2
  8. if (findValue == arr[mid]) {
  9. return mid;
  10. } else if (findValue < arr[mid]) {
  11. return binarySearch1(arr, left, mid - 1, findValue);
  12. } else {
  13. return binarySearch1(arr, mid + 1, right, findValue);
  14. }
  15. }

测试代码:

  1. package search;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class BinarySearch {
  5. public static void main(String[] args) {
  6. int[] arr = {1,8,10, 89,1000,1234};
  7. int binarySearch = binarySearch3(arr, 0, arr.length-1, 1);
  8. if(binarySearch != -1) {
  9. System.out.println("找到该值,下标为:"+binarySearch);
  10. }else {
  11. System.out.println("没有找到该值!");
  12. }
  13. }
  14. }

运行结果:
QQ截图20200822174439.jpg


四、斐波那契(黄金分割法)查找算法(不太明白)

1、斐波那契(黄金分割法)查找基本介绍

QQ截图20200824144152.jpg

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

QQ截图20200824144223.jpg
QQ截图20200824144304.jpgQQ截图20200824144316.jpg

3、斐波那契查找应用案例

题目说明:请对一个有序数组进行斐波那契查找 {1,8,10,89,1000,1234} ,输入一个数看看该数组是否存在此数,并且求 出下标,如果没有就提示”没有这个数”。

说明:这里包含两个方法,一个方法是获取到前20位斐波那契数,第二个方法是通过斐波那契数组来寻找黄金分割点进行值的查找。

  1. package search;
  2. import java.util.Arrays;
  3. public class FibonacciSearch {
  4. private static int maxSize = 20;
  5. //创建一个斐波那契数组
  6. public static int[] fib(){
  7. int[] f = new int[maxSize];
  8. f[0] = 1;
  9. f[1] = 1;
  10. for(int i=2;i<maxSize;i++) {
  11. f[i] = f[i-1]+f[i-2];
  12. }
  13. return f;
  14. }
  15. public static int fibSearch(int[] a, int key) {
  16. int low = 0;
  17. int high = a.length - 1;
  18. int k = 0;// 表示斐波那契分割数值的下标
  19. int mid = 0;
  20. int[] f = fib();// 获取到斐波那契数组
  21. // 获取到斐波那契
  22. while (high > f[k] - 1) {
  23. k++;
  24. }
  25. // 重新生成一个新的指定为f数组中的长度大小数组,多余的使用a数组的最后一位填充
  26. int[] temp = Arrays.copyOf(a, f[k]);
  27. // 举例:
  28. // temp={1,8,10,89,1000,1234,0,0} =>{1,8,10,89,1000,1234,1234,1234,}
  29. for (int i = high + 1; i < temp.length; i++) {
  30. temp[i] = temp[high];
  31. }
  32. while (low <= high) {
  33. System.out.println("查找");
  34. mid = low + f[k - 1] - 1;
  35. if (key < temp[mid]) {// 如果实际值再左边
  36. high = mid-1;
  37. k--;
  38. }else if(key>temp[mid]) {//这是往后面查找
  39. low = mid+1;
  40. k-=2;
  41. }else {//找到的情况
  42. //需要确定,返回的是哪个下标
  43. if(mid<=high) {
  44. return mid;
  45. }else {
  46. return high;
  47. }
  48. }
  49. }
  50. return -1;//没有找到
  51. }
  52. }



测试代码:

  1. package search;
  2. import java.util.Arrays;
  3. public class FibonacciSearch {
  4. public static void main(String[] args) {
  5. int[] arr = {1,8,10,89,1000,1234};
  6. int fibSearch = fibSearch(arr, 1234);
  7. System.out.println(fibSearch);
  8. }
  9. }

运行结果:5



整理者:长路 时间:2020/8/21-2020/8/24