我已经编写了二进制搜索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)
}
答案 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)
}
}
请注意,阈值只是随机猜测,必须通过执行性能测量来确定。