|
1 |
| -module Data.Map |
| 1 | +-- |
| 2 | +-- Maps as balanced 2-3 trees |
| 3 | +-- |
| 4 | +-- Based on http://www.cs.princeton.edu/~dpw/courses/cos326-12/ass/2-3-trees.pdf |
| 5 | +-- |
| 6 | + |
| 7 | +module Data.Map |
2 | 8 | ( Map(),
|
| 9 | + showTree, |
3 | 10 | empty,
|
| 11 | + isEmpty, |
4 | 12 | singleton,
|
| 13 | + checkValid, |
5 | 14 | insert,
|
6 | 15 | lookup,
|
7 |
| - member, |
| 16 | + toList, |
| 17 | + fromList, |
8 | 18 | delete,
|
| 19 | + member, |
9 | 20 | alter,
|
10 | 21 | update,
|
11 |
| - toList, |
12 |
| - fromList, |
13 | 22 | keys,
|
14 | 23 | values,
|
15 | 24 | union,
|
16 | 25 | unions,
|
17 | 26 | map
|
18 | 27 | ) where
|
19 |
| - |
| 28 | + |
20 | 29 | import qualified Prelude as P
|
21 | 30 |
|
22 |
| -import Data.Array (concat) |
23 |
| -import Data.Foldable (foldl) |
24 |
| -import Data.Maybe |
| 31 | +import qualified Data.Array as A |
| 32 | +import Data.Maybe |
25 | 33 | import Data.Tuple
|
26 |
| - |
27 |
| -data Map k v = Leaf | Branch { key :: k, value :: v, left :: Map k v, right :: Map k v } |
| 34 | +import Data.Foldable (foldl) |
| 35 | + |
| 36 | +data Map k v |
| 37 | + = Leaf |
| 38 | + | Two (Map k v) k v (Map k v) |
| 39 | + | Three (Map k v) k v (Map k v) k v (Map k v) |
28 | 40 |
|
29 | 41 | instance eqMap :: (P.Eq k, P.Eq v) => P.Eq (Map k v) where
|
30 | 42 | (==) m1 m2 = toList m1 P.== toList m2
|
31 | 43 | (/=) m1 m2 = P.not (m1 P.== m2)
|
32 | 44 |
|
33 | 45 | instance showMap :: (P.Show k, P.Show v) => P.Show (Map k v) where
|
34 |
| - show m = "fromList " P.++ P.show (toList m) |
35 |
| - |
| 46 | + show m = "fromList " P.++ P.show (toList m) |
| 47 | + |
| 48 | +instance functorMap :: P.Functor (Map k) where |
| 49 | + (<$>) _ Leaf = Leaf |
| 50 | + (<$>) f (Two left k v right) = Two (f P.<$> left) k (f v) (f P.<$> right) |
| 51 | + (<$>) f (Three left k1 v1 mid k2 v2 right) = Three (f P.<$> left) k1 (f v1) (f P.<$> mid) k2 (f v2) (f P.<$> right) |
| 52 | + |
| 53 | +showTree :: forall k v. (P.Show k, P.Show v) => Map k v -> String |
| 54 | +showTree Leaf = "Leaf" |
| 55 | +showTree (Two left k v right) = |
| 56 | + "Two (" P.++ showTree left P.++ |
| 57 | + ") (" P.++ P.show k P.++ |
| 58 | + ") (" P.++ P.show v P.++ |
| 59 | + ") (" P.++ showTree right P.++ ")" |
| 60 | +showTree (Three left k1 v1 mid k2 v2 right) = |
| 61 | + "Three (" P.++ showTree left P.++ |
| 62 | + ") (" P.++ P.show k1 P.++ |
| 63 | + ") (" P.++ P.show v1 P.++ |
| 64 | + ") (" P.++ showTree mid P.++ |
| 65 | + ") (" P.++ P.show k2 P.++ |
| 66 | + ") (" P.++ P.show v2 P.++ |
| 67 | + ") (" P.++ showTree right P.++ ")" |
| 68 | + |
36 | 69 | empty :: forall k v. Map k v
|
37 | 70 | empty = Leaf
|
38 | 71 |
|
39 |
| -singleton :: forall k v. k -> v -> Map k v |
40 |
| -singleton k v = Branch { key: k, value: v, left: empty, right: empty } |
41 |
| - |
42 |
| -insert :: forall k v. (P.Ord k) => k -> v -> Map k v -> Map k v |
43 |
| -insert k v Leaf = singleton k v |
44 |
| -insert k v (Branch b@{ key = k1 }) | k P.== k1 = Branch (b { key = k, value = v }) |
45 |
| -insert k v (Branch b@{ key = k1 }) | k P.< k1 = Branch (b { left = insert k v b.left }) |
46 |
| -insert k v (Branch b) = Branch (b { right = insert k v b.right }) |
| 72 | +isEmpty :: forall k v. Map k v -> Boolean |
| 73 | +isEmpty Leaf = true |
| 74 | +isEmpty _ = false |
47 | 75 |
|
| 76 | +singleton :: forall k v. k -> v -> Map k v |
| 77 | +singleton k v = Two Leaf k v Leaf |
| 78 | + |
| 79 | +checkValid :: forall k v. Map k v -> Boolean |
| 80 | +checkValid tree = A.length (A.nub (allHeights tree)) P.== 1 |
| 81 | + where |
| 82 | + allHeights :: forall k v. Map k v -> [Number] |
| 83 | + allHeights Leaf = [0] |
| 84 | + allHeights (Two left _ _ right) = A.map (\n -> n P.+ 1) (allHeights left P.++ allHeights right) |
| 85 | + allHeights (Three left _ _ mid _ _ right) = A.map (\n -> n P.+ 1) (allHeights left P.++ allHeights mid P.++ allHeights right) |
| 86 | + |
48 | 87 | lookup :: forall k v. (P.Ord k) => k -> Map k v -> Maybe v
|
49 |
| -lookup k Leaf = Nothing |
50 |
| -lookup k (Branch { key = k1, value = v }) | k P.== k1 = Just v |
51 |
| -lookup k (Branch { key = k1, left = left }) | k P.< k1 = lookup k left |
52 |
| -lookup k (Branch { right = right }) = lookup k right |
| 88 | +lookup _ Leaf = Nothing |
| 89 | +lookup k (Two _ k1 v _) | k P.== k1 = Just v |
| 90 | +lookup k (Two left k1 _ _) | k P.< k1 = lookup k left |
| 91 | +lookup k (Two _ _ _ right) = lookup k right |
| 92 | +lookup k (Three _ k1 v1 _ _ _ _) | k P.== k1 = Just v1 |
| 93 | +lookup k (Three _ _ _ _ k2 v2 _) | k P.== k2 = Just v2 |
| 94 | +lookup k (Three left k1 _ _ _ _ _) | k P.< k1 = lookup k left |
| 95 | +lookup k (Three _ k1 _ mid k2 _ _) | k1 P.< k P.&& k P.<= k2 = lookup k mid |
| 96 | +lookup k (Three _ _ _ _ _ _ right) = lookup k right |
53 | 97 |
|
54 | 98 | member :: forall k v. (P.Ord k) => k -> Map k v -> Boolean
|
55 | 99 | member k m = isJust (k `lookup` m)
|
56 | 100 |
|
57 |
| -findMinKey :: forall k v. (P.Ord k) => Map k v -> Tuple k v |
58 |
| -findMinKey (Branch { key = k, value = v, left = Leaf }) = Tuple k v |
59 |
| -findMinKey (Branch b) = findMinKey b.left |
| 101 | +data TreeContext k v |
| 102 | + = TwoLeft k v (Map k v) |
| 103 | + | TwoRight (Map k v) k v |
| 104 | + | ThreeLeft k v (Map k v) k v (Map k v) |
| 105 | + | ThreeMiddle (Map k v) k v k v (Map k v) |
| 106 | + | ThreeRight (Map k v) k v (Map k v) k v |
| 107 | + |
| 108 | +fromZipper :: forall k v. (P.Ord k) => [TreeContext k v] -> Map k v -> Map k v |
| 109 | +fromZipper [] tree = tree |
| 110 | +fromZipper (TwoLeft k1 v1 right : ctx) left = fromZipper ctx (Two left k1 v1 right) |
| 111 | +fromZipper (TwoRight left k1 v1 : ctx) right = fromZipper ctx (Two left k1 v1 right) |
| 112 | +fromZipper (ThreeLeft k1 v1 mid k2 v2 right : ctx) left = fromZipper ctx (Three left k1 v1 mid k2 v2 right) |
| 113 | +fromZipper (ThreeMiddle left k1 v1 k2 v2 right : ctx) mid = fromZipper ctx (Three left k1 v1 mid k2 v2 right) |
| 114 | +fromZipper (ThreeRight left k1 v1 mid k2 v2 : ctx) right = fromZipper ctx (Three left k1 v1 mid k2 v2 right) |
| 115 | + |
| 116 | +data KickUp k v = KickUp (Map k v) k v (Map k v) |
60 | 117 |
|
| 118 | +insert :: forall k v. (P.Ord k) => k -> v -> Map k v -> Map k v |
| 119 | +insert = down [] |
| 120 | + where |
| 121 | + down :: forall k v. (P.Ord k) => [TreeContext k v] -> k -> v -> Map k v -> Map k v |
| 122 | + down ctx k v Leaf = up ctx (KickUp Leaf k v Leaf) |
| 123 | + down ctx k v (Two left k1 _ right) | k P.== k1 = fromZipper ctx (Two left k v right) |
| 124 | + down ctx k v (Two left k1 v1 right) | k P.< k1 = down (TwoLeft k1 v1 right P.: ctx) k v left |
| 125 | + down ctx k v (Two left k1 v1 right) = down (TwoRight left k1 v1 P.: ctx) k v right |
| 126 | + down ctx k v (Three left k1 _ mid k2 v2 right) | k P.== k1 = fromZipper ctx (Three left k v mid k2 v2 right) |
| 127 | + down ctx k v (Three left k1 v1 mid k2 _ right) | k P.== k2 = fromZipper ctx (Three left k1 v1 mid k v right) |
| 128 | + down ctx k v (Three left k1 v1 mid k2 v2 right) | k P.< k1 = down (ThreeLeft k1 v1 mid k2 v2 right P.: ctx) k v left |
| 129 | + down ctx k v (Three left k1 v1 mid k2 v2 right) | k1 P.< k P.&& k P.<= k2 = down (ThreeMiddle left k1 v1 k2 v2 right P.: ctx) k v mid |
| 130 | + down ctx k v (Three left k1 v1 mid k2 v2 right) = down (ThreeRight left k1 v1 mid k2 v2 P.: ctx) k v right |
| 131 | + |
| 132 | + up :: forall k v. (P.Ord k) => [TreeContext k v] -> KickUp k v -> Map k v |
| 133 | + up [] (KickUp left k v right) = Two left k v right |
| 134 | + up (TwoLeft k1 v1 right : ctx) (KickUp left k v mid) = fromZipper ctx (Three left k v mid k1 v1 right) |
| 135 | + up (TwoRight left k1 v1 : ctx) (KickUp mid k v right) = fromZipper ctx (Three left k1 v1 mid k v right) |
| 136 | + up (ThreeLeft k1 v1 c k2 v2 d : ctx) (KickUp a k v b) = up ctx (KickUp (Two a k v b) k1 v1 (Two c k2 v2 d)) |
| 137 | + up (ThreeMiddle a k1 v1 k2 v2 d : ctx) (KickUp b k v c) = up ctx (KickUp (Two a k1 v1 b) k v (Two c k2 v2 d)) |
| 138 | + up (ThreeRight a k1 v1 b k2 v2 : ctx) (KickUp c k v d) = up ctx (KickUp (Two a k1 v1 b) k2 v2 (Two c k v d)) |
| 139 | + |
61 | 140 | delete :: forall k v. (P.Ord k) => k -> Map k v -> Map k v
|
62 |
| -delete k Leaf = Leaf |
63 |
| -delete k (Branch b@{ key = k1, left = Leaf }) | k P.== k1 = |
64 |
| - case b of |
65 |
| - { left = Leaf } -> b.right |
66 |
| - { right = Leaf } -> b.left |
67 |
| - _ -> glue b.left b.right |
68 |
| -delete k (Branch b@{ key = k1 }) | k P.< k1 = Branch (b { left = delete k b.left }) |
69 |
| -delete k (Branch b) = Branch (b { right = delete k b.right }) |
70 |
| - |
| 141 | +delete = down [] |
| 142 | + where |
| 143 | + down :: forall k v. (P.Ord k) => [TreeContext k v] -> k -> Map k v -> Map k v |
| 144 | + down ctx _ Leaf = fromZipper ctx Leaf |
| 145 | + down ctx k (Two Leaf k1 _ Leaf) | k P.== k1 = up ctx Leaf |
| 146 | + down ctx k (Two left k1 _ right) | k P.== k1 = |
| 147 | + let max = maxNode left |
| 148 | + in removeMaxNode (TwoLeft max.key max.value right P.: ctx) left |
| 149 | + down ctx k (Two left k1 v1 right) | k P.< k1 = down (TwoLeft k1 v1 right P.: ctx) k left |
| 150 | + down ctx k (Two left k1 v1 right) = down (TwoRight left k1 v1 P.: ctx) k right |
| 151 | + down ctx k (Three Leaf k1 _ Leaf k2 v2 Leaf) | k P.== k1 = fromZipper ctx (Two Leaf k2 v2 Leaf) |
| 152 | + down ctx k (Three Leaf k1 v1 Leaf k2 _ Leaf) | k P.== k2 = fromZipper ctx (Two Leaf k1 v1 Leaf) |
| 153 | + down ctx k (Three left k1 _ mid k2 v2 right) | k P.== k1 = |
| 154 | + let max = maxNode left |
| 155 | + in removeMaxNode (ThreeLeft max.key max.value mid k2 v2 right P.: ctx) left |
| 156 | + down ctx k (Three left k1 v1 mid k2 _ right) | k P.== k2 = |
| 157 | + let max = maxNode mid |
| 158 | + in removeMaxNode (ThreeMiddle left k1 v1 max.key max.value right P.: ctx) mid |
| 159 | + down ctx k (Three left k1 v1 mid k2 v2 right) | k P.< k1 = down (ThreeLeft k1 v1 mid k2 v2 right P.: ctx) k left |
| 160 | + down ctx k (Three left k1 v1 mid k2 v2 right) | k1 P.< k P.&& k P.< k2 = down (ThreeMiddle left k1 v1 k2 v2 right P.: ctx) k mid |
| 161 | + down ctx k (Three left k1 v1 mid k2 v2 right) = down (ThreeRight left k1 v1 mid k2 v2 P.: ctx) k right |
| 162 | + |
| 163 | + up :: forall k v. (P.Ord k) => [TreeContext k v] -> Map k v -> Map k v |
| 164 | + up [] tree = tree |
| 165 | + up (TwoLeft k1 v1 Leaf : ctx) Leaf = fromZipper ctx (Two Leaf k1 v1 Leaf) |
| 166 | + up (TwoRight Leaf k1 v1 : ctx) Leaf = fromZipper ctx (Two Leaf k1 v1 Leaf) |
| 167 | + up (TwoLeft k1 v1 (Two m k2 v2 r) : ctx) l = up ctx (Three l k1 v1 m k2 v2 r) |
| 168 | + up (TwoRight (Two l k1 v1 m) k2 v2 : ctx) r = up ctx (Three l k1 v1 m k2 v2 r) |
| 169 | + up (TwoLeft k1 v1 (Three b k2 v2 c k3 v3 d) : ctx) a = fromZipper ctx (Two (Two a k1 v1 b) k2 v2 (Two c k3 v3 d)) |
| 170 | + up (TwoRight (Three a k1 v1 b k2 v2 c) k3 v3 : ctx) d = fromZipper ctx (Two (Two a k1 v1 b) k2 v2 (Two c k3 v3 d)) |
| 171 | + up (ThreeLeft k1 v1 Leaf k2 v2 Leaf : ctx) Leaf = fromZipper ctx (Three Leaf k1 v1 Leaf k2 v2 Leaf) |
| 172 | + up (ThreeMiddle Leaf k1 v1 k2 v2 Leaf : ctx) Leaf = fromZipper ctx (Three Leaf k1 v1 Leaf k2 v2 Leaf) |
| 173 | + up (ThreeRight Leaf k1 v1 Leaf k2 v2 : ctx) Leaf = fromZipper ctx (Three Leaf k1 v1 Leaf k2 v2 Leaf) |
| 174 | + up (ThreeLeft k1 v1 (Two b k2 v2 c) k3 v3 d : ctx) a = fromZipper ctx (Two (Three a k1 v1 b k2 v2 c) k3 v3 d) |
| 175 | + up (ThreeMiddle (Two a k1 v1 b) k2 v2 k3 v3 d : ctx) c = fromZipper ctx (Two (Three a k1 v1 b k2 v2 c) k3 v3 d) |
| 176 | + up (ThreeMiddle a k1 v1 k2 v2 (Two c k3 v3 d) : ctx) b = fromZipper ctx (Two a k1 v1 (Three b k2 v2 c k3 v3 d)) |
| 177 | + up (ThreeRight a k1 v1 (Two b k2 v2 c) k3 v3 : ctx) d = fromZipper ctx (Two a k1 v1 (Three b k2 v2 c k3 v3 d)) |
| 178 | + up (ThreeLeft k1 v1 (Three b k2 v2 c k3 v3 d) k4 v4 e : ctx) a = fromZipper ctx (Three (Two a k1 v1 b) k2 v2 (Two c k3 v3 d) k4 v4 e) |
| 179 | + up (ThreeMiddle (Three a k1 v1 b k2 v2 c) k3 v3 k4 v4 e : ctx) d = fromZipper ctx (Three (Two a k1 v1 b) k2 v2 (Two c k3 v3 d) k4 v4 e) |
| 180 | + up (ThreeMiddle a k1 v1 k2 v2 (Three c k3 v3 d k4 v4 e) : ctx) b = fromZipper ctx (Three a k1 v1 (Two b k2 v2 c) k3 v3 (Two d k4 v4 e)) |
| 181 | + up (ThreeRight a k1 v1 (Three b k2 v2 c k3 v3 d) k4 v4 : ctx) e = fromZipper ctx (Three a k1 v1 (Two b k2 v2 c) k3 v3 (Two d k4 v4 e)) |
| 182 | + |
| 183 | + maxNode :: forall k v. (P.Ord k) => Map k v -> { key :: k, value :: v } |
| 184 | + maxNode (Two _ k v Leaf) = { key: k, value: v } |
| 185 | + maxNode (Two _ _ _ right) = maxNode right |
| 186 | + maxNode (Three _ _ _ _ k v Leaf) = { key: k, value: v } |
| 187 | + maxNode (Three _ _ _ _ _ _ right) = maxNode right |
| 188 | + |
| 189 | + removeMaxNode :: forall k v. (P.Ord k) => [TreeContext k v] -> Map k v -> Map k v |
| 190 | + removeMaxNode ctx (Two Leaf _ _ Leaf) = up ctx Leaf |
| 191 | + removeMaxNode ctx (Two left k v right) = removeMaxNode (TwoRight left k v P.: ctx) right |
| 192 | + removeMaxNode ctx (Three Leaf k1 v1 Leaf _ _ Leaf) = up (TwoRight Leaf k1 v1 P.: ctx) Leaf |
| 193 | + removeMaxNode ctx (Three left k1 v1 mid k2 v2 right) = removeMaxNode (ThreeRight left k1 v1 mid k2 v2 P.: ctx) right |
| 194 | + |
71 | 195 | alter :: forall k v. (P.Ord k) => (Maybe v -> Maybe v) -> k -> Map k v -> Map k v
|
72 |
| -alter f k Leaf = case f Nothing of |
73 |
| - Nothing -> Leaf |
74 |
| - Just v -> singleton k v |
75 |
| -alter f k (Branch b@{ key = k1, value = v }) | k P.== k1 = case f (Just v) of |
76 |
| - Nothing -> glue b.left b.right |
77 |
| - Just v' -> Branch (b { value = v' }) |
78 |
| -alter f k (Branch b@{ key = k1 }) | k P.< k1 = Branch (b { left = alter f k b.left }) |
79 |
| -alter f k (Branch b) = Branch (b { right = alter f k b.right }) |
| 196 | +alter f k m = case f (k `lookup` m) of |
| 197 | + Nothing -> delete k m |
| 198 | + Just v -> insert k v m |
80 | 199 |
|
81 | 200 | update :: forall k v. (P.Ord k) => (v -> Maybe v) -> k -> Map k v -> Map k v
|
82 |
| -update f k m = alter (maybe Nothing f) k m |
83 |
| - |
84 |
| -glue :: forall k v. (P.Ord k) => Map k v -> Map k v -> Map k v |
85 |
| -glue left right = |
86 |
| - case findMinKey right of |
87 |
| - Tuple minKey root -> Branch { key: minKey, value: root, left: left, right: delete minKey right } |
88 |
| - |
| 201 | +update f k m = alter (maybe Nothing f) k m |
| 202 | + |
89 | 203 | toList :: forall k v. Map k v -> [Tuple k v]
|
90 | 204 | toList Leaf = []
|
91 |
| -toList (Branch b) = toList b.left P.++ [Tuple b.key b.value] P.++ toList b.right |
| 205 | +toList (Two left k v right) = toList left P.++ [Tuple k v] P.++ toList right |
| 206 | +toList (Three left k1 v1 mid k2 v2 right) = toList left P.++ [Tuple k1 v1] P.++ toList mid P.++ [Tuple k2 v2] P.++ toList right |
92 | 207 |
|
93 | 208 | fromList :: forall k v. (P.Ord k) => [Tuple k v] -> Map k v
|
94 | 209 | fromList = foldl (\m (Tuple k v) -> insert k v m) empty
|
95 | 210 |
|
96 | 211 | keys :: forall k v. Map k v -> [k]
|
97 | 212 | keys Leaf = []
|
98 |
| -keys (Branch b) = keys b.left P.++ [b.key] P.++ keys b.right |
| 213 | +keys (Two left k _ right) = keys left P.++ [k] P.++ keys right |
| 214 | +keys (Three left k1 _ mid k2 _ right) = keys left P.++ [k1] P.++ keys mid P.++ [k2] P.++ keys right |
99 | 215 |
|
100 | 216 | values :: forall k v. Map k v -> [v]
|
101 | 217 | values Leaf = []
|
102 |
| -values (Branch b) = values b.left P.++ [b.value] P.++ values b.right |
| 218 | +values (Two left _ v right) = values left P.++ [v] P.++ values right |
| 219 | +values (Three left _ v1 mid _ v2 right) = values left P.++ [v1] P.++ values mid P.++ [v2] P.++ values right |
103 | 220 |
|
104 | 221 | union :: forall k v. (P.Ord k) => Map k v -> Map k v -> Map k v
|
105 | 222 | union m1 m2 = foldl (\m (Tuple k v) -> insert k v m) m2 (toList m1)
|
106 | 223 |
|
107 | 224 | unions :: forall k v. (P.Ord k) => [Map k v] -> Map k v
|
108 | 225 | unions = foldl union empty
|
109 | 226 |
|
110 |
| -map :: forall k v1 v2. (P.Ord k) => (v1 -> v2) -> Map k v1 -> Map k v2 |
111 |
| -map _ Leaf = Leaf |
112 |
| -map f (Branch b) = Branch (b { value = f b.value, left = map f b.left, right = map f b.right }) |
| 227 | +map :: forall k a b. (a -> b) -> Map k a -> Map k b |
| 228 | +map = P.(<$>) |
0 commit comments