Skip to content
This repository was archived by the owner on May 22, 2026. It is now read-only.

Commit d73a761

Browse files
feat: add FingerTree
1 parent ee24ffc commit d73a761

1 file changed

Lines changed: 141 additions & 0 deletions

File tree

data_structure/tree/fingerTree.hs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
-- 以下のdata型の定義はhttps://www.staff.city.ac.uk/~ross/papers/FingerTree.htmlに記載のあるものを流用している。
2+
data FingerTree a
3+
= Empty -- 要素なし
4+
| Single a -- 要素1つ
5+
| Deep (Digit a) (FingerTree (Node a)) (Digit a)
6+
deriving (Show)
7+
8+
-- Finger Tree左右端のバッファ
9+
data Digit a
10+
= One a
11+
| Two a a
12+
| Three a a a
13+
| Four a a a a
14+
deriving (Show)
15+
16+
-- Finger Treeの中間圧縮ノード
17+
data Node a
18+
= Node2 a a
19+
| Node3 a a a
20+
deriving (Show)
21+
22+
-- 以降はそれっぽく作っているだけ。
23+
24+
-- 先頭(左端)追加
25+
(<|) :: a -> FingerTree a -> FingerTree a
26+
x <| Empty = Single x
27+
x <| Single a = Deep (One x) Empty (One a)
28+
-- pr: prefix(Digit)
29+
-- m: middle(Node)
30+
-- sf: suffix(Digit)
31+
x <| Deep pr m sf =
32+
case pr of -- 左端のDigitのサイズで分岐
33+
One a -> Deep (Two x a) m sf
34+
Two a b -> Deep (Three x a b) m sf
35+
Three a b c -> Deep (Four x a b c) m sf
36+
Four a b c d -> Deep (Two x a) (Node3 b c d <| m) sf -- TODO
37+
38+
-- 末尾(右端)追加
39+
(|>) :: FingerTree a -> a -> FingerTree a
40+
Empty |> x = Single x
41+
Single a |> x = Deep (One a) Empty (One x)
42+
-- pr: prefix(Digit)
43+
-- m: middle(Node)
44+
-- sf: suffix(Digit)
45+
Deep pr m sf |> x =
46+
case sf of
47+
One a -> Deep pr m (Two a x)
48+
Two a b -> Deep pr m (Three a b x)
49+
Three a b c -> Deep pr m (Four a b c x)
50+
Four a b c d -> Deep pr (m |> Node3 a b c) (Two d x)
51+
52+
data ViewR a
53+
= EmptyR
54+
| FingerTree a :> a
55+
deriving (Show)
56+
57+
-- 末尾(右端)とりだし
58+
viewR :: FingerTree a -> ViewR a
59+
viewR Empty = EmptyR
60+
viewR (Single x) = Empty :> x
61+
viewR (Deep pr m sf) =
62+
case sf of
63+
One a ->
64+
case viewR m of
65+
EmptyR -> digitToTreeR pr
66+
m' :> Node2 b c -> Deep pr m' (Two b c) :> a
67+
m' :> Node3 b c d -> Deep pr m' (Three b c d) :> a
68+
Two a b -> Deep pr m (One a) :> b
69+
Three a b c -> Deep pr m (Two a b) :> c
70+
Four a b c d -> Deep pr m (Three a b c) :> d
71+
72+
digitToTreeR :: Digit a -> ViewR a
73+
digitToTreeR (One a) = Empty :> a
74+
digitToTreeR (Two a b) = Single a :> b
75+
digitToTreeR (Three a b c) = Deep (One a) Empty (One b) :> c
76+
digitToTreeR (Four a b c d) = Deep (Two a b) Empty (One c) :> d
77+
78+
data ViewL a
79+
= EmptyL
80+
| a :< FingerTree a
81+
deriving (Show)
82+
83+
-- 先頭(左端)取り出し
84+
viewL :: FingerTree a -> ViewL a
85+
viewL Empty = EmptyL
86+
viewL (Single x) = x :< Empty
87+
viewL (Deep pr m sf) =
88+
case pr of
89+
One a ->
90+
case viewL m of
91+
EmptyL -> case digitToTree sf of
92+
b :< t -> a :< (b <| t)
93+
Node2 b c :< m' -> a :< Deep (Two b c) m' sf
94+
Node3 b c d :< m' -> a :< Deep (Three b c d) m' sf
95+
Two a b ->
96+
a :< Deep (One b) m sf
97+
Three a b c ->
98+
a :< Deep (Two b c) m sf
99+
Four a b c d ->
100+
a :< Deep (Three b c d) m sf
101+
102+
-- digitをFingerTreeに変換する (ViewL用)
103+
digitToTree :: Digit a -> ViewL a
104+
digitToTree (One a) = a :< Empty
105+
digitToTree (Two a b) = a :< Single b
106+
digitToTree (Three a b c) = a :< Deep (One b) Empty (One c)
107+
digitToTree (Four a b c d) = a :< Deep (Two b c) Empty (One d)
108+
109+
main :: IO ()
110+
main = do
111+
-- 末尾追加
112+
let addFingerTree = scanl (|>) Empty [1 .. 21]
113+
putStrLn $ unlines $ map show addFingerTree
114+
putStrLn "--------------------------------------"
115+
-- 先頭追加
116+
let addFingerTree' = scanl (flip (<|)) Empty $ reverse [1 .. 21]
117+
putStrLn $ unlines $ map show addFingerTree'
118+
putStrLn "--------------------------------------"
119+
120+
-- 末端から取り出される過程をみる
121+
let testFingerTree = foldl (|>) Empty [1 .. 21]
122+
let removeSteps = scanl (\ft _ -> restL ft) testFingerTree [1 .. 21]
123+
putStrLn $ unlines $ map show removeSteps
124+
putStrLn "--------------------------------------"
125+
126+
-- 先頭から取り出される過程をみる
127+
let testFingerTree = foldl (|>) Empty [1 .. 21]
128+
let removeSteps = scanl (\ft _ -> restL ft) testFingerTree [1 .. 21]
129+
putStrLn $ unlines $ map show removeSteps
130+
131+
-- viewRの結果から残りの木を取り出す
132+
restR :: FingerTree a -> FingerTree a
133+
restR ft = case viewR ft of
134+
EmptyR -> Empty
135+
rest :> _ -> rest
136+
137+
-- viewLの結果から残りの木を取り出す
138+
restL :: FingerTree a -> FingerTree a
139+
restL ft = case viewL ft of
140+
EmptyL -> Empty
141+
_ :< rest -> rest

0 commit comments

Comments
 (0)