当前位置:   article > 正文

详解:二分查找算法【Java实现】(递归&&非递归)_二分查找递归实现和非递归实现java

二分查找递归实现和非递归实现java

目录

一、基本概念

二、二分查找算法的图解思路分析【递归法】:

代码实现:

二分查找优化:实现返回数组里多个相同的数的所有索引

三、二分查找算法的图解思路分析【非递归法】:


一、基本概念

二分查找法(Binary Search)算法,也叫折半查找算法。二分查找针对的是一个有序的数据集合,查找思想有点类似于分治思想。每次都通过跟区间的中间元素对比,将带查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为0。

二、二分查找算法的图解思路分析【递归法】:

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

定义变量

        mid:要进行二分查找的数组的中间下标;

        left:要进行二分查找的数组的最左边的下标

        right:要进行二分查找的数组的最右边的下标

        findVal:我们要进行二分查找的数字

1,首先确定该数组的中间的下标mid= (left+right)/2

2,然后让需要查找的数findVal和arr[mid]比较:

        2.1 findVal>arr[mid],说明要查找的数在mid的右边,因此需要递归的向右查找

        2.2 findVal <arr[mid],说明你要查找的数在mid的左边,因此需要递归的向左查找。

        2.3 findval==arr[mid]说明找到,就返回 。

3,结束递归的条件:
        1)找到就结束递归。
        2)递归完整个数组,仍然没有找到findval,就需要结束递归。

        3)当left> right就需要退出递归。

4,弊端:

        当一个有序数组中,有多个相同的数值时,只会返回一个值的位置的索引。

代码实现:

  1. //注意二分查找的前提是:该数组是有序的
  2. public class BinarySearch {//二分查找
  3. public static void main(String[] args) {
  4. //测试二分查找:
  5. int[] arr = {18108910001234};
  6. int val = binarySearch2(arr, 0, arr.length - 1, 36);
  7. System.out.println(val);
  8. }
  9. /*二分查找【不能查找重复的值的索引,相同的值只会返回一个值的索引】
  10. arr 数组
  11. left 数组最左边的索引
  12. right 数组最右边的索引
  13. findVal 要查找的值
  14. 如果找到就返回下标,如果没有找到就返回-1
  15. * */
  16. public static int binarySearch(int[] arr, int left, int right, int findVal) {
  17. // findVal < arr[0] || findVal > arr[arr.length - 1]说明要查找的findVal值再数组中不存在
  18. //当left>right时说明,已经递归了整个数组,但是没有findVal值
  19. if (left > right || findVal < arr[0] || findVal > arr[arr.length - 1]) {//当满足其中任意一个条件时,就要退出递归。
  20. return -1;
  21. }
  22. int mid = (left + right) / 2;//mid表示数组中间的下标
  23. int midVal = arr[mid];//midVal表示数组中间的值
  24. if (findVal > midVal) {
  25. //向右递归
  26. return binarySearch(arr, mid + 1, right, findVal);
  27. } else if (findVal < midVal) {
  28. //向左递归
  29. return binarySearch(arr, left, mid - 1, findVal);
  30. } else {//表示:findVal==midVal找到要查找的值
  31. return mid;
  32. }
  33. }
  34. }

二分查找优化:实现返回数组里多个相同的数的所有索引

  1. //注意二分查找的前提是:该数组是有序的
  2. public class BinarySearch {//二分查找
  3. public static void main(String[] args) {
  4. //测试:当有数组里多个相同的数值时,将所有的数值都查找到返回下标索引。比如这里的1000
  5. int[] arr = {1,8, 10, 89, 1000, 1000, 1 ,34};
  6. List val = binarySearch2(arr, 0, arr.length - 1, 1000);
  7. System.out.println(val);
  8. }
  9. /*二分查找优化【查找出多个相同的的值的下标索引】
  10. arr 数组
  11. left 数组最左边的索引
  12. right 数组最右边的索引
  13. findVal 要查找的值
  14. 如果找到就返回下标,如果没有找到就返回-1
  15. * */
  16. public static ArrayList<Integer> binarySearch2(int[] arr, int left, int right, int findVal) {
  17. if (left > right || findVal < arr[0] || findVal > arr[arr.length - 1]) {
  18. return new ArrayList<Integer>();
  19. }
  20. int mid = (left + right) / 2;//mid表示数组中间的下标
  21. int midVal = arr[mid];//midVal表示数组中间的值
  22. if (findVal > midVal) {
  23. //向右递归
  24. return binarySearch2(arr, mid + 1, right, findVal);
  25. } else if (findVal < midVal) {
  26. //向左递归
  27. return binarySearch2(arr, left, mid - 1, findVal);
  28. } else {//表示:findVal==midVal【经过前面的递归,最终都会有findVal==midVal】
  29. /*
  30. * 思路分析:
  31. * 1,在找到mid索引值,不马上返回
  32. * 2,向mid索引值的左边扫描,将所有满足findVal的值的下标加入到ArrayList集合里
  33. * 3,向mid索引值的右边扫描,将所有满足findVal的值的下标加入到ArrayList集合里
  34. * 4,将ArrayList集合返回
  35. * */
  36. ArrayList<Integer> integers = new ArrayList<>();
  37. //向mid索引值的左边扫描,将所有满足findVal的值的下标加入到ArrayList集合里
  38. int temp = mid - 1;//temp表示向左扫描的索引
  39. while (true) {
  40. if (temp < 0 || arr[temp] != findVal) {//退出
  41. break;
  42. }
  43. //否则,就把temp放入集合integers中
  44. integers.add(temp);
  45. temp -= 1;
  46. }
  47. integers.add(mid);//刚好mid就是要找的findVal值
  48. //向mid索引值的右边扫描,将所有满足findVal的值的下标加入到ArrayList集合里
  49. temp = mid + 1;//temp表示向右扫描的索引
  50. while (true) {
  51. if (temp > arr.length - 1 || arr[temp] != findVal) {//退出
  52. break;
  53. }
  54. //否则,就把temp放入集合integers中
  55. integers.add(temp);
  56. temp += 1;
  57. }
  58. return integers;
  59. }
  60. }

三、二分查找算法的图解思路分析【非递归法】:

非递归法相对于递归法就要简单的多,只是while循环和if-else的嵌套使用就可以实现。

  1. public class BinaryDearchNoRecur {//二分查找的非递归实现
  2. public static void main(String[] args) {
  3. //测试
  4. int[] arr = {1, 3, 8, 10, 11, 67, 100};
  5. int index = binaryDearch(arr, 13);
  6. System.out.println("index=" + index);
  7. }
  8. /**
  9. * 二分查找的非递归实现
  10. * @param arr 待查找的数组,arr是升序排列
  11. * @param target 需要查找的数
  12. * @return 返回对应数组下标,没有返回-1
  13. */
  14. public static int binaryDearch(int[] arr, int target) {
  15. int left = 0;//left表示数组最左边的索引
  16. int right = arr.length - 1;//表示数组最右边的索引
  17. while (left <= right) {//说明可以继续查找
  18. int mid = (left + right) / 2;//mid表示数组中间的索引
  19. if (arr[mid] == target) {
  20. return mid;
  21. } else if (arr[mid] > target) {
  22. right = mid - 1;//需要向左边查找
  23. } else {
  24. left = mid + 1;//需要向右边查找
  25. }
  26. }
  27. return -1;
  28. }
  29. }

长风破浪会有时,直挂云帆济沧海!

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/896617
推荐阅读
相关标签
  

闽ICP备14008679号