@@ -802,85 +802,100 @@ maxView x = Just (deleteFindMax x)
802
802
size of one of them. (a rotation).
803
803
804
804
[delta] is the maximal relative difference between the sizes of
805
- two trees, it corresponds with the [w] in Adams' paper,
806
- or equivalently, [1/delta] corresponds with the $\alpha$
807
- in Nievergelt's paper. Adams shows that [delta] should
808
- be larger than 3.745 in order to garantee that the
809
- rotations can always restore balance.
810
-
805
+ two trees, it corresponds with the [w] in Adams' paper.
811
806
[ratio] is the ratio between an outer and inner sibling of the
812
807
heavier subtree in an unbalanced setting. It determines
813
808
whether a double or single rotation should be performed
814
809
to restore balance. It is correspondes with the inverse
815
810
of $\alpha$ in Adam's article.
816
811
817
- Note that:
812
+ Note that according to the Adam's paper :
818
813
- [delta] should be larger than 4.646 with a [ratio] of 2.
819
814
- [delta] should be larger than 3.745 with a [ratio] of 1.534.
820
-
815
+
816
+ But the Adam's paper is errorneous:
817
+ - it can be proved that for delta=2 and delta>=5 there does
818
+ not exist any ratio that would work
819
+ - delta=4.5 and ratio=2 does not work
820
+
821
+ That leaves two reasonable variants, delta=3 and delta=4,
822
+ both with ratio=2.
823
+
821
824
- A lower [delta] leads to a more 'perfectly' balanced tree.
822
825
- A higher [delta] performs less rebalancing.
823
826
824
- - Balancing is automatic for random data and a balancing
825
- scheme is only necessary to avoid pathological worst cases.
826
- Almost any choice will do in practice
827
-
828
- - Allthough it seems that a rather large [delta] may perform better
829
- than smaller one, measurements have shown that the smallest [delta]
830
- of 4 is actually the fastest on a wide range of operations. It
831
- especially improves performance on worst-case scenarios like
832
- a sequence of ordered insertions.
833
-
834
- Note: in contrast to Adams' paper, we use a ratio of (at least) 2
835
- to decide whether a single or double rotation is needed. Allthough
836
- he actually proves that this ratio is needed to maintain the
837
- invariants, his implementation uses a (invalid) ratio of 1.
838
- He is aware of the problem though since he has put a comment in his
839
- original source code that he doesn't care about generating a
840
- slightly inbalanced tree since it doesn't seem to matter in practice.
841
- However (since we use quickcheck :-) we will stick to strictly balanced
842
- trees.
827
+ In the benchmarks, delta=3 is faster on insert operations,
828
+ but delta=4 has better overall performance, so we use delta=4.
829
+
830
+ Note: in contrast to Adam's paper, we perform the rebalance
831
+ even in the case when (size left == delta * size right), instead
832
+ when (size left > delta * size) as in the paper. Both are correct,
833
+ but the former is slightly faster overall.
834
+
843
835
--------------------------------------------------------------------}
844
836
delta ,ratio :: Int
845
837
delta = 4
846
838
ratio = 2
847
839
840
+ -- The balance function is equivalent to the following:
841
+ --
842
+ -- balance :: a -> Set a -> Set a -> Set a
843
+ -- balance x l r
844
+ -- | sizeL + sizeR <= 1 = Bin sizeX x l r
845
+ -- | sizeR >= delta*sizeL = rotateL x l r
846
+ -- | sizeL >= delta*sizeR = rotateR x l r
847
+ -- | otherwise = Bin sizeX x l r
848
+ -- where
849
+ -- sizeL = size l
850
+ -- sizeR = size r
851
+ -- sizeX = sizeL + sizeR + 1
852
+ --
853
+ -- rotateL :: a -> Set a -> Set a -> Set a
854
+ -- rotateL x l r@(Bin _ _ ly ry) | size ly < ratio*size ry = singleL x l r
855
+ -- | otherwise = doubleL x l r
856
+ -- rotateR :: a -> Set a -> Set a -> Set a
857
+ -- rotateR x l@(Bin _ _ ly ry) r | size ry < ratio*size ly = singleR x l r
858
+ -- | otherwise = doubleR x l r
859
+ --
860
+ -- singleL, singleR :: a -> Set a -> Set a -> Set a
861
+ -- singleL x1 t1 (Bin _ x2 t2 t3) = bin x2 (bin x1 t1 t2) t3
862
+ -- singleR x1 (Bin _ x2 t1 t2) t3 = bin x2 t1 (bin x1 t2 t3)
863
+ --
864
+ -- doubleL, doubleR :: a -> Set a -> Set a -> Set a
865
+ -- doubleL x1 t1 (Bin _ x2 (Bin _ x3 t2 t3) t4) = bin x3 (bin x1 t1 t2) (bin x2 t3 t4)
866
+ -- doubleR x1 (Bin _ x2 t1 (Bin _ x3 t2 t3)) t4 = bin x3 (bin x2 t1 t2) (bin x1 t3 t4)
867
+ --
868
+ -- It is only written in such a way that every node is pattern-matched only once.
869
+
848
870
balance :: a -> Set a -> Set a -> Set a
849
- balance x l r
850
- | sizeL + sizeR <= 1 = Bin sizeX x l r
851
- | sizeR >= delta* sizeL = rotateL x l r
852
- | sizeL >= delta* sizeR = rotateR x l r
853
- | otherwise = Bin sizeX x l r
854
- where
855
- sizeL = size l
856
- sizeR = size r
857
- sizeX = sizeL + sizeR + 1
858
-
859
- -- rotate
860
- rotateL :: a -> Set a -> Set a -> Set a
861
- rotateL x l r@ (Bin _ _ ly ry)
862
- | size ly < ratio* size ry = singleL x l r
863
- | otherwise = doubleL x l r
864
- rotateL _ _ Tip = error " rotateL Tip"
865
-
866
- rotateR :: a -> Set a -> Set a -> Set a
867
- rotateR x l@ (Bin _ _ ly ry) r
868
- | size ry < ratio* size ly = singleR x l r
869
- | otherwise = doubleR x l r
870
- rotateR _ Tip _ = error " rotateL Tip"
871
-
872
- -- basic rotations
873
- singleL , singleR :: a -> Set a -> Set a -> Set a
874
- singleL x1 t1 (Bin _ x2 t2 t3) = bin x2 (bin x1 t1 t2) t3
875
- singleL _ _ Tip = error " singleL"
876
- singleR x1 (Bin _ x2 t1 t2) t3 = bin x2 t1 (bin x1 t2 t3)
877
- singleR _ Tip _ = error " singleR"
878
-
879
- doubleL , doubleR :: a -> Set a -> Set a -> Set a
880
- doubleL x1 t1 (Bin _ x2 (Bin _ x3 t2 t3) t4) = bin x3 (bin x1 t1 t2) (bin x2 t3 t4)
881
- doubleL _ _ _ = error " doubleL"
882
- doubleR x1 (Bin _ x2 t1 (Bin _ x3 t2 t3)) t4 = bin x3 (bin x2 t1 t2) (bin x1 t3 t4)
883
- doubleR _ _ _ = error " doubleR"
871
+ balance x l r = case l of
872
+ Tip -> case r of
873
+ Tip -> Bin 1 x Tip Tip
874
+ r@ (Bin rs rx Tip Tip ) -> Bin 2 x Tip r
875
+ r@ (Bin rs rx Tip rr@ (Bin _ _ _ _)) -> Bin 3 rx (Bin 1 x Tip Tip ) rr
876
+ r@ (Bin rs rx rl@ (Bin _ rlx _ _) Tip ) -> Bin 3 rlx (Bin 1 x Tip Tip ) (Bin 1 rx Tip Tip )
877
+ r@ (Bin rs rx rl@ (Bin rls rlx rll rlr) rr@ (Bin rrs rrx rrl rrr))
878
+ | rls < ratio* rrs -> Bin (1 + rs) rx (Bin (1 + rls) x Tip rl) rr
879
+ | otherwise -> Bin (1 + rs) rlx (Bin (1 + size rll) x Tip rll) (Bin (1 + rrs+ size rlr) rx rlr rr)
880
+
881
+ l@ (Bin ls lx ll lr) -> case r of
882
+ Tip -> case (ll, lr) of
883
+ (Tip , Tip ) -> Bin 2 x l Tip
884
+ (Tip , lr@ (Bin _ lrx _ _)) -> Bin 3 lrx (Bin 1 lx Tip Tip ) (Bin 1 x Tip Tip )
885
+ (ll@ (Bin _ _ _ _), Tip ) -> Bin 3 lx ll (Bin 1 x Tip Tip )
886
+ (ll@ (Bin lls llx lll llr), lr@ (Bin lrs lrx lrl lrr))
887
+ | lrs < ratio* lls -> Bin (1 + ls) lx ll (Bin (1 + lrs) x lr Tip )
888
+ | otherwise -> Bin (1 + ls) lrx (Bin (1 + lls+ size lrl) lx ll lrl) (Bin (1 + size lrr) x lrr Tip )
889
+ r@ (Bin rs rx rl rr)
890
+ | rs >= delta* ls -> case (rl, rr) of
891
+ (Bin rls rlx rll rlr, Bin rrs rrx rrl rrr)
892
+ | rls < ratio* rrs -> Bin (1 + ls+ rs) rx (Bin (1 + ls+ rls) x l rl) rr
893
+ | otherwise -> Bin (1 + ls+ rs) rlx (Bin (1 + ls+ size rll) x l rll) (Bin (1 + rrs+ size rlr) rx rlr rr)
894
+ | ls >= delta* rs -> case (ll, lr) of
895
+ (Bin lls llx lll llr, Bin lrs lrx lrl lrr)
896
+ | lrs < ratio* lls -> Bin (1 + ls+ rs) lx ll (Bin (1 + rs+ lrs) x lr r)
897
+ | otherwise -> Bin (1 + ls+ rs) lrx (Bin (1 + lls+ size lrl) lx ll lrl) (Bin (1 + rs+ size lrr) x lrr r)
898
+ | otherwise -> Bin (1 + ls+ rs) x l r
884
899
885
900
886
901
{- -------------------------------------------------------------------
0 commit comments