van Emde Boas Trees
           〜明日から使えない謎の速い木〜




catupper
van Emde Boas Treesとは
● 読み:ばん えんで ぼーす
● 以下「謎木」


● 集合(set)


● 非常に速い


● あらゆる操作がO(lg lg u)


● 実装が重い
機能要件
●   MAXIMUM   最大値
●   MINIMUM   最小値
●   MEMBER    有無
●   INSERT     挿入
●   DELETE     削除
●   SUCCESSOR  それより大きい最小の要素
●   PREDECESSOR それより小さい最大の要素
平衡二分探索木
●   葉にビットを立てて有無を表現
●   親は全子孫のORの結果を保持(Summary)
                                    1


                    0                               1



            0               0               0               1




        0       0       0       0       0       0       1       0

        0       1       2       3       4       5       6       7
各オーダー
●   MAXIMUM     log u
●   MINIMUM     log u
●   MEMBER      log u
●   INSERT      log u
●   DELETE      log u
●   SUCCESSOR   log u
●   PREDCESSOR log u
●   木の深さに依存
深さを
log log u
 にしたい
平方兵法
●   サイズu の親は サイズ√uの子を√u個持つ
●   最小サイズは2
●   深さはlog log u
                       サイズ256




         サイズ4      サイズ4         サイズ4   サイズ4




                サイズ2      サイズ2
各ノードのデータ
●   サイズuのノード

               サイズ      U   最大値 max      最小値 min


                               Cluster

●   最大値       Summary   木      木  木  木  木  木

●   最小値
●   子へのポインタ
●   Summary
      –   各子に対する そのノードとその子孫のOR値
全体図
各オペレーションの
  オーダー
MIN,MAX,MEMBER
●   MIN、MAX
      –   子孫の最大値と最小値を各親が持ってる
      –   O(1)
●   MEMBER
      –   該当箇所へ降りて行って確認するだけ
      –   処理数は深さ分
      –   O(log log u)
SUCCESSOR,PREDCESSOR
●   SUCCESSOR
       – 木を下りながら
       – minより小さくなったらminを返す
       – maxより大きくなったら次の兄弟のminを返す
       – 次の兄弟はsummaryからSUCCESSORで探す
       – 処理数は深さ分
       – O(log log u)
●   PREDCESSOR
       –   逆も然り
INSERT
●   INSERT
       –   該当場所へ向かって木を降りて行って
       –   minもmaxも未定義だったら両方に入れて
            summaryを更新して終わる
       –   minより小さかったら値を交換して再帰続行
       –   maxより大きかったらmaxを更新
       –   処理数は深さ分
       –   O(log log u)
DELETE
●   DELETE
      –   該当箇所に向かって降りていく
      –   minとmaxが等しかったら削除して終了
      –   minと等しかったらsummaryのminのminで更新
      –   maxと等しかったらsummaryのmaxのmaxで更新
      –   いた木のminとmaxが等しかったらsummary更新
      –   O(log log u)
超ややこしい
要するに
●   maxとminで要素数が0か1か2以上かを判断
      –   Summaryの更新が必要かを判断
●   どの要素もいずれかの木のmin
      –   min maxを中心にオペレーションを回せる
●   Summaryはminを扱わない
      –   削除のとき更新が楽になる
●   要素数が2未満ならそこで再帰終了
      –   必要メモリが減る
空間計算量
● 扱う数字の範囲分(u)必要
● よってO(u)

● Int型なら32bit

● 大きい
使えない?
工夫
● オペレーションは空の木の子に行かない
● 空の木はINSERT時以外更新されない


● INSERT時に動的につくればええやん


● 木の数は要素数(n)を超えない


● よって空間計算量O(n)
やったねたえちゃん




二分ヒープと同じ
まとめ
●   ヒープ並のメモリ使用量でO(log log u)で同じ機能
    をサポート
●   実装
      –   ややこしいオペレーション関数
      –   ややこしい構造
      –   動的ハッシュ
      –   スクリプト言語に向いてない
      –   デバッグ大変でした
まとめ



使えるまでメモリを削減するには
   動的ハッシュが必要
結論




実装が重い!
結論



実装できんかった
   ><
結論



謎木速いんだけど
 微妙にバグる
ご清聴ありがとうございました

Nazoki

  • 1.
    van Emde BoasTrees 〜明日から使えない謎の速い木〜 catupper
  • 2.
    van Emde BoasTreesとは ● 読み:ばん えんで ぼーす ● 以下「謎木」 ● 集合(set) ● 非常に速い ● あらゆる操作がO(lg lg u) ● 実装が重い
  • 3.
    機能要件 ● MAXIMUM   最大値 ● MINIMUM   最小値 ● MEMBER    有無 ● INSERT     挿入 ● DELETE     削除 ● SUCCESSOR  それより大きい最小の要素 ● PREDECESSOR それより小さい最大の要素
  • 4.
    平衡二分探索木 ● 葉にビットを立てて有無を表現 ● 親は全子孫のORの結果を保持(Summary) 1 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 1 2 3 4 5 6 7
  • 5.
    各オーダー ● MAXIMUM  log u ● MINIMUM log u ● MEMBER log u ● INSERT log u ● DELETE log u ● SUCCESSOR log u ● PREDCESSOR log u ● 木の深さに依存
  • 6.
  • 7.
    平方兵法 ● サイズu の親は サイズ√uの子を√u個持つ ● 最小サイズは2 ● 深さはlog log u サイズ256 サイズ4 サイズ4 サイズ4 サイズ4 サイズ2 サイズ2
  • 8.
    各ノードのデータ ● サイズuのノード サイズ U 最大値 max 最小値 min Cluster ● 最大値 Summary 木 木  木  木  木  木 ● 最小値 ● 子へのポインタ ● Summary – 各子に対する そのノードとその子孫のOR値
  • 9.
  • 10.
  • 11.
    MIN,MAX,MEMBER ● MIN、MAX – 子孫の最大値と最小値を各親が持ってる – O(1) ● MEMBER – 該当箇所へ降りて行って確認するだけ – 処理数は深さ分 – O(log log u)
  • 12.
    SUCCESSOR,PREDCESSOR ● SUCCESSOR – 木を下りながら – minより小さくなったらminを返す – maxより大きくなったら次の兄弟のminを返す – 次の兄弟はsummaryからSUCCESSORで探す – 処理数は深さ分 – O(log log u) ● PREDCESSOR – 逆も然り
  • 13.
    INSERT ● INSERT – 該当場所へ向かって木を降りて行って – minもmaxも未定義だったら両方に入れて summaryを更新して終わる – minより小さかったら値を交換して再帰続行 – maxより大きかったらmaxを更新 – 処理数は深さ分 – O(log log u)
  • 14.
    DELETE ● DELETE – 該当箇所に向かって降りていく – minとmaxが等しかったら削除して終了 – minと等しかったらsummaryのminのminで更新 – maxと等しかったらsummaryのmaxのmaxで更新 – いた木のminとmaxが等しかったらsummary更新 – O(log log u)
  • 15.
  • 16.
    要するに ● maxとminで要素数が0か1か2以上かを判断 – Summaryの更新が必要かを判断 ● どの要素もいずれかの木のmin – min maxを中心にオペレーションを回せる ● Summaryはminを扱わない – 削除のとき更新が楽になる ● 要素数が2未満ならそこで再帰終了 – 必要メモリが減る
  • 17.
  • 18.
  • 19.
    工夫 ● オペレーションは空の木の子に行かない ● 空の木はINSERT時以外更新されない ●INSERT時に動的につくればええやん ● 木の数は要素数(n)を超えない ● よって空間計算量O(n)
  • 20.
  • 21.
    まとめ ● ヒープ並のメモリ使用量でO(log log u)で同じ機能 をサポート ● 実装 – ややこしいオペレーション関数 – ややこしい構造 – 動的ハッシュ – スクリプト言語に向いてない – デバッグ大変でした
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.