2016-06-16 8 views
0

以下に示すように、整数の配列を2進数でスカラーで検索するコードを記述しました。私は、バイナリ検索は実装するのが非常に難しいことを知っています。だから、私はこのコードが常に正しく動作するかどうかを知りたい。私はテスト配列に対してテストすることで試してみたところ、うまくいきました。しかし、いつもうまくいくかどうかは分かりません。このバイナリ検索の実装は、常に正しく動作しますか?

メモ:アレイのサイズは、最大整数値の半分以下であるとします。あなたの仮定の下で

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) 
} 
+3

これは、中点計算のための古典的なオーバーフロー加算を含んでいます。負になります.2で除算すると、負の値になります(論理シフトが正しく機能します)。 – harold

+0

正の数の2で除算すると、負の数はどのようになりますか?配列サイズが最大整数値以下であると仮定します。 – pythonic

+0

2で除算しても負の数は出力されません。除算は負の値になりますが、加算の結果を符号なしとして扱うことで回収できる可能性があります。 – harold

答えて

2

それは正しいとです。しかし、私はいつもval guess = (starti + endi)/2の代わりにval guess = starti + (endi - starti)/2と書くことをお勧めします。なぜなら、後者は一般的なケースでオーバーフローする可能性があるからです。

return binarySearch(arr, starti, guess-2, x)の代わりにreturn binarySearch(arr, starti, guess-1, 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) 
    } 
} 

注意しきい値は単にランダムな推測ことと性能測定を行うことによって決定しなければなりません。

+0

xが見つからない場合、-1を返す場合を追加しました。関数の最初の行を参照してください。また、私の前提は、配列のサイズが決して整数の最大値の半分以上ではないということです。 – pythonic

+0

@ hk6279私のコードを尋ねていますか?そうであれば、0を返します。 – pythonic

+1

0が返されます(これは最初にテストされたインデックスなので)。私のバージョンのインターフェイスは、元のインターフェイスと少し異なることに注意してください。元のバージョンでは、間隔に 'endi 'が含まれていましたが、私のバージョンでは除外されています。 IMHOこれは、 'binarySearch(arr、0、arr.length、x)'を使うことができるので、最初の呼び出しをもっとエレガントにしますが、単に個人的な好みです。 – Nicolas

関連する問題