Skew Binary Random-Access Lists

Linuxの環境整備に熱中していて、すっかり忘れていたけれど、http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf の 6.4.1章について。


これは何かというと、Skew Binary Numbers - komamitsu.logBinary Random-Access List - komamitsu.logを合わせたランダムアクセス向けリストです。


もの凄くあっさりと言うと以下のような特徴を持っています。

  • 二分木の要素数(Node含む)がSkew Binary Numberとなる
  • 繰り上げ・繰り下げの際の挙動もSkew Binary Numberと同じとなる
  • ランダムアクセス時の計算量はO(min(i, log n))でBinary Random-Access Listより少し性能が良いとのこと

内部的な構造について例をあげると…

  • [100; 101] => [(1, Leaf 101); (1, Leaf 100)]
  • [100; 101; 102] => [(3, Node (102, Leaf 101, Leaf 100))]
  • [100; 101; 102; 103] => [(1, Leaf 103); (3, Node (102, Leaf 101, Leaf 100))]
  • [100; 101; 102; 103; 104; 105] => [(3, Node (105, Leaf 104, Leaf 103)); (3, Node (102, Leaf 101, Leaf 100))]

というように、要素を保持していきます(当然、詳細は上記のPDF参照)。


で、いつもの如くこれを実装してみました => http://github.com/komamitsu/ocaml-skew-binary-random-access-list


どうも元の論文(79P: line 23 & 29)のStandardMLのコードが微妙らしく、移植の際には以下のように変更しています。

if i < w div 2 then lookupTree (w div 2, t1, i - 1)
         ↓
if i - 1 < w div 2 then lookupTree (w div 2, t1, i - 1)

で、これの使い方の例はこんな感じです.

open Printf

module M = SkewBinaryRandomAccessList

let p s i = printf "%s : %d\n" s i

let _ =
  let l = [100; 101; 102; 103; 104; 105; 106; 107; 108; 109] in
  let rl = List.fold_left (fun rl x -> M.cons x rl) M.empty l in
  ignore (p "the head of rl" (M.head rl));
  ignore (p "the 2nd of rl" (M.lookup (2 - 1) rl));
  ignore (p "the 5th of rl" (M.lookup (5 - 1) rl));
  ignore (p "the 10th of rl" (M.lookup (10 - 1) rl));
  let the_tail_of_rl = M.tail rl in
  ignore (p "the 2nd of rl via tail" (M.head the_tail_of_rl));
  let rl_replaced_the_1st_with_99 = M.update (1 - 1) 99 rl in
  ignore (p "the head of updated rl" (M.head rl_replaced_the_1st_with_99));
  let rl_replaced_the_9th_with_999 = M.update (9 - 1) 999 rl in
  ignore (p "the 9th of updated rl" (M.lookup (9 - 1) rl_replaced_the_9th_with_999))

これを実行してみると

komamitsu@potato:~/git/ocaml-skew-binary-random-access-list$ ocamlc -o sample skewBinaryRandomAccessList.cmo sample.ml
komamitsu@potato:~/git/ocaml-skew-binary-random-access-list$ ./sample 
the head of rl : 109
the 2nd of rl : 108
the 5th of rl : 105
the 10th of rl : 100
the 2nd of rl via tail : 108
the head of updated rl : 99
the 9th of updated rl : 999

と、きちんと動作しているようです。

後日、暇があったらListとかと性能比較をしてみたいなぁ、なんて。