简体   繁体   English

递归二分查找(整数)

[英]Recursive binary search (integer)

I've written this binary search algorithm based on recursion but I'm unable to understand the reason for the error.我已经编写了这个基于递归的二进制搜索算法,但我无法理解错误的原因。

    // Only a sorted array must be entered for binary search to work
    public int binarySearch(int searchFor, int[] inArray, int from, int to){
        if (to >= from){
            int mid = (to-from)/2 + from;
            
            if (inArray[mid] == searchFor){
                return inArray[mid];
            } else if (inArray[mid] < searchFor){
                binarySearch(searchFor, inArray, ++mid, to);
            } else if (inArray[mid] > searchFor){
                binarySearch(searchFor, inArray, from, ++mid);
            }
        }
        return -1;
    }

Exception in thread "main" java.lang.StackOverflowError线程“主”java.lang.StackOverflowError 中的异常

at search.binarySearch(search.java:24)
at search.binarySearch(search.java:24)
at search.binarySearch(search.java:24)
at search.binarySearch(search.java:24)

A few issues and remarks:几个问题和注意事项:

  • In the last case, the value ++mid is wrong as argument for binarySearch .在最后一种情况下,值++mid作为binarySearch的参数是错误的。 That value should be one less than mid in that case.在这种情况下,该值应该mid小一。

  • I would also vote against the use of ++mid or --mid here, as that suggests that it is important that mid changes value, which is not needed.我也会在这里投票反对使用++mid--mid ,因为这表明mid更改值很重要,这不是必需的。 You should just pass mid+1 in the first case, and mid-1 in the second.你应该在第一种情况下通过mid+1 ,在第二种情况下通过mid-1

  • binarySearch returns an int , but when your code calls it recursively it doesn't do anything with that return value. binarySearch返回一个int ,但是当您的代码递归调用它时,它不会对该返回值做任何事情。

    You should return that value.您应该返回该值。 So:所以:

     } else if (inArray[mid] < searchFor){ return binarySearch(searchFor, inArray, mid+1, to); // ^^^^^^ ^^^^^ } else if (inArray[mid] > searchFor){ return binarySearch(searchFor, inArray, from, mid-1); // ^^^^^^ ^^^^^ }
  • The expression (to-from)/2 + from is a verbose way of doing (from+to)/2 ...表达式(to-from)/2 + from(from+to)/2 ...

Apart from adding return to the recursive calls of binarySearch , there are a couple of flaws in the logic:除了在binarySearch的递归调用中添加return之外,逻辑中还有一些缺陷:

  • mid should be decremented to catch values in the left part: mid递减以捕获左侧的值:
    return binarySearch(searchFor, inArray, from, --mid);
  • there should be a check for valid mid , from , to values to fit inside the input array应该检查有效的midfromto值以适合输入数组

Thus, the method should look as:因此,该方法应如下所示:

public static int binarySearch(int searchFor, int[] inArray, int from, int to) {
        if (to >= from && from > -1 && to <= inArray.length) {
            int mid = (to-from)/2 + from;
            
            if (mid >= inArray.length) {
                return -1;
            }
            
            // System.out.printf("from=%d to=%d mid=%d val=%d%n", from, to, mid, inArray[mid]); // debug print
            if (inArray[mid] == searchFor) {
                return inArray[mid];
            } else if (inArray[mid] < searchFor){
                return binarySearch(searchFor, inArray, ++mid, to);
            } else {
                return binarySearch(searchFor, inArray, from, --mid);
            }
        }
        return -1;
    }
}

Tests:测试:

public static int binarySearch(int searchFor, int... inArray) {
    System.out.printf("Searching for %d in %s%n", searchFor, Arrays.toString(inArray));
    return binarySearch(searchFor, inArray, 0, inArray.length);
}

System.out.println(binarySearch(10));
    System.out.println(binarySearch(10, 10));
    System.out.println(binarySearch(10, 1));
    System.out.println(binarySearch(10, 0, 1, 5, 8, 10, 21));
    System.out.println(binarySearch( 0, 0, 1, 5, 8, 10, 21));
    System.out.println(binarySearch(21, 0, 1, 5, 8, 10, 21));
    
    System.out.println(binarySearch(10, 0, 1, 3, 5, 8, 10, 21));
    System.out.println(binarySearch( 0, 0, 1, 5, 8, 10, 15, 21));
    System.out.println(binarySearch(21, 0, 1, 5, 8, 10, 16, 21));
    
    System.out.println(binarySearch(30, 0, 1, 5, 8, 10, 21));
    System.out.println(binarySearch(-1, 0, 1, 5, 8, 10, 21));
    System.out.println(binarySearch(7, 0, 1, 5, 8, 10, 21));

Output: Output:

Searching for 10 in []
-1
Searching for 10 in [10]
10
Searching for 10 in [1]
-1
Searching for 10 in [0, 1, 5, 8, 10, 21]
10
Searching for 0 in [0, 1, 5, 8, 10, 21]
0
Searching for 21 in [0, 1, 5, 8, 10, 21]
21
Searching for 10 in [0, 1, 3, 5, 8, 10, 21]
10
Searching for 0 in [0, 1, 5, 8, 10, 15, 21]
0
Searching for 21 in [0, 1, 5, 8, 10, 16, 21]
21
Searching for 30 in [0, 1, 5, 8, 10, 21]
-1
Searching for -1 in [0, 1, 5, 8, 10, 21]
-1
Searching for 7 in [0, 1, 5, 8, 10, 21]
-1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM