タグ付けされた質問 「search-trees」

効率的なアクセスのためにソートされたデータを格納するために使用されるデータ構造のクラスである検索ツリーに関する質問。

4
赤黒の木はなぜそんなに人気があるのですか?
私が見るところはどこでも、データ構造は赤黒木を使用して実装されているようです(std::setC ++、SortedDictionaryC#などで) アルゴリズムクラスで(a、b)、赤黒、AVLの各ツリーをカバーしたので、次のようになりました(教授に尋ねたり、数冊の本を読んだり、グーグルで調べたりすることからも)。 AVLツリーの平均深度は赤黒ツリーよりも小さいため、AVLツリーの値の検索は一貫して高速です。 赤黒木は、AVL木よりもバランスをとるための構造的な変化が少ないため、挿入/削除の速度が向上する可能性があります。これは、ランタイムと実装に大きく依存するため、これはツリーの構造変更のコストに依存するため、潜在的に言っています(ツリーが不変の場合、関数型言語でも完全に異なる可能性があります) AVLと赤黒木を比較する多くのオンラインベンチマークがありますが、私が驚いたのは、私の教授が基本的に次のいずれかを行うと言ったということです。 パフォーマンスについてそれほど気にかけない場合もあります。その場合、ほとんどの場合、AVLと赤黒の10〜20%の違いはまったく問題になりません。 または、パフォーマンスに本当に関心があります。この場合、AVLツリーと赤黒ツリーの両方を捨てて、Bツリーを使用します。Bツリーは、より良く機能するように調整できます(または(a、b)ツリー、私は)これらすべてを1つのバスケットに入れます。) その理由は、Bツリーがメモリにデータをよりコンパクトに格納するため(1つのノードに多くの値が含まれる)、キャッシュミスがはるかに少なくなるためです。また、ユースケースに基づいて実装を微調整し、Bツリーの順序をCPUキャッシュサイズなどに依存させることもできます。 問題は、実際の最新のハードウェアでの検索ツリーのさまざまな実装の実際の使用状況を分析するソースがほとんど見つからないことです。私はアルゴリズムに関する多くの本を調べましたが、異なるツリーバリアントを一緒に比較するものは見つかりませんでした。実際のプログラムで。) そうは言っても、上記で述べたことに基づいて、Bツリーがそれらを上回るはずであるときに、どこでも赤黒ツリーが使用されている特定の理由がありますか?(私が見つけることができる唯一のベンチマークとして、http://lh3lh3.users.sourceforge.net/udb.shtmlも示していますが、それは特定の実装の問題である可能性があります)。それとも、実装がかなり簡単であるために、誰もが赤黒ツリーを使用する理由、またはそれを別の言葉で言うと、実装が難しいのはなぜですか? また、関数型言語の領域に移動すると、これはどのように変わりますか?ClojureとScalaはどちらもHash配列にマップされた tryを使用しているようで、Clojureは32の分岐係数を使用しています。

1
赤黒の木を想像してください。それを作成する挿入と削除のシーケンスは常にありますか?
次の赤黒ツリーの定義を想定してみましょう。 これは二分探索木です。 各ノードは赤または黒の色で表示されます。ルートは黒です。 エッジで接続された2つのノードを同時に赤にすることはできません。 wikiのように、NILリーフの適切な定義が必要です。NILの葉は黒く着色されています。 ルートから任意のNILリーフへのパスには、同じ数の黒いノードが含まれます。 質問 赤黒ツリーのinsertand delete操作を実装したとします。さて、あなたが有効な赤黒木を与えられたら、それを構築する一連の操作insertとdelete操作が常にありますか? 動機 この質問は、この質問とこの質問からの議論によって動機付けられています。ます。 個人的には、黒のノードだけで構成される有効な赤黒木を想像すると(完全にバランスの取れた木を想像していることを意味します)、それを構築するシーケンスinsertとdelete操作があると思います。しかしながら、 私はそれを正確に証明する方法がわかりません より一般的なケースにも興味があります

2
すべての赤黒の木のバランスが取れているわけではありませんか?
直感的に、「バランスの取れたツリー」は、各ノードの左右のサブツリーが「ほぼ同じ」数のノードを持たなければならないツリーでなければなりません。 もちろん、赤黒木*(最後の定義を参照)のバランスについて話すとき、実際には、それらは高さのバランスが取れており、その意味で、バランスが取れていることを意味します。 上記の直観を次のように形式化しようとするとします。 定義:バイナリツリーはμμ\mu -balanced と呼ばれ、、ノードごとに不等式0≤μ≤120≤μ≤120 \le \mu \leq \frac{1}{2}NNN μ≤|NL|+1|N|+1≤1−μμ≤|NL|+1|N|+1≤1−μ \mu \le \frac{|N_L| + 1}{|N| + 1} \le 1 - \mu がすべて保持され、上記のステートメントが失敗するノードがあります。は、および左サブツリー内のノードの数ですがルート(ルートを含む)であるツリーの下のノードの数です。μ′>μμ′>μ\mu' \gt \mu|NL||NL||N_L|NNN|N||N||N|NNN このトピックに関する文献のいくつかでは、これらはウェイトバランスツリーと呼ばれています。 ノードを持つバイナリツリーが -balanced(定数)である場合、ツリーの高さはであるため、適切な検索を維持できることがわかります。プロパティ。nnnμμ\muμ>0μ>0\mu \gt 0O(logn)O(log⁡n)\mathcal{O}(\log n) 質問は次のとおりです。 いくつかありますすべてのビッグ十分な赤黒木があるように、 -balancedは?μ>0μ>0\mu \gt 0μμ\mu 使用する赤黒木の定義(Cormenらによるアルゴリズムの紹介から): 各ノードが赤または黒に色付けされているバイナリ検索ツリー 根は黒です すべてのNULLノードは黒です ノードが赤の場合、その子は両方とも黒です。 各ノードについて、そのノードから子孫NULLノードへのすべてのパスには、同じ数の黒いノードがあります。 注:上記の -balancedの定義では、NULLノードはカウントしません。(私たちがそうするかどうかは問題ではないと思いますが)。μμ\mu

2
Cのvoid型がempty / bottom型と類似していないのはなぜですか?
ウィキペディアと私が見つけた他のソースはvoid、空のタイプではなくユニットタイプとしてリストCのタイプを見つけました。void空の/下の型の定義によりよく適合するように思えるので、この混乱を見つけます。 void私が知る限り、値は存在しません。 戻り値の型がvoidの関数は、関数が何も返さないため、何らかの副作用しか実行できないことを指定します。 タイプのポインターvoid*は、他のすべてのポインタータイプのサブタイプです。また、void*C との間の変換は暗黙的です。 最後の点voidに、空の型であることの引数としてのメリットがあるかどうかはわかりvoid*ませんvoid。 一方、voidそれ自体は他のすべてのタイプのサブタイプではありません。これは、タイプがボトムタイプであるための要件であると言えます。
28 type-theory  c  logic  modal-logic  coq  equality  coinduction  artificial-intelligence  computer-architecture  compilers  asymptotics  formal-languages  asymptotics  landau-notation  asymptotics  turing-machines  optimization  decision-problem  rice-theorem  algorithms  arithmetic  floating-point  automata  finite-automata  data-structures  search-trees  balanced-search-trees  complexity-theory  asymptotics  amortized-analysis  complexity-theory  graphs  np-complete  reductions  np-hard  algorithms  string-metrics  computability  artificial-intelligence  halting-problem  turing-machines  computation-models  graph-theory  terminology  complexity-theory  decision-problem  polynomial-time  algorithms  algorithm-analysis  optimization  runtime-analysis  loops  turing-machines  computation-models  recurrence-relation  master-theorem  complexity-theory  asymptotics  parallel-computing  landau-notation  terminology  optimization  decision-problem  complexity-theory  polynomial-time  counting  coding-theory  permutations  encoding-scheme  error-correcting-codes  machine-learning  natural-language-processing  algorithms  graphs  social-networks  network-analysis  relational-algebra  constraint-satisfaction  polymorphisms  algorithms  graphs  trees 

1
スプレイツリーローテーションアルゴリズムが親ノードと祖父母ノードの両方を考慮するのはなぜですか?
スプレーツリーデータ構造の回転が、評価ノードの親だけでなく、祖父母(zig-zagおよびzig-zig操作)も考慮している理由はよくわかりません。以下が機能しないのはなぜですか: たとえば、ツリーに新しいノードを挿入するときに、左または右のサブツリーに挿入するかどうかを確認します。左に挿入する場合、結果を右に回転させ、右のサブツリーに対して結果を右に回転させます。再帰的にこのようになります Tree insert(Tree root, Key k){ if(k < root.key){ root.setLeft(insert(root.getLeft(), key); return rotateRight(root); } //vice versa for right subtree } それは、「スプレイ」手順全体を回避するはずです、あなたは思いませんか?

1
AVLツリーはウェイトバランスされていませんか?
前の質問では、重量バランスの取れた木の定義と赤黒木に関する質問がありました。 この質問は、AVLツリーの場合と同じ質問をすることです。 問題は、他の質問と同様にバランスのとれた木の定義を考えると、μμ\mu いくつかありますすべての大きな十分なAVL木があるように、 -balancedは?μ > 0μ>0\mu \gt 0μμ\mu AVLツリーの定義は1つだけで、あいまいさはないと思います。

1
ロックのない、一定の更新時間の同時ツリーデータ構造?
私は最近少しの文献を読んでいて、かなり興味深いデータ構造を見つけました。 更新時間を最悪の場合の更新時間まで下げるさまざまな方法を調査しました[1-7]。O(1)O(1)\mathcal{O}(1) 最近、効率的な同時アクセスをサポートするために、ロックフリーのデータ構造の調査を開始しました。 これらの最悪の場合の更新時間技術は、ロックフリーデータ構造の実装に使用されていますか?O(1)O(1)\mathcal{O}(1) 私が尋ねるのは; 私には、それらはこの「理論的強化」の明らかな実際的な拡張のように思えます。 タージャン、ロバート・エンドレ。「O(1)ローテーションでのバランスの取れた検索ツリーの更新。」情報処理レター16、no。5(1983):253 – 257。 Driscoll、JR、N Sarnak、DD Sleator、およびRE Tarjan。「データ構造の永続化」。第18回コンピューティング理論に関する年次ACMシンポジウムの議事録、109–121。STOC '86。ニューヨーク、ニューヨーク、アメリカ:ACM、1986。 Levcopoulos、C。、およびMark H. Overmars。「O(1)最悪の場合の更新時間を備えたバランスの取れた検索ツリー。」Acta Inf。26、いいえ。3(1988年11月):269–277。 フライシャー、ルドルフ。O(1)ワーストケース更新時間を備えた単純なバランスの取れた検索ツリー ディーツ、ポールF、ラジーエフラマン。「一定の更新時間のフィンガー検索ツリー。」情報処理レター52、いいえ。3(1994):147 – 154。 Lagogiannis、George、Christos Makris、Yannis Panagis、Spyros Sioutas、Kostas Tsichlas。「最悪の場合の一定の更新時間を備えた新しい動的なバランスの取れた検索ツリー。」J. Autom。ラング。櫛。8、いいえ。4(2003年7月):607–632。 Brodal、GerthStølting、George Lagogiannis、Christos Makris、Athanasios Tsakalidis、Kostas Tsichlas。「ポインターマシンでの最適な指探索ツリー」。J。Comput。システム。科学 67、いいえ。2(2003年9月):381–418。

2
自己順序付けバイナリツリーの作成
バイナリ検索ツリーを使用して自己アクセス順序に変更する必要がある割り当てがあり、最もアクセスされる(優先度が高い)アイテムがツリーの最上部にあり、ルートが最もアクセスされるノードです。 教授は私にBSTとノード構造体を提供してくれましたが、挿入中にツリーを更新するアルゴリズムに頭を悩ませようとすると混乱します。 挿入が発生すると、現在のノードのデータが現在のノードより少ないか大きいかをチェックし、nullポインターを見つけてそこに挿入するまで再帰的に正しい方向に進みます。挿入された後、優先度が1増加します。 template <class Type> void BinarySearchTree<Type> :: insert( const Type & x, BinaryNode<Type> * & t ) { if( t == NULL ) t = new BinaryNode<Type>( x, NULL, NULL ); else if( x < t->element ) insert( x, t->left ); else if( t->element < x ) insert( …

2
二分木の色を赤黒木にする
一般的なインタビューの質問は、特定のバイナリツリーが高さのバランスが取れているかどうかを判断するアルゴリズムを提供することです(AVLツリー定義)。 赤黒木で似たようなことができるのかと思っていました。 任意の未着色のバイナリツリー(NULLノード)が与えられた場合、ノードが赤黒ツリーのすべてのプロパティを満足するようにノードを赤/黒に色付けできるかどうかを判断できる「高速」アルゴリズムがあります。 (この質問のような定義)? 最初の考えは、NULLノードを削除して、結果のツリーが赤黒ツリーになり得るかどうかを再帰的に検証しようとすることでしたが、それはどこにも行かないようでした。 私は論文を(簡単に)ウェブ検索しましたが、この問題に対処していると思われるものを見つけることができませんでした。 単純なものが欠けている可能性があります。

3
配列なしのメモ化
Cormen et al。の「アルゴリズムの概要」のセクション15.3 動的プログラミングの要素では、メモ化について次のように説明しています。 メモ化された再帰アルゴリズムは、各サブ問題の解決策のエントリをテーブルに保持します。各テーブルエントリには、エントリがまだ入力されていないことを示す特別な値が最初に含まれています。再帰アルゴリズムが展開するときにサブ問題に最初に遭遇すると、その解が計算されてテーブルに保存されます。このサブ問題に遭遇するたびに、テーブルに保存されている値を検索して返します。 さらに、脚注として追加します。 このアプローチでは、考えられるすべてのサブ問題パラメーターのセットがわかっていること、およびテーブルの位置とサブ問題の間の関係が確立されていることを前提としています。別のより一般的なアプローチは、サブ問題パラメーターをキーとしてハッシュを使用してメモすることです。 メモした値を(多次元)配列ではなく辞書に保存する必要がある(または簡単にする)よく知られているDPの問題はありますか? 背景:これが何らかの用途であれば、この質問の理由は、動的プログラミングを見たばかりの人に(自己均衡型)バイナリ検索ツリーの概念を動機付けようとしているからです。

2
BSTでの検索時に可能な検索パスの数
次の質問がありますが、答えはありません。私の方法が正しいかどうか私は感謝します: Q.バイナリサーチツリーでキー値60を検索すると、キー値10、20、40、50、70、80、90を含むノードが、必ずしも指定された順序で移動されるわけではありません。これらのキー値が、値60を含むルートノードからの検索パスで発生する可能性のある順序はいくつありますか? (A)35(B)64(C)128(D)5040 質問から、与えられたすべてのノードをトラバーサルに含める必要があり、最終的にキー60に到達する必要があることを理解しています。たとえば、そのような組み合わせの1つは次のようになります。 10、20、40、50、90、80、70、60。 上記のすべてのノードをトラバースする必要があるため、10または90から開始する必要があります。20から開始すると、10に到達しません(60> 20であり、20の右サブツリーをトラバースするため)。 同様に、80から始めることはできません。90に到達できないためです。80> 60なので、80の左のサブツリーをトラバースし、90に到達しません。 残りのノードは20、40、50、70、80、90です。次のノードは20または90のいずれかです。前述の同じ理由で他のノードを取得することはできません。 同様に考えると、各レベルで2つの選択肢があります。ノードは7つあるため、最初の6つには2つの選択肢があり、最後の1つには選択肢がありません。だから完全にあります 2∗2∗2∗2∗2∗2∗12∗2∗2∗2∗2∗2∗12*2*2*2*2*2*1順列= = 6426262^6646464 これは正解ですか? そうでない場合、より良いアプローチは何ですか? 一般化したいと思います。場合ノードが次に与えられる合計の可能な検索パスは次のようになり2 n − 1nnn2n−12n−12^{n-1}

4
2つの異なるツリーの予約注文トラバーサルは、たとえ異なっていても同じですか?
この質問は、それらが可能であることをかなり説明していますが、同じプレオーダートラバーサルを持つ2つの異なるツリーがある例は示していません。 また、構造的には異なりますが、2つの異なるツリーの順序トラバーサルは同じでもかまいません。この例はありますか?

2
リストの代わりに検索ツリーを使用したハッシュ
私はハッシュと二分探索木資料と格闘しています。そして、同じハッシュ値を持つエントリを格納するためにリストを使用する代わりに、バイナリサーチツリーを使用することも可能だと私は読んだ。そして、私は操作の最悪の場合と平均の場合の実行時間を理解しようとします insert、 find そして delete 価値があります。平均的なケース。リストに関しては改善されますか?

3
整数の範囲を効率的に格納するデータ構造はどれですか。
コレクションを0から65535の範囲の整数で保持する必要があるため、次のことをすばやく実行できます。 新しい整数を挿入する 連続する整数の範囲を挿入する 整数を削除する 整数以下のすべての整数を削除します 整数が存在するかどうかをテストします 私のデータには、コレクションに整数の実行が含まれることが多いという特性があります。たとえば、ある時点でのコレクションは次のようになります。 { 121, 122, 123, 124, 3201, 3202, 5897, 8912, 8913, 8914, 18823, 18824, 40891 } 最も単純なアプローチは、C ++ std :: setのようなバランスのとれたバイナリツリーを使用することですが、それを使用して、私はしばしば数値の実行があるという事実を利用していません。おそらく、範囲のコレクションを格納する方が良いでしょうか?しかし、これは、範囲内の整数が削除された場合、または2つの範囲間のスペースが埋められた場合に結合された場合、範囲を分割できる必要があることを意味します。 この問題に適している既存のデータ構造はありますか?


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.