すべてのプログラマーは、バイナリ検索がデータの順序付けられたリストを検索するための優れた高速な方法であることを教えられています。バイナリ検索を使用したおもちゃの教科書の例はたくさんありますが、実際のプログラミングではどうですか。バイナリ検索は実際のプログラムで実際にどこで使用されていますか?
二分検索が使用されますどこでも。言語ライブラリ(Java、.NET、C++ STLなど)から並べ替えられたコレクションを取得すると、バイナリ検索を使用して(または使用するオプションがあり)、値が検索されます。それを実装する必要はほとんどないことは事実ですが、それを利用するには、その背後にある原則を理解する必要があります。
バイナリ検索を使用すると、順序付けされたデータにすばやくアクセスできますメモリ領域が少ない場合。 100.000の32ビット整数のセットを検索可能な順序付けされたデータ構造に格納したいが、セットを頻繁に変更しないと仮定します。 400.000バイトのソートされた配列に整数を簡単に格納でき、バイナリ検索を使用して高速にアクセスできます。しかし、あなたがそれらを置くならば、例えばBツリー、RBツリー、または「より動的な」データ構造にすると、メモリのオーバーヘッドが発生し始めます。たとえば、左の子ポインタと右の子ポインタがある任意の種類のツリーに整数を格納すると、少なくとも1.200.000バイトのメモリが消費されます(32ビットメモリアーキテクチャを想定)。もちろん、実行できる最適化はありますが、それが一般的な方法です。
順序付けされた配列の更新(挿入または削除を行う)は非常に遅いため、配列が頻繁に変更される場合、バイナリ検索は役に立ちません。
ここで私が二分探索を使用したいくつかの実際的な例:
すべてのプログラマは、デバッグ時にバイナリ検索を使用する方法を知っている必要があります。
プログラムがあり、プログラムの実行中の特定の時点でバグが表示されることがわかっている場合は、バイナリ検索を使用して、実際に発生する場所を特定できます。これは、コードの大部分をシングルステップするよりもはるかに高速です。
二分探索isは良い高速な方法です!
STLや.NETフレームワークなどが登場する前に、独自のカスタマイズされたコレクションクラスをロールする必要がある状況に遭遇することがよくありました。ソートされた配列がデータを格納するための実行可能な場所である場合は常に、バイナリ検索はその配列内のエントリを見つける方法です。
バイナリ検索は今日でも広く使用されていると思いますが、便宜上、ライブラリによって「内部」で処理されます。
BTree実装にバイナリ検索を実装しました。
BTree検索アルゴリズムは、読み取る次のノードブロックを見つけるために使用されましたが、4Kブロック自体(キーサイズに基づいていくつかのキーを含みます)内で、バイナリサーチを使用して(リーフノードの)レコード番号を検索しました)または次のブロック(非リーフノードの場合)。
平衡二分木のように、すべてのチェックで残りの検索スペースの半分を削除するため、シーケンシャル検索に比べて驚くほど高速です。
実践的な例で質問に答えます。
Rプログラミング言語には、パッケージ data.table があります。これは、データ変換のためのC実装の短い構文、高性能拡張機能から知られています。バイナリ検索を使用します。バイナリサーチがなくても、競合他社よりも拡張性が高くなります。
ベンチマークvspython pandasおよびvsR dplyrプロジェクトWiki内 グループ2E9 -ランダムな順序のデータ。
ニースベンチマークvsデータベースvsビッグデータ benchm-databases もあります。
最近のdata.tableバージョン(1.9.6)では、バイナリ検索が拡張され、任意のアトミック列のインデックスとして使用できるようになりました。
私は完全に同意するニースの要約を見つけました- see 。
R比較を行う人は、data.frameではなくdata.tableを使用する必要があります。ベンチマークの場合はさらにそうです。 data.tableは、私がキャリアで見つけた最高のデータ構造/クエリ言語です。それは、Rの世界、そして私のやり方では、すべてのデータ中心言語で先導しています。
そうです、バイナリ検索が使用されており、それのおかげで世界ははるかに良い場所です。
それでも、コードで頻繁に使用して、数千のACLを1秒間に何千回も検索しています。 ACLはファイルから取得すると静的になるため便利です。また、起動時にアレイを追加するときに、アレイを拡張する費用がかかる可能性があります。その実行も非常に高速です。
最大7つの比較/ジャンプで255要素の配列を検索できる場合(511で8、1023で9など)、バイナリ検索がほぼ可能な限り高速であることがわかります。
グラフに2次元データを表示するGUIコントロールに対して、これを実装しました(これが実際にバイナリ検索であることを知ることさえありませんでした)。マウスでクリックすると、データカーソルがx値に最も近いポイントに設定されます。多数のポイント(数1000、これはx86が100 MHzを超えるCPU周波数を取得し始めた頃のことです)を扱う場合、対話的に使用することはできませんでした。最初から線形検索を行っていました。少し考えてみたところ、分割統治の方法でこれに取り組むことができると思いました。すべてのEdgeケースで機能するようになるまで少し時間がかかりました。
これが本当に基本的なCSアルゴリズムであることを知ったのは、しばらくしてからです...
1つの例はstlセットです。基礎となるデータ構造は、バイナリ検索によるO(log n)の検索、挿入、および削除をサポートするバランスのとれたバイナリ検索ツリーです。
別の例は、ログ時間で実行される整数除算アルゴリズムです。
さて、 バイナリ検索 は現在、3Dゲームとアプリケーションの99%で使用されています。スペースはツリー構造に分割され、バイナリ検索を使用して、3Dの位置とカメラに応じて表示するサブディビジョンを取得します。
その最初の最大のショーケースの一つはドゥームでした。バイナリツリーと関連する検索により、レンダリングが強化されました。
バイナリ検索を使用して、Gitでデバッグできます。 git bisect と呼ばれます。
他の場所の中でも、コマンド名の表とそのコマンドを解釈するための関数へのポインターを備えたインタープリターがあります。約60のコマンドがあります。線形検索を使用するのはそれほど面倒ではありませんが、私は二分検索を使用しています。
バイナリソートは、テキストボックスの寸法が一定のフォントをテキストのサイズに調整するのに役立ちます
いくつかの計算を実行するためにコレクションを繰り返し処理するプログラムがありました。これは非効率的だと思ったので、コレクションを並べ替え、単一のバイナリ検索を使用して目的のアイテムを見つけました。私はこのアイテムとそれにマッチする隣人を返しました。コレクションを実際にフィルタリングしました。
これを行うことは、実際にはコレクション全体を繰り返して、一致するアイテムを釣り出すよりも時間がかかりました。
並べ替えと検索のパフォーマンスが最終的には反復に追いつくことがわかっているので、コレクションにアイテムを追加し続けました。速度が同じになるまで、約600個のオブジェクトのコレクションが必要でした。 1000個のオブジェクトには、明らかにパフォーマンス上の利点があります。
また、作業しているデータのタイプ、複製、拡散についても検討します。これは、並べ替えと検索に影響します。
私の答えは、両方の方法を試して時間を計ることです。
hg bisect の基礎です
デジタルタイミングまたはアナログレベルの測定に使用される半導体テストプログラムは、バイナリサーチを多用します。 Advantest、Teradin、Verigyなどの自動テスト装置(ATE)は、入力ロジックを適用してデジタルパーツの出力状態を検証する真理値表ブラスターと考えることができます。
単純なゲートについて考えてみましょう。各サイクルの時間= 0で入力ロジックが変化し、入力ロジックが変化した後X nsで遷移します。 T = Xの前に出力をストローブする場合、ロジックは期待値と一致しません。時間T = Xより遅くストローブし、ロジックは期待値と一致します。バイナリ検索は、ロジックが一致しない最新の値とそれが一致する最も早い部分との間のしきい値を見つけるために使用されます(Teradin FLEXシステムはタイミングを39pSの解像度に解決し、他のテスターは同等です)。これは、遷移時間を測定する簡単な方法です。同じ手法を使用して、セットアップ時間、ホールドタイム、動作可能な電源レベル、電源対遅延などを解決できます。
あらゆる種類のマイクロプロセッサ、メモリ、FPGA、ロジック、および多くのアナログ混合信号回路は、テストと特性評価でバイナリ検索を使用します。
-マイク
Delphiは、ソートされたTStringListで文字列を検索しながら、バイナリ検索を利用できます。
バイナリ検索は、多くの既製のマップ/辞書実装が提供していない機能を提供します:完全に一致しないものを見つけます。
たとえば、バイナリ検索を使用して、GPSログに基づいて写真のジオタグを実装しました。すべてのGPSウェイポイントをタイムスタンプでソートされた配列に入れ、バイナリ検索を使用して、各写真のタイムスタンプに時間的に最も近いウェイポイントを特定します。
.NET SortedDictionary
は(STLマップのように)舞台裏でバイナリツリーを使用していると思います...したがって、バイナリ検索を使用してSortedDictionary
の要素にアクセスします
方程式の根を見つけることは、おそらくバイナリ検索のような非常に簡単なアルゴリズムで実行したい非常に簡単なことの1つでしょう。
Pythonのlist.sort()
メソッドは Timsort を使用します(これは(AFAIK)がバイナリ検索を使用して要素の位置を特定するためです)。