差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
次のリビジョン両方とも次のリビジョン
programming:algorithm:data_structure:union_find_tree [2017/08/07] ikatakosprogramming_algorithm:data_structure:union_find_tree [2017/10/08] – ↷ programming:algorithm:data_structure:union_find_tree から programming_algorithm:data_structure:union_find_tree へページを移動しました。 ikatakos
行 2: 行 2:
  
   * 要素が$n$個ある   * 要素が$n$個ある
-  * 各要素はグループに1つだけ属する +  * 各要素は互いに素なグループに1つだけ属する
-    * 「互いに素な集合」+
     * 例: 生徒は必ず何かのクラブ活動に入り、かつ、兼部は認められていない     * 例: 生徒は必ず何かのクラブ活動に入り、かつ、兼部は認められていない
   * グループは統合される可能性がある。分割はされない   * グループは統合される可能性がある。分割はされない
行 16: 行 15:
   * [[https://www.slideshare.net/chokudai/union-find-49066733|Union find(素集合データ構造)]]   * [[https://www.slideshare.net/chokudai/union-find-49066733|Union find(素集合データ構造)]]
   * [[http://www.geocities.jp/m_hiroi/light/pyalgo61.html|Algorithms with Python / Union-Find]]   * [[http://www.geocities.jp/m_hiroi/light/pyalgo61.html|Algorithms with Python / Union-Find]]
 +  * [[http://dai1741.github.io/maximum-algo-2012/docs/minimum-spanning-tree/|最小全域木(クラスカル法とUnionFind) - アルゴリズム講習会]]
  
 =====アルゴリズム===== =====アルゴリズム=====
  
-  * 各グループの要素から、リーダーを1つ決める +  * 各グループの要素から、"代表"を1つ決める 
-  * リーダー以外の要素は、親となる要素を1つずつ持つ +  * 代表以外の要素は、""となる要素を1つずつ持つ 
-    * つまり、1つのグループを、リーダーを根とした木構造で表現する +    * どの要素からでも、親の親の親……を辿っていけば自身の代表に着くようにする 
-    * 親の親の親……を辿っていけばリーダーに着く+    * つまり、グループを、代表を根とした木構造で表現する
  
-  * ${\rm Union}(x, y)$は、yのリーダーの親をxのリーダーにする +<code> 
-  * ${\rm Find}(x, y)$は、xとyから親を辿って同じリーダーに行き着くか調べる+    1    4    8  ←代表 
 +  ↗↑    ↑ 
 + 2 5    6 
 + ↑     ↗  ↖ 
 + 3    7    9 
 +</code>
  
-=====高速化工夫=====+  * ${\rm Union}(x, y)$は、一方代表を、もう一方の代表につなぐ(親にする) 
 +  * ${\rm Find}(x, y)$は、xとyから親を辿って同じ代表に行き着くか調べる
  
-  * 木の階層を低く保たないと、リーダーを見つける処理に時間がかかる +====高速化の工夫==== 
-    * はやい例ではどの要素からも、1回調べたらにたどり着ける + 
-    * おそい例では、4からだと、4→3→2→1と3回辿らないとに着かない+  * 木の階層を低く保たないと、代表を見つける処理に時間がかかる 
 +    * 以下の例、はやい例では2~4のどの要素からも、1回調べたら代表にたどり着ける 
 +    * おそい例では、4からだと、4→3→2→1と3回辿らないと代表に着かない 
 +    * できるだけ、はやい例のような状態を保ちた
 <code> <code>
 ◎はやい  ×おそい ◎はやい  ×おそい
行 43: 行 52:
 </code> </code>
  
-  * 経路圧縮 +===経路圧縮=== 
-    * 一度調べた経路上にある要素は、全て親をリーダーに書き換える +  * 一度調べた経路上にある要素は、全て親を代表に書き換える 
-      * おそい例において、4調べて1がリーダーだとわかったら、3,4の親を1に書き換える +    * おそい例において、4→3→2→1と調べて1が代表だとわかったら、2~4の親を1に書き換える 
-  ランク + 
-    * 木の深さ情報(ランク)を記録しておく +===ランク=== 
-    * Unionでは、ランクの低い方のグループを、高い方のグループに吸収+  * 木の最大深さ(ランク)を記録しておく 
 +  * Union、ランクの低い方のグループを、高い方のグループにつなぐ 
 +    * 互いのランクが等しい場合を除き、ランクが高くならずに済む(等しい場合のみ1増える) 
 + 
 +<code> 
 +この2つをUnionする場合| こうすると   | 低い方に高い方をつなげると 
 + Rank:   Rank:    | Rank:4のまま | Rank:5になっちゃう 
 +   1        5            5      |     1 
 + ↗↑↖      ↑            ↑↖    | ↗↗↑↖ 
 +2 3 4     6            1 6   |23 4 5 
 +             ↑        ↗↗↑ ↑          ↑ 
 +             7       | 23 4 7          6 
 +             ↑               ↑          ↑ 
 +             8               8          7 
 +                      |              |        ↑ 
 +                      |              |        8 
 +</code> 
 + 
 +ランクは深でなく、要素数で考えこともある 
 + 
 +  * 例: 要素数100,最大深さ2のグループAと、要素数5,最大深さ4のグループB 
 +    * AにBを繋ぐとBの5個の要素の深さが1ずつ増え、最大深さは5 
 +    * BにAを繋ぐとAの100個の要素の深さが1ずつ増え、最大深さは4 
 +    * 局所的に最大深さが深くなろうが、100個の要素の深さが1ずつ増える方が効率悪くない?という考え方か 
 +  * A.V.Aho, John E. Hopcroft, Jeffrey D. Ulman, 『データ構造とアルゴリズム』, 培風館, 1987
  
 =====実装===== =====実装=====
 +
 +  * 要素数$n$の配列''**table**''を作り、-1で初期化する
 +    * ${\rm table}[x]$が負ならば、$x$は代表。絶対値はランクを示す
 +    * ${\rm table}[x]$が非負ならば、$x$は代表でない。値は$x$の親を示す
 +    * 最初は、$n$個の要素が別々の$n$個のグループに所属している状態
 +  * ''_root''で代表を再帰的に探索する
 +    * ついでに経路圧縮を行う
  
 <sxh python> <sxh python>
programming_algorithm/data_structure/union_find_tree.txt · 最終更新: 2023/05/26 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0