我的二进制搜索实现是否始终正常工作?

时间:2016-06-16 12:26:19

标签: algorithm scala sorting binary-search

我已经编写了二进制搜索scala中整数数组的代码,如下所示。我知道二进制搜索实现起来相当棘手。所以,我想知道这段代码是否总能正常工作。我通过对测试数组进行测试来尝试它,它可以工作。但是,我不确定它是否会一直有效。

注意:假设数组大小永远不会超过最大整数值的一半。

def binarySearch(arr: Array[Int], starti: Int, endi: Int, x: Int) : Int =
{
    if (starti > endi)
        return -1

    val guess = (starti + endi) / 2

    if (arr(guess) == x)
        return guess

    if ((guess != 0) && (arr(guess-1) == x))
        return guess - 1

    if ((guess != endi) && (arr(guess+1) == x))
        return guess + 1

    if (arr(guess) > x)
        return binarySearch(arr, starti, guess-1, x)
    else
        return binarySearch(arr, guess+1, endi, x) 
}

1 个答案:

答案 0 :(得分:2)

根据您的假设似乎是正确的。但是,我总是建议编写val guess = starti + (endi - starti) / 2而不是val guess = (starti + endi) / 2,因为后者在一般情况下可能会溢出(但不是在您的假设下)。

此外,搜索邻居是相当罕见的,在您的情况下它只是开销,因为您使用return binarySearch(arr, starti, guess-1, x)而不是return binarySearch(arr, starti, guess-2, x),同样地return binarySearch(arr, guess+1, endi, x),忽略您已经检查过这些。

我建议删除guess邻居的测试。相反,计算间隔的大小(endi - starti),如果它小于某个阈值,则线性搜索数组x(由于缓存的工作方式,线性遍历非常快)。如果它更大,请使用递归二进制搜索。请注意,在以下示例中,我略微更改了界面:给定的搜索时间间隔不包括endi,以使初始调用更加舒适(binarySearch(arr, 0, arr.length, x))。

def binarySearch(arr: Array[Int], starti: Int, endi: Int, x: Int) : Int =
{
    val threshold = 100

    val len = endi - starti
    if (len <= 0) {
        return -1
    }

    // Optional and purely for performance reasons
    if (len < threshold) {
        for (i <- starti until endi) {
            if (arr(i) == x) {
                return i
            }
        }
    }


    val guess = starti + len / 2
    if (arr(guess) == x) {
        return guess
    } else if (arr(guess) > x) {
        return binarySearch(arr, starti, guess, x)
    } else {
        return binarySearch(arr, guess + 1, endi, x)
    }
}

请注意,阈值只是随机猜测,必须通过执行性能测量来确定。