Skip to content
This repository was archived by the owner on Oct 4, 2020. It is now read-only.

Commit 0ce5038

Browse files
committed
deleteMin and deleteMax
1 parent e424494 commit 0ce5038

File tree

2 files changed

+68
-33
lines changed

2 files changed

+68
-33
lines changed

src/Data/Map.purs

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ module Data.Map
1616
, lookupGT
1717
, findMin
1818
, findMax
19+
, deleteMin
20+
, deleteMax
1921
, foldSubmap
2022
, submap
2123
, fromFoldable
@@ -293,6 +295,32 @@ findMin = go Nothing
293295
go _ (Two left k1 v1 _) = go (Just { key: k1, value: v1 }) left
294296
go _ (Three left k1 v1 _ _ _ _) = go (Just { key: k1, value: v1 }) left
295297

298+
-- | Delete the pair with the least key. O(logn).
299+
-- |
300+
-- | Return an empty map if the map is empty.
301+
deleteMin :: forall k v. Ord k => Map k v -> Map k v
302+
deleteMin Leaf = Leaf
303+
deleteMin n = down Nil n
304+
where
305+
down :: List (TreeContext k v) -> Map k v -> Map k v
306+
down = unsafePartial \ctx -> case _ of
307+
Two left k v right ->
308+
case left, right of
309+
Leaf, Leaf -> deleteUp ctx Leaf
310+
_ , _ -> down (Cons (TwoLeft k v right) ctx) left
311+
Three left k1 v1 mid k2 v2 right ->
312+
case left, mid, right of
313+
Leaf, Leaf, Leaf -> fromZipper ctx (Two Leaf k2 v2 Leaf)
314+
_ , _ , _ ->
315+
down (Cons (ThreeLeft k1 v1 mid k2 v2 right) ctx) left
316+
317+
-- | Delete the pair with the greatest key. O(logn).
318+
-- |
319+
-- | Return an empty map if the map is empty.
320+
deleteMax :: forall k v. Ord k => Map k v -> Map k v
321+
deleteMax Leaf = Leaf
322+
deleteMax n = removeMaxNode Nil n
323+
296324
-- | Fold over the entries of a given map where the key is between a lower and
297325
-- | an upper bound. Passing `Nothing` as either the lower or upper bound
298326
-- | argument means that the fold has no lower or upper bound, i.e. the fold
@@ -470,7 +498,7 @@ pop k = down Nil
470498
Leaf -> Nothing
471499
Two left k1 v1 right ->
472500
case right, comp k k1 of
473-
Leaf, EQ -> Just (Tuple v1 (up ctx Leaf))
501+
Leaf, EQ -> Just (Tuple v1 (deleteUp ctx Leaf))
474502
_ , EQ -> let max = maxNode left
475503
in Just (Tuple v1 (removeMaxNode (Cons (TwoLeft max.key max.value right) ctx) left))
476504
_ , LT -> down (Cons (TwoLeft k1 v1 right) ctx) left
@@ -491,30 +519,6 @@ pop k = down Nil
491519
_ , GT, LT -> down (Cons (ThreeMiddle left k1 v1 k2 v2 right) ctx) mid
492520
_ , _ , _ -> down (Cons (ThreeRight left k1 v1 mid k2 v2) ctx) right
493521

494-
up :: List (TreeContext k v) -> Map k v -> Map k v
495-
up = unsafePartial \ctxs tree ->
496-
case ctxs of
497-
Nil -> tree
498-
Cons x ctx ->
499-
case x, tree of
500-
TwoLeft k1 v1 Leaf, Leaf -> fromZipper ctx (Two Leaf k1 v1 Leaf)
501-
TwoRight Leaf k1 v1, Leaf -> fromZipper ctx (Two Leaf k1 v1 Leaf)
502-
TwoLeft k1 v1 (Two m k2 v2 r), l -> up ctx (Three l k1 v1 m k2 v2 r)
503-
TwoRight (Two l k1 v1 m) k2 v2, r -> up ctx (Three l k1 v1 m k2 v2 r)
504-
TwoLeft k1 v1 (Three b k2 v2 c k3 v3 d), a -> fromZipper ctx (Two (Two a k1 v1 b) k2 v2 (Two c k3 v3 d))
505-
TwoRight (Three a k1 v1 b k2 v2 c) k3 v3, d -> fromZipper ctx (Two (Two a k1 v1 b) k2 v2 (Two c k3 v3 d))
506-
ThreeLeft k1 v1 Leaf k2 v2 Leaf, Leaf -> fromZipper ctx (Three Leaf k1 v1 Leaf k2 v2 Leaf)
507-
ThreeMiddle Leaf k1 v1 k2 v2 Leaf, Leaf -> fromZipper ctx (Three Leaf k1 v1 Leaf k2 v2 Leaf)
508-
ThreeRight Leaf k1 v1 Leaf k2 v2, Leaf -> fromZipper ctx (Three Leaf k1 v1 Leaf k2 v2 Leaf)
509-
ThreeLeft k1 v1 (Two b k2 v2 c) k3 v3 d, a -> fromZipper ctx (Two (Three a k1 v1 b k2 v2 c) k3 v3 d)
510-
ThreeMiddle (Two a k1 v1 b) k2 v2 k3 v3 d, c -> fromZipper ctx (Two (Three a k1 v1 b k2 v2 c) k3 v3 d)
511-
ThreeMiddle a k1 v1 k2 v2 (Two c k3 v3 d), b -> fromZipper ctx (Two a k1 v1 (Three b k2 v2 c k3 v3 d))
512-
ThreeRight a k1 v1 (Two b k2 v2 c) k3 v3, d -> fromZipper ctx (Two a k1 v1 (Three b k2 v2 c k3 v3 d))
513-
ThreeLeft k1 v1 (Three b k2 v2 c k3 v3 d) k4 v4 e, a -> fromZipper ctx (Three (Two a k1 v1 b) k2 v2 (Two c k3 v3 d) k4 v4 e)
514-
ThreeMiddle (Three a k1 v1 b k2 v2 c) k3 v3 k4 v4 e, d -> fromZipper ctx (Three (Two a k1 v1 b) k2 v2 (Two c k3 v3 d) k4 v4 e)
515-
ThreeMiddle a k1 v1 k2 v2 (Three c k3 v3 d k4 v4 e), b -> fromZipper ctx (Three a k1 v1 (Two b k2 v2 c) k3 v3 (Two d k4 v4 e))
516-
ThreeRight a k1 v1 (Three b k2 v2 c k3 v3 d) k4 v4, e -> fromZipper ctx (Three a k1 v1 (Two b k2 v2 c) k3 v3 (Two d k4 v4 e))
517-
518522
maxNode :: Map k v -> { key :: k, value :: v }
519523
maxNode = unsafePartial \m -> case m of
520524
Two _ k' v Leaf -> { key: k', value: v }
@@ -523,13 +527,36 @@ pop k = down Nil
523527
Three _ _ _ _ _ _ right -> maxNode right
524528

525529

526-
removeMaxNode :: List (TreeContext k v) -> Map k v -> Map k v
527-
removeMaxNode = unsafePartial \ctx m ->
528-
case m of
529-
Two Leaf _ _ Leaf -> up ctx Leaf
530-
Two left k' v right -> removeMaxNode (Cons (TwoRight left k' v) ctx) right
531-
Three Leaf k1 v1 Leaf _ _ Leaf -> up (Cons (TwoRight Leaf k1 v1) ctx) Leaf
532-
Three left k1 v1 mid k2 v2 right -> removeMaxNode (Cons (ThreeRight left k1 v1 mid k2 v2) ctx) right
530+
removeMaxNode :: forall k v. Ord k => List (TreeContext k v) -> Map k v -> Map k v
531+
removeMaxNode = unsafePartial \ctx -> case _ of
532+
Two Leaf _ _ Leaf -> deleteUp ctx Leaf
533+
Two left k' v right -> removeMaxNode (Cons (TwoRight left k' v) ctx) right
534+
Three Leaf k1 v1 Leaf _ _ Leaf -> deleteUp (Cons (TwoRight Leaf k1 v1) ctx) Leaf
535+
Three left k1 v1 mid k2 v2 right -> removeMaxNode (Cons (ThreeRight left k1 v1 mid k2 v2) ctx) right
536+
537+
deleteUp :: forall k v. Ord k => List (TreeContext k v) -> Map k v -> Map k v
538+
deleteUp = unsafePartial \ctxs tree ->
539+
case ctxs of
540+
Nil -> tree
541+
Cons x ctx ->
542+
case x, tree of
543+
TwoLeft k1 v1 Leaf, Leaf -> fromZipper ctx (Two Leaf k1 v1 Leaf)
544+
TwoRight Leaf k1 v1, Leaf -> fromZipper ctx (Two Leaf k1 v1 Leaf)
545+
TwoLeft k1 v1 (Two m k2 v2 r), l -> deleteUp ctx (Three l k1 v1 m k2 v2 r)
546+
TwoRight (Two l k1 v1 m) k2 v2, r -> deleteUp ctx (Three l k1 v1 m k2 v2 r)
547+
TwoLeft k1 v1 (Three b k2 v2 c k3 v3 d), a -> fromZipper ctx (Two (Two a k1 v1 b) k2 v2 (Two c k3 v3 d))
548+
TwoRight (Three a k1 v1 b k2 v2 c) k3 v3, d -> fromZipper ctx (Two (Two a k1 v1 b) k2 v2 (Two c k3 v3 d))
549+
ThreeLeft k1 v1 Leaf k2 v2 Leaf, Leaf -> fromZipper ctx (Three Leaf k1 v1 Leaf k2 v2 Leaf)
550+
ThreeMiddle Leaf k1 v1 k2 v2 Leaf, Leaf -> fromZipper ctx (Three Leaf k1 v1 Leaf k2 v2 Leaf)
551+
ThreeRight Leaf k1 v1 Leaf k2 v2, Leaf -> fromZipper ctx (Three Leaf k1 v1 Leaf k2 v2 Leaf)
552+
ThreeLeft k1 v1 (Two b k2 v2 c) k3 v3 d, a -> fromZipper ctx (Two (Three a k1 v1 b k2 v2 c) k3 v3 d)
553+
ThreeMiddle (Two a k1 v1 b) k2 v2 k3 v3 d, c -> fromZipper ctx (Two (Three a k1 v1 b k2 v2 c) k3 v3 d)
554+
ThreeMiddle a k1 v1 k2 v2 (Two c k3 v3 d), b -> fromZipper ctx (Two a k1 v1 (Three b k2 v2 c k3 v3 d))
555+
ThreeRight a k1 v1 (Two b k2 v2 c) k3 v3, d -> fromZipper ctx (Two a k1 v1 (Three b k2 v2 c k3 v3 d))
556+
ThreeLeft k1 v1 (Three b k2 v2 c k3 v3 d) k4 v4 e, a -> fromZipper ctx (Three (Two a k1 v1 b) k2 v2 (Two c k3 v3 d) k4 v4 e)
557+
ThreeMiddle (Three a k1 v1 b k2 v2 c) k3 v3 k4 v4 e, d -> fromZipper ctx (Three (Two a k1 v1 b) k2 v2 (Two c k3 v3 d) k4 v4 e)
558+
ThreeMiddle a k1 v1 k2 v2 (Three c k3 v3 d k4 v4 e), b -> fromZipper ctx (Three a k1 v1 (Two b k2 v2 c) k3 v3 (Two d k4 v4 e))
559+
ThreeRight a k1 v1 (Three b k2 v2 c k3 v3 d) k4 v4, e -> fromZipper ctx (Three a k1 v1 (Two b k2 v2 c) k3 v3 (Two d k4 v4 e))
533560

534561

535562
-- | Insert the value, delete a value, or update a value for a key in a map

test/Test/Data/Map.purs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Control.Monad.Eff.Random (RANDOM)
99
import Data.Array as A
1010
import Data.Foldable (foldl, for_, all)
1111
import Data.Function (on)
12-
import Data.List (List(Cons), groupBy, length, nubBy, singleton, sort, sortBy)
12+
import Data.List (List(Cons), groupBy, length, nubBy, singleton, sort, sortBy, tail, init)
1313
import Data.List.NonEmpty as NEL
1414
import Data.Map as M
1515
import Data.Map.Gen (genMap)
@@ -269,6 +269,14 @@ mapTests = do
269269
Nothing -> M.isEmpty m
270270
Just { key: k, value: v } -> M.lookup k m == Just v && all (_ <= k) (M.keys m)
271271

272+
log "deleteMin result is correct"
273+
quickCheck $ \(TestMap m :: TestMap String Int) ->
274+
M.deleteMin m == maybe m M.fromFoldable (tail $ M.toAscUnfoldable m)
275+
276+
log "deleteMax result is correct"
277+
quickCheck $ \(TestMap m :: TestMap String Int) ->
278+
M.deleteMax m == maybe m M.fromFoldable (init $ M.toAscUnfoldable m)
279+
272280
log "mapWithKey is correct"
273281
quickCheck $ \(TestMap m :: TestMap String Int) -> let
274282
f k v = k <> show v

0 commit comments

Comments
 (0)