コンピュータサイエンス において、選択アルゴリズムとは、数値などの順序付け可能な値の集合の中で、番目に小さい値。見つかった値は、番目の順序統計量。選択には、コレクション内の最小値、中央値、最大値を見つける問題が特殊なケースとして含まれます。選択アルゴリズムには、クイックセレクトと中央値の中央値アルゴリズムが含まれます。コレクションに適用すると、値、これらのアルゴリズムは線形時間で動作します。ビッグO記法で表すと、データ構造が既に整っている場合は、より高速なアルゴリズムが可能な場合があります。極端な例として、既にソートされた配列の選択には時間がかかります。。
選択問題のアルゴリズムは、値の集合と数値を入力として受け取ります。出力はこれらの値の中で最小の値、または問題のバージョンによっては、最小値。これを適切に定義するには、値を最小から最大にソートできる必要があります。たとえば、整数、浮動小数点数、または数値キーを持つ他の種類のオブジェクトである可能性があります。ただし、既にソートされているとは想定されていません。多くの場合、選択アルゴリズムは比較ベースの計算モデルに制限されます。比較ソートアルゴリズムでは、アルゴリズムは任意の 2 つの値の相対的な順序を決定できる比較操作にアクセスできますが、これらの値に対して他の種類の算術演算を実行することはできません。[ 1 ]
問題を単純化するために、この問題に関するいくつかの研究では、値がすべて互いに異なると仮定している[ 2 ] 、または、同じ値を持つ項目のペアに順序を割り当てるために、何らかの一貫したタイブレーク方法が使用されていると仮定している。問題定義のもう1つのバリエーションは、順序付けられた値の番号付けに関するものである。は、と設定することによって得られる最小値である。配列のゼロベース番号付けのように、または設定によって得られるのでしょうか最小値、2番目に小さい値などを表す通常の英語の慣例に従っていますか?この記事は、Cormen らが使用した慣例に従っており、それによると、すべての値は異なり、最小値は次の値から得られます。[ 2 ]
これらの慣例により、コレクションの中での最大値は値は、設定することで得られます。。いつは奇数であり、コレクションの中央値は を設定することによって得られます。。いつが偶数の場合、中央値には 2 つの選択肢があり、この選択肢を丸めることで得られます。それぞれ下降または上昇:中央値が低いほどそして上部中央値は[ 2 ]
ベースラインアルゴリズムとして、値の集合の中から最小値を求めるには、次の2つの手順を実行します。
この方法の所要時間はソートステップによって支配され、比較ソートを使用した場合の時間。[ 2 ] [ 3 ]整数ソートアルゴリズムを使用する場合でも、これらは一般的に、特殊な選択アルゴリズムを使用した場合に達成できる線形時間よりも遅くなります。それでも、このアプローチの単純さは魅力的であり、特にランタイムライブラリの一部として高度に最適化されたソートルーチンが提供されているが、選択アルゴリズムが提供されていない場合に有効です。中程度のサイズの入力の場合、ソートは実行時間の定数係数が小さいため、非ランダム選択アルゴリズムよりも高速になる可能性があります。[ 4 ]この方法は、コレクションのソート済みバージョンも生成し、これは他の後続の計算、特に他の選択肢による選択に役立つ可能性があります。[ 3 ]
選択ソートのように一度に1つの項目を生成するソートアルゴリズムの場合、スキャンはソートと同時に実行でき、番目の要素が見つかりました。シングルエリミネーショントーナメントにおける慰めブラケットの設計例の1つとして、最終的に優勝したチームに敗れたチームが2位を決定するための別のミニトーナメントを行うというものがありますが、これはこの方法の一例と見なすことができます。[ 5 ]この最適化をヒープソートに適用すると、ヒープセレクトアルゴリズムが生成され、時間における最小値[ 6 ]これは、に比べて小さいしかし、より大きな値の場合例えば、選択肢中央値を求めるために使用されます。
選択方法の多くは、入力から特別な「ピボット」要素を選択し、この要素との比較を使用して残りの要素を分割することに基づいています。入力値を2つのサブセットに分割します。ピボットより小さい要素とセットピボットより大きい要素。アルゴリズムは、比較に基づいて、の最小値を見つける。これらのセットのサイズで。特に、、最小値は、そして同じ選択アルゴリズムを に適用することで再帰的に見つけることができます。。もしすると、最小の値はピボットであり、すぐに返されます。残りのケースでは、最小値はより具体的には、位置にある要素ですの。これは、選択アルゴリズムを再帰的に適用し、この位置の値を探すことによって見つけることができます。[ 7 ]
関連するピボットベースのクイックソートアルゴリズムと同様に、入力の分割はそしてこれらのセット用に新しいコレクションを作成するか、指定されたリストまたは配列データ型をその場で分割する方法によって実行できます。詳細は、入力コレクションの表現方法によって異なります。[ 8 ]ピボットを他のすべての値と比較する時間は[ 7 ]しかし、ピボット法はピボットの選択方法が異なり、それが各再帰呼び出しにおける部分問題の大きさに影響します。これらの方法の効率は、ピボットの選択に大きく依存します。ピボットの選択が不適切な場合、この方法の実行時間は、[ 4 ]

既知の最小比較回数を持つ決定論的選択アルゴリズム、値遠く離れたまたはこれらは、 1976年にアーノルド・シェーンハーゲ、マイク・パターソン、ニック・ピペンジャーによって導入されたファクトリーの概念に基づいています。[ 18 ]これらは、入力値の小さなサブセットに対して、比較を使用してより小さな部分順序を組み合わせることにより、特定の指定されたタイプの部分順序を構築する方法です。非常に単純な例として、あるタイプのファクトリーは、単一要素の部分順序のシーケンスを入力として受け取り、これらの順序の要素のペアを比較し、2要素の完全順序セットのシーケンスを出力として生成できます。このファクトリーへの入力として使用される要素は、まだ何も比較されていない入力値、または他のファクトリーによって生成された「無駄な」値のいずれかです。ファクトリーベースのアルゴリズムの目標は、さまざまなファクトリーを組み合わせ、一部のファクトリーの出力を他のファクトリーの入力として使用して、最終的に1つの要素((最小)は、いくつかのものよりも大きい他の要素よりも小さく、その他。これらの工場を慎重に設計すると、中央値探索に適用した場合、最大で比較。その他の値については比較回数は少なくなる。[ 19 ]
選択のための並列アルゴリズムは、1975年にレスリー・ヴァリアントがこれらのアルゴリズムを分析するための並列比較ツリーモデルを導入し、このモデルでは線形数の比較を使用した選択には最小値や最大値を選択する場合でも、並列ステップが用いられます。[ 20 ]研究者らは後に、選択のための並列アルゴリズムを発見しました。この境界に一致するステップ数。[ 21 ] [ 22 ]ランダム化並列比較ツリーモデルでは、選択を制限されたステップ数と線形回数の比較で実行できます。[ 23 ]排他的読み出し排他的書き込みメモリアクセスを備えた、より現実的な並列RAMコンピューティングモデルでは、選択は時間で実行できます。とプロセッサ数で、時間とプロセッサ数の両方で最適です。[ 24 ]同時メモリアクセスにより、一般的にわずかに高速な並列処理が可能になり、[ 25 ]時間制限内の項は、[ 26 ]
データが既にデータ構造に整理されている場合、値の数に対して非線形な時間で選択を実行できる可能性があります。この簡単な例として、既に配列にソートされているデータの場合、番目の要素は、定数時間で単一の配列ルックアップによって実行できます。[ 27 ]サイズの2次元配列に整理された値の場合行と列がソートされている場合、選択は時間内に実行できます。または、より速く配列の次元に比べて小さい。[ 27 ] [ 28 ]コレクションの場合1次元のソート済み配列で、選択したアイテムよりも少ないアイテムth配列、時間は[ 28 ]
バイナリヒープ内のデータからの選択には時間がかかりますこれはサイズとは無関係です山積みの、そしてより速い最良優先探索から得られる時間制限。[ 28 ] [ 29 ]この同じ方法は、ヒープ順序付けされたツリー(各ノードが1つの値を格納し、各非ルートノードの親が子よりも小さい値を持つツリー)として構成されたデータに、より一般的に適用できます。ヒープでの選択を実行するこの方法は、暗黙的に定義されたヒープ順序付けされたツリーの形式で解の状態空間を定義し、この選択アルゴリズムをこのツリーに適用することにより、重み付きグラフでk個の最短経路を見つけるなど、組み合わせ最適化問題の複数の解をリストアップする問題に適用されています。[ 30 ]反対に、線形時間の選択アルゴリズムは、ヒープに関連する優先度キューデータ構造のサブルーチンとして使用され、その抽出時間を改善しています。アイテムからに;ここは反復対数である。[ 31 ]
動的な挿入と削除が行われるデータ値のコレクションの場合、順序統計ツリーは自己平衡二分探索ツリー構造をツリーノードごとに一定量の追加情報で拡張し、挿入、削除、選択クエリで要求される値を可能にします。現在のセットの 番目の要素はすべて実行されます演算あたりの時間。[ 2 ]計算の比較モデルを超えて、バイナリ算術演算が可能な小さな整数値の場合、演算あたりの時間が速くなる可能性があります。 [ 32 ]メモリが両方とも準線形であるストリーミングアルゴリズムでは不可能です。そして動的データに対して選択クエリを正確に解決するには、カウント-ミニット スケッチを使用できます。これは、要素の順序付けにおける位置 (要素に追加された場合) が、範囲内にある値を見つけることで、選択クエリを近似的に解決します。のステップサイズが対数係数の範囲内にあるスケッチの場合[ 33 ]
の上述の選択アルゴリズムの実行時間は、任意の順序で入力を処理できる選択アルゴリズムが、すべての入力を調べるのにそれだけの時間を要するため、必要不可欠です。入力値のいずれかが比較されない場合、その値が選択されるべき値である可能性があり、アルゴリズムが誤った答えを生成する可能性があります。[ 28 ]この単純な議論を超えて、ランダム化および決定論的ケースの両方において、選択に必要な正確な比較数に関する研究が数多く行われてきました。
最小値を選択する値には比較すると、選択されなかった値はそれぞれ、何らかの比較において最大であることによって最小値ではないと判断されたものでなければならず、これらの値の 2 つが同じ比較において最大となることはない。同じ議論は、最大値を選択する場合にも対称的に適用される。[ 14 ]
次に単純なケースは、2番目に小さい値を選択することです。何度か誤った試みを行った後、このケースに関する最初の厳密な下限は、1964年にソ連の数学者セルゲイ・キスリツィンによって発表されました。2番目に小さい値を選択するには、最小値を他の値から区別する必要があること、そしてその数を考慮することで、このことが示されます。この問題に対するアルゴリズムが行う最小値を含む比較。最小値と比較された項目は、2番目に小さい候補であり、これらの値のうち、2回目の比較で別の値よりも大きい値を見つけなければ、2番目に小さい値として除外することはできません。少なくとも1つの比較において値が大きい方であり、少なくとも 2 つの比較で値が大きい場合、合計で少なくとも比較。各比較の結果が最大化されるように選択される敵対的議論。(少なくとも1つの可能な順序との整合性を条件として)与えられた項目の数値ではなく、強制的に少なくともしたがって、 2番目に小さい値を選択するために必要な最悪の場合の比較回数はこれは、最小値に敗れた値の中から決選投票を行う単一トーナメントを開催した場合に得られる数と同じです。ただし、ランダム選択アルゴリズムの比較回数の期待値は、この上限よりも優れている場合があります。たとえば、6 つの要素の中から 2 番目に小さい値を選択するには、最悪の場合 7 回の比較が必要ですが、ランダムアルゴリズムでは6.5 回の比較で済む場合があります。[ 14 ]
より一般的には、番目の要素少なくとも平均的には、フロイド・リベストアルゴリズムの比較回数に匹敵する比較回数で、用語。この議論は、入力値のすべての可能な順列にわたって平均化された比較回数を持つ決定論的アルゴリズムに対して直接行われます。[ 1 ]ヤオの原理により、これは最悪の場合の入力に対するランダム化アルゴリズムの期待される比較回数にも適用されます。[ 34 ]
決定論的アルゴリズムの場合、th要素には比較では、はバイナリエントロピー関数である。[ 35 ]中央値探索の特殊なケースでは、少なくとも比較回数の下限がわずかに大きくなる。、のために[ 36 ]

クヌースは、次の数の三角形を提供し、そして最適な選択アルゴリズムに必要な比較回数が正確にわかっている場合。三角形の 番目の行((最上段)は、入力の比較回数を示します。価値観、そして各行内の 番目の数字は、選択するために必要な比較回数を示します。そのサイズの入力から番目に小さい値を選択します。行は対称です。最小値を選択するには、最悪の場合、 を選択するのとまったく同じ数の比較が必要になります。2番目に大きい。[ 14 ]
各行の左半分にある項目のほとんど(すべてではない)は、次の式を使用して見つけることができます。これは、Abdollah Hadian とMilton Sobelによる、heapselect に関連する手法によって行われる比較回数を表しています。この手法は、単一エリミネーション トーナメントを使用して最小値を見つけ、その後、最終的なトーナメントの勝者によって排除された値の中からより小さなトーナメントを繰り返し使用して、次の連続する値を見つけ、最終的に最小値に達するまで続けます。最小値。[ 14 ] [ 37 ]より大きなエントリのいくつかは、コンピュータ検索を使用して最適であることが証明されました。[ 14 ] [ 38 ]
一般的な選択を組み込んだサポートを持つ言語はごくわずかですが、多くの言語はリストの最小要素または最大要素を見つけるための機能を提供しています。注目すべき例外は、C++とRustの標準ライブラリです。C ++ の標準テンプレートライブラリは、期待される線形時間を保証するテンプレートメソッドを提供します。 [ 3 ] Rust の標準ライブラリは、データ型のメンバ関数の複数のバリアントを提供します。これらのバリアントはすべて、すべての入力に対して線形実行時間が保証されています。[ 39 ]nth_elementselect_nth_unstableslice
Pythonの標準ライブラリには、コレクションから最小または最大の要素をソートされた順序で返す関数heapq.nsmallestが含まれています。実装ではバイナリヒープが維持され、保持できる要素数はに制限されます。heapq.nlargest要素、そして最初の要素に初期化されますコレクション内の要素。次に、コレクションの各後続の要素は、ヒープ内の最大または最小の要素よりも小さいか大きい場合、その要素を置き換えることができます。このアルゴリズムのメモリ使用量は、heapselect よりも優れています (前者は保持するメモリ量のみ)。一度にメモリに要素を格納できるのに対し、後者はデータセット全体をメモリに操作する必要がある)。実行時間はデータの順序に依存します。最良のケースは既にソートされたデータの場合。最悪のケースは逆順にソートされたデータの場合。平均的なケースでは、ヒープの更新は少なく、ほとんどの入力要素は単一の比較だけで処理される可能性が高い。たとえば、10,000,000 個のランダムな入力から 100 個の最大または最小の値を抽出すると、平均で 10,009,401 回の比較が行われる。[ 40 ]
2017年以降、Matlabには最大値(最小値)を返す関数maxk()と関数が含まれています。mink()ベクトル内の値とそのインデックス。Matlab のドキュメントには、これらの関数がどのアルゴリズムを使用しているか、または実行時間がどれくらいかは明記されていません。[ 41 ]
Quickselectは1965年にTony Hoare によって分析なしで発表され[ 42 ] 、1971年にDonald Knuthによる技術レポートで初めて分析されました[ 11 ]。最初に知られている線形時間決定論的選択アルゴリズムは、1973年にManuel Blum、Robert W. Floyd、Vaughan Pratt、Ron Rivest、およびRobert Tarjanによって発表された中央値法です[ 5 ]。彼らは、選択問題の定式化を、1883年にシングルエリミネーションのスポーツトーナメントの通常の設計では2番目に優れた選手が2位になることが保証されないことを指摘したCharles L. Dodgson( Lewis Carrollとしてよく知られている)の研究[ 5 ] [ 43 ] 、および1930年頃のHugo Steinhausの研究に遡っています。Steinhausは、最小限のゲーム数(つまり比較)でこの保証ができるトーナメント設計を求めることで、同じ考えを続けました。 [ 5 ]