Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Red-Black Tree for Ruby

Red-Black Tree for Ruby

Kyuden Masahiro

March 22, 2019
Tweet

More Decks by Kyuden Masahiro

Other Decks in Programming

Transcript

  1. I’m kyuden • Github: kyuden • Twitter: @kyuden_ • Banken

    gem creator • https://github.com/kyuden/banken • Sorcery gem commiter • https://github.com/Sorcery/sorcery • WEB+DB Press Ruby連載(vol96~101)
  2. SortedSetの内部実装 – rbtreeを利用しない場合 - • SourtedSet#first – SourtedSet#firstが呼ばれると全要素をArray#sort!して いた •

    一度sortしたものはキャッシュするが新しい要素が 追加/削除された場合はキャッシュが消える • 最悪計算量はO(n^2) • SortedSetという名前からO(log n)を期待していた
  3. 各計算量のおけるステップ数比較 log n n n log n n^2 2 5

    12 25 3 10 33 100 4 15 59 225 4 20 86 400 5 25 116 625 5 30 147 900 7 100 664 10000 8 300 2468 90000 10 1000 9966 1000000 13 10000 132877 100000000 16 100000 1660964 10000000000 20 1000000 19931568 1000000000000
  4. 解決? • とりあえず`gem install rbtree`すればO(log n)が手に入るので今回の問題 は解決する – だがRubyとしてこれで良いのかは少し疑問が残る –

    気づかずにO(n^2)のSortedSetを利用してしまう人がいるのではないか – Ruby本体にrbtreeのようなデータ構造の実装が入ると今回の自分のよ うに調査しなくて済むし、気づかなかった人もO(log n)が手に入る – もしくはRuby本体からSortedSetを削除し後方互換性を考えgemとし て提供するのも選択肢としてはあり?
  5. Red-Black Tree -性質- • 2分木 • 各ノードは赤か黒の色を持つ • 根は黒ノード •

    赤ノードの子は黒ノード • 全ての葉から根への経路上の 黒ノードは同じ個数 1 2 5 4 6 7 8 3
  6. Red-Black Tree -性能- • 探索、挿入、削除の最悪計算量がO(log n) • 木の高さが2logn以下 – 最短のパスは全てが黒ノードのパス、最長のパスは赤黒交互に並ぶノードのパス

    • 最短の最長のパスの長さは2倍以内に収まる ※ AVL木も探索、挿入、削除の最悪計算量はO(log n)だが赤黒木より厳密な平衡性を保つので 赤黒木より木高さも低く検索は早い。一方、その分挿入、削除のリバランスに時間がかかる ため赤黒木より遅くなる場合がある。 よって頻繁に更新しない辞書のような用途だとAVL木が適しているが、様々な汎用的な用 途を考慮すると赤黒木のほうが適しているケースが多いため様々な言語のライブラリの実 装として選択されているのではないかと推測する
  7. Red-Black Tree -ユースケース-優先度付きキュー- • Linuxカーネル 2.6.23 にマージされたCompletely Fair Scheduler (CFS)も内

    部でも仮想実行時間でキーとし優先順序付けされた赤黒木を使用しタスク を選択している。 https://github.com/torvalds/linux/blob/master/kernel/sched/fair.c
  8. Left-leaning Red-Black Tree • 2008年にRobert Sedgewickによって発表された論文※1にて発表された赤黒 木の異種(variant) • もともと赤黒木は1978年にRobert SedgewickとLeonidas

    J. Guibasによって 発表された※2ことを考えると、相対的には最近発表されたといえ、かつ Robert Sedgewick自身による赤黒木の再発明ということでわくわくする ※1 Robert Sedgewick. Left-leaning Red–Black Trees(2008) http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf ※2 赤黒木の元になったのは1972年のRudolf Bayerの発明によるもの
  9. Left-leaning Red-Black Tree - 要約 - • Left-leaning Red-Black Tree(以後

    左傾赤黒木と記載する)は赤黒木より非常にシンプル に実装でき、挿入、削除においては1/4以下のコード量で実装できる – よって従来の赤黒木の複雑性を解決し、メンテナンス性が向上する • 赤黒木と左傾赤黒木のパフォーマンス比較に関しては明確にはこの論文で述べられて いない – Robert Sedgewickによるプレゼンテーション資料※1では左傾赤黒木の特徴として 赤黒木と比較して”less code implies faster insert, delete”とパフォーマンスに関し 言及されていた。(だがあくまで”imply”であり計測結果の数値の記載はない) ※1 Robert Sedgewick. Left-leaning Red–Black Trees http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf
  10. Left-leaning Red-Black Tree - コンセプト - • 左傾赤黒木は赤黒木に対してさらに制約を追加することで赤黒木の複 雑な条件分岐を減らすことに成功している –

    赤黒木を2-3-4木もしくは2-3木に1対1対応させる過程で新しい制 約が生まれ結果それが左傾赤黒木となる 1 2 5 4 6 7 8 3 1 2 3 5 4 6 7 8
  11. 2-3-4木をRed-Black Treeで表現 -3ノード場合- 5 3 3 5 • 子ノードに赤ノードを含む赤黒木で表現する –

    3ノードの場合は上記のように2種類の赤黒木に分類できる – 必ず左の子に赤ノードが傾くという制約を加え、もし右の子に赤いノードが傾いている場合は 左回転(Left flip)して左の子に赤ノードがくるよう強制する(Left-leaning Red-Black Treeという命 名はこの制約からきたものである) • その結果、右の子が赤ノードである多くのケースを排除でき赤黒木の分岐条件を減らすこと ができる 3 3 5 5 3 3
  12. kyuden/llrbtree • 左傾赤黒木を提供するC extention gem • 左傾赤黒木は`llrbtree/ext/llrbtree/tree.c`に実装 • binding部分は左傾赤黒木に合わせて改変したが基本的には rbtree

    gemと同じであるためbinding部分のCopyrightは原 作者のまま • Robert Sedgewickがさきほどの論文で推奨していた再帰に よる追加、削除処理の実装を選択
  13. Red-Black Tree vs Left-leaning Red-Black Tree • 左傾赤黒木はたしかにコード量はシンプルだがパフォーマンス比較の 結果をふまえると、例えばプログラミング言語の標準ライブラリとし て提供するなら赤黒木の方がメリットがあるのではないか

    – 赤黒木の方が歴史が長く安定して実用されてきたという実績から も左傾赤黒木が選ばれるユースケースは限られてくるのではない か – もし要素数が少ない場合のみの使用を前提とするアプリケーショ ンなら実装コストを優先して左傾赤黒木が選択肢になりえる
  14. 本日の内容 • SortedSetの内部実装/気をつけるべき点 • Red-Black Tree – 性質/性能 – ユースケース

    • Left-leaning Red-Black Tree – コンセプト – Red-Black Treeとのパフォーマンス比較