web-dev-qa-db-ja.com

三元検索がある場合、なぜ二分検索を使用するのですか?

最近、配列を3つの部分に分割して比較する三元検索について聞きました。ここでは2つの比較がありますが、配列はn/3に減少します。なぜこんなに使わないの?

40
mousey

実際、人は任意のkに対してk-aryツリーを使用します。

ただし、これはトレードオフです。

K-aryツリー内の要素を見つけるには、約k * ln(N)/ ln(k)演算が必要です(基本変更式を思い出してください)。 kが大きいほど、必要な操作全体が多くなります。

あなたが言っていることの論理的な拡張は、「なぜ人々はN個のデータ要素にN-aryツリーを使用しないのですか?」です。もちろん、これは配列になります。

42
Borealid

三元検索でも、同じ漸近的な複雑さO(log N)検索時間が得られ、実装が複雑になります。

同じ理由が、クワッドサーチやその他の高次を必要としない理由についても言えます。

26
Akusete

10億(10億-1億)の並べ替えられたアイテムを検索すると、平均で約15のバイナリ検索での比較と約9の比較で3項検索が行われますが、大きな利点ではありません。また、各「3項比較」には2つの実際の比較が含まれる場合があることに注意してください。

25
Michael Burr

ワオ。投票した上位の回答は、この質問に回答できなかったと思います。

CPUは3値論理を単一の操作としてサポートしていません。これは、3値論理を数段階の2値論理に分割します。 CPUに最適なコードはバイナリロジックです。 3値論理を単一の操作としてサポートするチップが一般的だったとしても、それは正しいでしょう。

Bツリーは各ノードに複数のブランチを持つことができます。次数3のBツリーは3値論理です。ツリーを下に移動するたびに、1つではなく2つの比較が行われます。これにより、CPU時間が遅くなる可能性があります。

ただし、Bツリーはかなり一般的です。ツリー内のすべてのノードがディスク上の別々の場所に格納されると想定すると、ほとんどの時間をディスクから読み取ることになり、CPUはボトルネックになりませんが、ディスクはボトルネックになります。したがって、ノードごとに100,000の子を持つBツリーを取得するか、他の何でもかろうじてメモリの1つのブロックに適合します。この種の分岐要因を持つBツリーは、3ノードを超える高さになることはめったになく、巨大な巨大なデータセットを検索するために、3回のディスク読み取り(ボトルネックで3回の停止)しかありません。

レビュー:

  • 三元ツリーはハードウェアでサポートされていないため、実行速度が遅くなります。
  • 大規模なデータセットのディスク最適化では、3をはるかに超えるB-tressが一般的です。 2を超えたら、3より高くなります。
10
Dean J

3進検索が2進検索よりも高速になる唯一の方法は、2ウェイ比較のコストの約1.55倍未満で3ウェイパーティション決定を実行できる場合です。アイテムがソートされた配列に格納されている場合、3方向の決定は平均して2方向の決定の1.66倍のコストになります。ただし、情報がツリーに格納されている場合、情報をフェッチするコストは実際に比較するコストに比べて高く、キャッシュの局所性は、関連するデータのペアをランダムにフェッチするコストが、単一のデータをフェッチするコストよりもはるかに悪いことを意味しますデータム、三元またはn方向ツリーは、効率を大幅に向上させる可能性があります。

8
supercat

Ternary検索の方が高速であると思われる理由は何ですか?

比較の平均数:

in ternary search = ((1/3)*1 + (2/3)*2) * ln(n)/ln(3) ~ 1.517*ln(n)
in binary search  =                   1 * ln(n)/ln(2) ~ 1.443*ln(n).

比較の最悪数:

in ternary search = 2 * ln(n)/ln(3) ~ 1.820*ln(n)
in binary search  = 1 * ln(n)/ln(2) ~ 1.443*ln(n).

したがって、三元検索の方が悪いようです。

8
Aryabhatta

また、このシーケンスは、一般化すると線形探索に一般化されることに注意してください。

Binary search
Ternary search
...
...
n-ary search ≡ linear search

したがって、n項検索では、最大n個の実際の比較が行われる可能性がある「1つだけの比較」が存在します。

5
Lazer

「三項」(三項?)検索は、最良のケースでより効率的です。これには、最初の要素(または最初に行う比較によっては最後の要素)の検索が含まれます。最初にチェックしている最後から遠い要素の場合、2つの比較では配列が毎回2/3ずつ狭められますが、バイナリ検索による同じ2つの比較では検索スペースが3/4狭められます。

それに加えて、バイナリ検索はより簡単です。最初の3分の1を下回る場合は比較するのではなく、どちらか片方を比較して取得するだけです。

2
cHao

三元検索は、FPGAとASICなどの並列アーキテクチャで効果的に使用できます。たとえば、検索に必要な内部FPGAメモリがFPGAリソースの半分未満の場合、メモリブロックを複製できます。これにより、2つの異なるメモリアドレスに同時にアクセスし、すべての比較を1つのクロックサイクルで実行できます。これは、100MHz FPGAが4GHz CPUよりも優れている場合がある理由の1つです:)

2
Thu

バイナリサーチツリーに関するほとんどすべての教科書とウェブサイトは実際にはバイナリツリーについて話していない!彼らはあなたに三分探索木を示します!真の二分木は、内部ノードではなくリーフにデータを格納します(ナビゲートするキーを除く)。一部では、これらの葉ツリーを呼び出して、教科書に示されているノードツリーを区別しています。

J. Nievergelt、C.-K。ウォン:バイナリツリーの総パス長の上限、ジャーナルACM 20(1973)1–6。

これに関する以下は、データ構造に関するピーター・ブラスの本からです。

2.1探索木の2つのモデル

上記の概要では、最初は取るに足らないように見える重要なポイントを省略しましたが、実際には、2つの異なる検索ツリーモデルにつながります。どちらのモデルも、次の資料の多くと組み合わせることができますが、その1つは非常に好ましいものです。

各ノードでクエリキーをノードに含まれるキーと比較し、クエリキーが小さい場合は左側のブランチをたどり、クエリキーが大きい場合は右側のブランチをたどると、それらが等しい場合はどうなりますか?検索ツリーの2つのモデルは次のとおりです。

  1. クエリキーがノードキーよりも小さい場合は、左の分岐を使用します。そうでなければ、あなたが木の葉に到達するまで、正しい枝を取りなさい。ツリーの内部ノードのキーは、比較のみを目的としています。すべてのオブジェクトは葉の中にあります。

  2. クエリキーがノードキーよりも小さい場合は、左の分岐を使用します。クエリキーがノードキーより大きい場合は、正しい分岐を行います。それらが等しい場合、ノードに含まれるオブジェクトを取得します。

このマイナーポイントには、多くの影響があります。

{モデル1では、基になるツリーはバイナリツリーですが、モデル2では、各ツリーノードは実際には特別な中間の隣接ノードを持つ3ノードです。

{モデル1では、各内部ノードに左と右のサブツリー(それぞれツリーのリーフノード)がありますが、モデル2では、左または右のサブツリーが欠落している可能性がある不完全なノードを許可する必要があります。比較オブジェクトとキーは存在することが保証されています。

したがって、モデル1の検索ツリーの構造は、モデル2のツリーの構造よりも規則的です。これは、少なくとも実装にとっては明らかな利点です。

{モデル1では、内部ノードのトラバースに必要な比較は1つだけですが、モデル2では、3つの可能性をチェックするために2つの比較が必要です。

実際、モデル1と2で同じ高さのツリーには、最大でほぼ同じ数のオブジェクトが含まれていますが、ツリーの最も深いオブジェクトに到達するには、モデル2で2倍の比較が必要です。もちろん、モデル2には、かなり以前に到達したオブジェクトもあります。ルート内のオブジェクトは2回の比較だけで見つかりますが、ほとんどすべてのオブジェクトは最も深いレベルまたはその近くにあります。

定理。高さhでモデル1のツリーには、最大2 ^ h個のオブジェクトが含まれます。高さhでモデル2のツリーには、最大で2 ^ h + 1 − 1個のオブジェクトが含まれます。

これは、高さhのツリーが左と右のサブツリーとして最大でそれぞれh-1の高さのツリーを持ち、モデル2ではそれらの間に1つの追加のオブジェクトを持っているため、簡単にわかります。

{モデル1では、内部ノードのキーは比較のためにのみ機能し、オブジェクトの識別のためにリーフに再表示される場合があります。モデル2では、各キーはそのオブジェクトとともに1回だけ表示されます。

たとえば、オブジェクトが削除されている場合、モデル1では、どのオブジェクトにも属さない比較に使用されるキーが存在する可能性もあります。これらの比較と識別の機能を概念的に分離することで、これは驚くべきことではなく、後の構造では、オブジェクトに対応しない人工テストを定義して、検索スペースを適切に分割する必要がある場合もあります。モデル1のツリーでは、各内部ノードに空ではない左と右のサブツリーがあるため、比較に使用されるすべてのキーは必然的に異なります。したがって、各キーは最大2回発生します。1回は比較キーとして、もう1回はリーフの識別キーとして発生します。

ほとんどの教科書ではオブジェクトとそのキーが区別されないため、モデル2が推奨される教科書バージョンになりました。キーはオブジェクトです。そうすると、キーをツリー構造で複製することが不自然になります。しかし、すべての実際のアプリケーションでは、キーとオブジェクトの区別は非常に重要です。数字のセットだけを追跡したいとは思わないでしょう。通常、番号はいくつかの詳細情報に関連付けられており、多くの場合、キー自体よりもはるかに大きくなります。

1
mszlazak

これは 私がまったく吟味していないいくつかのランダムな実験的証拠 で、バイナリ検索よりも遅いことを示しています。

1

スケールで物事を比較検討するなぞなぞで三項検索が使用されているのを聞いたことがあるかもしれません。これらのはかりは、3つの答えを返すことができます。左が明るい、両方が同じ、または左が重いです。したがって、三項検索では、比較は1つしかかかりません。ただし、コンピューターはブールロジックを使用します。これには2つの答えしかありません。三元検索を行うには、実際には1ではなく2つの比較を行う必要があります。以前のポスターで述べたように、これがさらに速いケースもあると思いますが、三元検索が常に優れているとは限らないことがわかります。コンピュータ上で実装するのはより混乱し、自然ではありません。

0
muddybruin

三項検索について ブログ を投稿したところ、いくつかの結果が表示されました。私もいくつかの初期レベルの実装を提供しました git repo 三元検索の理論の部分についてはすべてに同意しますが、試してみませんか?実装によれば、3年のコーディング経験があれば、その部分は十分に簡単です。巨大なデータセットがあり、それを何度も検索する必要がある場合は、3進検索の方が有利です。三元検索でもっと上手くできると思ったらそれのために行きなさい。

0
Vraj Pandya

理論的には、最小のk/ln(k)eで達成され、3は2よりもeに近いため、必要な比較は少なくなります。 3/ln(3) = 2.73..および2/ln(2) = 2.88..を確認できます。バイナリ検索の方が高速である理由は、コードのブランチが少なく、最新のCPUで高速に実行されるためです。

0
Daniel Velkov

両方の検索ツリーで同じビッグOの複雑さ(ln n)が得られますが、違いは定数にあります。各レベルで3値探索ツリーをさらに比較する必要があります。したがって、k-ary検索ツリーの場合、違いはk/ln(k)に要約されます。これにはe = 2.7で最小値があり、k = 2が最適な結果を提供します。

0
Crashh