コンテンツにスキップ

2-3 フィンガーツリー

出典: フリー百科事典『ウィキペディア(Wikipedia)』

2-3(2-3 finger treefinger tree)2006Ralf HinzeRoss Paterson[1][2]

使Haskellcontainers[3]Data.Sequence[4]fingertree[5]Scalascalaz[6]

[]


2-323(finger)[7] 辿辿辿(2-3)

辿22

2-3232314132-3
2-3

2-3Haskell
-- 2-3フィンガーツリー
data FingerTree a = Empty -- 空の木
                  | Single a -- 1つだけ要素を持つ木
                  | Deep (Digit a) (FingerTree (Node a)) (Digit a) -- より深い木

-- 左右の木の根。1から4つの要素を持つ。
data Digit a = One a | Two a a | Three a a a | Four a a a a

-- 左右の木の根以外。2つまたは3つの要素を持つ。
data Node a = Node2 a a | Node3 a a a

1DigitNode23DigitNodeNode Integer1Node (Node Integer)2Digit()

[]



[]




1
Empty ▷ a = Single a
(Single a) ▷ b = Deep (One a) Empty (One b)

Digit4Digit1
 (Deep pr m (One b)) ▷ c = Deep pr m (Two b c)

Digit4
 (Deep pr m (Four b c d e)) ▷ f = Deep pr (m ▷ (Node3 b c d)) (Two e f)

1Node

[]


popRpopL

1
 popR (Single a) = (Empty, a)

Digit1
 popR (Deep pr m (Two b c)) = (Deep pr m (One b), c)

Digit1
 popR (Deep pr m (One b)) = (borrowR pr m, b)


 borrowR pr Empty = toTree pr

toTreepr


 borrowR pr m
   = let
       (m', node) = popR m
     in
       Deep pr m' (toDigit node)

toDigitNodeDigitNode23TwoThreeNode

popRpopRborrowR1





171Digit3

[]


22append使

11
 append(pr, [a, b, c, d, e], Single f) = pr ▷ a ▷ b ▷ c ▷ d ▷ e ▷ f


 append(Deep pr m1 (Four a b c d), [e, f, g, h], Deep (Three i j k) m2 sf)
   = let
       m = append(m1, [Node3 a b c, Node3 d e f, Node3 g h i, Node j k], m2)
     in
       Deep pr m sf

[]



class SizeMeasured a where size :: a -> Integer

instance SizeMeasured FingerTree where
  size Empty = 0
  size (Single a) = size a
  size (Deep pr m sf) = size pr + size m + size sf

instance SizeMeasured Digit where
  size (One a) = size a
  size (Two a b) = size a + size b
  -- その他のDigitは省略

instance SizeMeasured Node where
  size (Node2 a b) = size a + size b
  size (Node3 a b c) = size a + size b + size c

newtype Leaf a = Leaf a -- 葉はLeafでくるんでおく。
instance SizeMeasured Leaf where
  size (Leaf _) = 1




iiiisplitTreeAt使

1i0
 splitTreeAt i (Single a) = (Empty, a, Empty)

ii
 splitTreeAt i (Deep pr m sf)
   | i <= size pr -- i番目の葉は左に含まれる
     = let
         (pr1, a, pr2) = splitDigitAt i pr
       in
         (pr1, a, Deep pr2 m sf)
   | i > size pr + size m -- i番目の葉は右に含まれる
     = let
         (sf1, a, sf2) = splitDigitAt (i - size pr - size m) sf
       in
         (Deep pr m sf1, a, pr2)
   -- 続く

iii
 splitDigitAt i (One a) = (Empty, a, Empty)
 splitDigitAt i (Two a b) | i < size a = (Empty, a, Single b)
                          | otherwise = (Single a, b, Empty)
 -- 他のDigitについては略

iiNodeNode
   -- 続き
   | otherwise -- i番目の葉はより深い木に含まれる
       = let
           -- m1とm3はFingerTree、m2はNode。
           (ml, xs, mr) = splitTreeAt (i - size pr) m
           -- lとrはMaybe (Digit a)とする。
           (l, a, r) = splitNodeAt (i - size pr - size ml) xs
         in
           -- deepR, deepLは、rlがNothingの場合に繰り下がり処理をしてFingerTreeを作る関数
           (deepR pr ml l, a, deepL r mr sf)
 
 splitNodeAt i node = -- 省略
 
 deepR pr m Nothing = borrowR pr m
 deepR pr m (Just sf) = Deep pr m sf
 
 -- deepLは省略

[]


i

#e

i使

i使

p0使i0

measurexp
 splitTreeAt p x (Single a) = (Empty, a, Empty)
 splitTreeAt p x (Deep pr m sf)
   | p (x ⊕ measure pr)
     = let
         (pr1, a, pr2) = splitDigitAt p x pr
       in
         (pr1, a, Deep pr2 m sf)
   | p (x ⊕ measure pr ⊕ measure m)
     = let
         (sf1, a, sf2) = splitDigitAt p (i ⊕ measure pr ⊕ measure m) sf
       in
         (Deep pr m sf1, a, pr2)
   | otherwise
       = let
           -- m1とm3はFingerTree、m2はNode。
           (ml, xs, mr) = splitTreeAt p (i ⊕ measure pr) m
           -- lとrはMaybe (Digit a)とする。
           (l, a, r) = splitNodeAt p (i ⊕ measure pr ⊕ measure ml) xs
         in
           -- deepR, deepLは、lrがNothingの場合に繰り下がり処理をしてFingerTreeを作る関数
           (deepR pr ml l, a, deepL r mr sf)

1

実行時間[編集]




implicit recursive slowdown[]


2-3implicit recursive slowdownimplicit recursive slowdownrecursive slowdownrecursive slowdownnnm2-3



[]


#使

[]


measureHaskellscalaz


[]


measurekkkk

[]


()[8]

measure×(en:Algorithms for calculating variance#Parallel algorithm)


参考文献[編集]

  1. ^ Ralf Hinze and Ross Paterson, “Finger Trees: A Simple General-purpose Data Structure”, In Journal of Functional Programming Vol. 16, No. 2, 2006, pp. 197–217, doi:10.1017/S0956796805005769
  2. ^ Finger Trees: A Simple General-purpose Data Structure
  3. ^ containers: Assorted concrete container types
  4. ^ Data.Sequence
  5. ^ fingertree: Generic finger-tree structure, with example instances
  6. ^ FingerTree - scalaz-core_2.13 javadoc
  7. ^ Leo J. Guibas, Edward M. McCreight, Michael F. Plass, and Janet R. Roberts, “A new representation for linear lists”, In Proceedings of the ninth annual ACM symposium on Theory of computing (STOC '77), New York, NY, USA: ACM, 1977, pp. 49–60. DOI=10.1145/800105.803395 http://doi.acm.org/10.1145/800105.803395
  8. ^ sigfpe, “Statistical Fingertrees”, A Neighborhood of Infinity, http://blog.sigfpe.com/2010/11/statistical-fingertrees.html 2011年6月5日アクセス