web-dev-qa-db-ja.com

このアルゴリズムを使用した最悪の場合、バイナリ検索はいくつの比較を行いますか?

こんにちは、私のバイナリ検索実装の擬似コードは次のとおりです。

Input: (A[0...n-1], K)
begin
   l ← 0; r ← n-1
   while l ≤ r do
      m ← floor((l+r)/2)
      if K > A[m] then l ← m+1
      else if K < A[m] then r ← m-1 else return m
      end if 
   end while
   return -1 // key not found
end

サイズnのソートされた配列に対して、この実装が最悪の場合に行う比較の数を計算する方法を疑問に思っていましたか?

比較の数はlg n + 1ですか?または何か違う?

18
Harry Tiron

この場合の最悪のケースは、要素KがAに存在せず、Aのすべての要素よりも小さい場合です。その後、各ステップで2つの比較があります:_K > A[m]_と_K < A[m]_。

各ステップで、配列はそれぞれサイズ_(n-1)/2_の2つの部分に分割され、最大log_2(n-1)ステップがあります。

これにより、合計2*log_2(n-1)比較が行われますが、これは漸近的にO(log(n))と等しくなります。

16
hielsnoppe

バイナリ検索 のウィキペディアのページによると、このアルゴリズムの最悪の場合のパフォーマンスはO(lg n)であり、必要な比較の無数の数を測定します。 actual比較の最悪ケースの数は、@ hielsnoppeの回答で指摘されているように、2*lg(n-1)になります。

質問の擬似コードは、バイナリ検索の典型的な実装を表しているため、サイズnの配列(またはベクトル)で予想されるパフォーマンスの複雑さが保持されます。

  • 最高のケースのパフォーマンス:O(1)
  • 平均ケースパフォーマンス:O(lg n)
  • 最悪の場合のパフォーマンス:O(lg n)

よく見ると、質問の擬似コードには2つの問題があります。

  • 行:_if K > A[m] then return l ← m+1_は_if K > A[m] then l ← m+1_を読み取る必要があります。まだ戻れない
  • 次の行:m ← floor((l+r)/2)は、固定サイズの整数を扱うときに数値が十分に大きい場合、オーバーフローを引き起こす可能性があります。正しい構文は、使用している実際のプログラミング言語によって異なりますが、これに沿って何かが問題を解決します:m ← (l + r) >>> 1、ここで_>>>_は符号なし右シフト演算子です。 here で問題の詳細を読んでください。
5
Óscar López