{-# OPTIONS_GHC -fglasgow-exts #-}------------------------------------------------------------------------------- |-- Module : Data.Tree.AVL.List-- Copyright : (c) Adrian Hey 2004,2005-- License : BSD3---- Maintainer : http://homepages.nildram.co.uk/~ahey/em.png-- Stability : stable-- Portability : portable-----------------------------------------------------------------------------moduleData.Tree.AVL.List(-- * List related utilities for AVL trees-- ** Converting AVL trees to Lists (fixed element order).-- | These functions are lazy and allow normal lazy list processing-- style to be used (without necessarily converting the entire tree-- to a list in one gulp).asListL,toListL,asListR,toListR,-- ** Converting Lists to AVL trees (fixed element order)asTreeLenL,asTreeL,asTreeLenR,asTreeR,-- ** Converting unsorted Lists to sorted AVL treesgenAsTree,-- ** \"Pushing\" unsorted Lists in sorted AVL treesgenPushList,-- * Some analogues of common List functionsreverseAVL,mapAVL,mapAVL',mapAccumLAVL,mapAccumRAVL,mapAccumLAVL',mapAccumRAVL',#ifdef __GLASGOW_HASKELL__mapAccumLAVL'',mapAccumRAVL'',#endif#if __GLASGOW_HASKELL__ > 604traverseAVL,#endifreplicateAVL,filterAVL,mapMaybeAVL,filterViaList,mapMaybeViaList,partitionAVL,-- ** Folds-- | Note that unlike folds over lists ('foldr' and 'foldl'), there is no-- significant difference between left and right folds in AVL trees, other-- than which side of the tree each starts with.-- Therefore this library provides strict and lazy versions of both.foldrAVL,foldrAVL',foldr1AVL,foldr1AVL',foldr2AVL,foldr2AVL',foldlAVL,foldlAVL',foldl1AVL,foldl1AVL',foldl2AVL,foldl2AVL',foldrAVL_UINT,-- * \"Flattening\" AVL trees-- | These functions can be improve search times by reducing a tree of given size to-- the minimum possible height.flatten,flatReverse,flatMap,flatMap',)whereimportPrelude-- so haddock finds the symbols there#if __GLASGOW_HASKELL__ > 604importControl.Applicativehiding(empty)#endifimportData.COrderingimportData.Tree.AVL.Types(AVL(..),empty)importData.Tree.AVL.Size(size)importData.Tree.AVL.Push(genPush)importData.Tree.AVL.Internals.HJoin(spliceH,joinH)importData.Bits(shiftR,(.&.))importData.List(foldl')#ifdef __GLASGOW_HASKELL__importGHC.Base#include "ghcdefs.h"#else#include "h98defs.h"#endif-- | List AVL tree contents in left to right order.-- The resulting list in ascending order if the tree is sorted.---- Complexity: O(n)asListL::AVLe->[e]asListLavl=toListLavl[]-- | Join the AVL tree contents to an existing list in left to right order.-- This is a ++ free function which behaves as if defined thusly..---- > avl `toListL` as = (asListL avl) ++ as---- Complexity: O(n)toListL::AVLe->[e]->[e]toListLEes=estoListL(Nler)es=toListL'lerestoListL(Zler)es=toListL'lerestoListL(Pler)es=toListL'lerestoListL'::AVLe->e->AVLe->[e]->[e]toListL'leres=toListLl(e:(toListLres))-- | List AVL tree contents in right to left order.-- The resulting list in descending order if the tree is sorted.---- Complexity: O(n)asListR::AVLe->[e]asListRavl=toListRavl[]-- | Join the AVL tree contents to an existing list in right to left order.-- This is a ++ free function which behaves as if defined thusly..---- > avl `toListR` as = (asListR avl) ++ as---- Complexity: O(n)toListR::AVLe->[e]->[e]toListREes=estoListR(Nler)es=toListR'lerestoListR(Zler)es=toListR'lerestoListR(Pler)es=toListR'lerestoListR'::AVLe->e->AVLe->[e]->[e]toListR'leres=toListRr(e:(toListRles))-- | The AVL equivalent of 'foldr' on lists. This is a the lazy version (as lazy as the folding function-- anyway). Using this version with a function that is strict in it's second argument will result in O(n)-- stack use. See 'foldrAVL'' for a strict version.---- It behaves as if defined..---- > foldrAVL f a avl = foldr f a (asListL avl)---- For example, the 'asListL' function could be defined..---- > asListL = foldrAVL (:) []---- Complexity: O(n)foldrAVL::(e->a->a)->a->AVLe->afoldrAVLf=foldUwherefoldUaE=afoldUa(Nler)=foldValerfoldUa(Zler)=foldValerfoldUa(Pler)=foldValerfoldValer=foldU(fe(foldUar))l-- | The strict version of 'foldrAVL', which is useful for functions which are strict in their second-- argument. The advantage of this version is that it reduces the stack use from the O(n) that the lazy-- version gives (when used with strict functions) to O(log n).---- Complexity: O(n)foldrAVL'::(e->a->a)->a->AVLe->afoldrAVL'f=foldUwherefoldUaE=afoldUa(Nler)=foldValerfoldUa(Zler)=foldValerfoldUa(Pler)=foldValerfoldValer=leta'=foldUara''=fea'ina'`seq`a''`seq`foldUa''l-- | The AVL equivalent of 'foldr1' on lists. This is a the lazy version (as lazy as the folding function-- anyway). Using this version with a function that is strict in it's second argument will result in O(n)-- stack use. See 'foldr1AVL'' for a strict version.---- > foldr1AVL f avl = foldr1 f (asListL avl)---- This function raises an error if the tree is empty.---- Complexity: O(n)foldr1AVL::(e->e->e)->AVLe->efoldr1AVLf=foldUwherefoldUE=error"foldr1AVL: Empty Tree"foldU(Nler)=foldVler-- r can't be EfoldU(Zler)=foldWler-- r might be EfoldU(Pler)=foldWler-- r might be E-- Use this when r can't be EfoldVler=foldrAVLf(fe(foldUr))l-- Use this when r might be EfoldWleE=foldrAVLfelfoldWle(Nrlrerr)=foldrAVLf(fe(foldVrlrerr))l-- rr can't be EfoldWle(Zrlrerr)=foldXlerlrerr-- rr might be EfoldWle(Prlrerr)=foldXlerlrerr-- rr might be E-- Common code for foldW (Z and P cases)foldXlerlrerr=foldrAVLf(fe(foldWrlrerr))l-- | The strict version of 'foldr1AVL', which is useful for functions which are strict in their second-- argument. The advantage of this version is that it reduces the stack use from the O(n) that the lazy-- version gives (when used with strict functions) to O(log n).---- Complexity: O(n)foldr1AVL'::(e->e->e)->AVLe->efoldr1AVL'f=foldUwherefoldUE=error"foldr1AVL': Empty Tree"foldU(Nler)=foldVler-- r can't be EfoldU(Zler)=foldWler-- r might be EfoldU(Pler)=foldWler-- r might be E-- Use this when r can't be EfoldVler=leta=foldUra'=feaina`seq`a'`seq`foldrAVL'fa'l-- Use this when r might be EfoldWleE=foldrAVL'felfoldWle(Nrlrerr)=leta=foldVrlrerr-- rr can't be Ea'=feaina`seq`a'`seq`foldrAVL'fa'lfoldWle(Zrlrerr)=foldXlerlrerr-- rr might be EfoldWle(Prlrerr)=foldXlerlrerr-- rr might be E-- Common code for foldW (Z and P cases)foldXlerlrerr=leta=foldWrlrerra'=feaina`seq`a'`seq`foldrAVL'fa'l-- | This fold is a hybrid between 'foldrAVL' and 'foldr1AVL'. As with 'foldr1AVL', it requires-- a non-empty tree, but instead of treating the rightmost element as an initial value, it applies-- a function to it (second function argument) and uses the result instead. This allows-- a more flexible type for the main folding function (same type as that used by 'foldrAVL').-- As with 'foldrAVL' and 'foldr1AVL', this function is lazy, so it's best not to use it with functions-- that are strict in their second argument. See 'foldr2AVL'' for a strict version.---- Complexity: O(n)foldr2AVL::(e->a->a)->(e->a)->AVLe->afoldr2AVLfg=foldUwherefoldUE=error"foldr2AVL: Empty Tree"foldU(Nler)=foldVler-- r can't be EfoldU(Zler)=foldWler-- r might be EfoldU(Pler)=foldWler-- r might be E-- Use this when r can't be EfoldVler=foldrAVLf(fe(foldUr))l-- Use this when r might be EfoldWleE=foldrAVLf(ge)lfoldWle(Nrlrerr)=foldrAVLf(fe(foldVrlrerr))l-- rr can't be EfoldWle(Zrlrerr)=foldXlerlrerr-- rr might be EfoldWle(Prlrerr)=foldXlerlrerr-- rr might be E-- Common code for foldW (Z and P cases)foldXlerlrerr=foldrAVLf(fe(foldWrlrerr))l-- | The strict version of 'foldr2AVL', which is useful for functions which are strict in their second-- argument. The advantage of this version is that it reduces the stack use from the O(n) that the lazy-- version gives (when used with strict functions) to O(log n).---- Complexity: O(n)foldr2AVL'::(e->a->a)->(e->a)->AVLe->afoldr2AVL'fg=foldUwherefoldUE=error"foldr2AVL': Empty Tree"foldU(Nler)=foldVler-- r can't be EfoldU(Zler)=foldWler-- r might be EfoldU(Pler)=foldWler-- r might be E-- Use this when r can't be EfoldVler=leta=foldUra'=feaina`seq`a'`seq`foldrAVL'fa'l-- Use this when r might be EfoldWleE=leta=geina`seq`foldrAVL'falfoldWle(Nrlrerr)=leta=foldVrlrerr-- rr can't be Ea'=feaina`seq`a'`seq`foldrAVL'fa'lfoldWle(Zrlrerr)=foldXlerlrerr-- rr might be EfoldWle(Prlrerr)=foldXlerlrerr-- rr might be E-- Common code for foldW (Z and P cases)foldXlerlrerr=leta=foldWrlrerra'=feaina`seq`a'`seq`foldrAVL'fa'l-- | The AVL equivalent of 'foldl' on lists. This is a the lazy version (as lazy as the folding function-- anyway). Using this version with a function that is strict in it's first argument will result in O(n)-- stack use. See 'foldlAVL'' for a strict version.---- > foldlAVL f a avl = foldl f a (asListL avl)---- For example, the 'asListR' function could be defined..---- > asListR = foldlAVL (flip (:)) []---- Complexity: O(n)foldlAVL::(a->e->a)->a->AVLe->afoldlAVLf=foldUwherefoldUaE=afoldUa(Nler)=foldValerfoldUa(Zler)=foldValerfoldUa(Pler)=foldValerfoldValer=foldU(f(foldUal)e)r-- | The strict version of 'foldlAVL', which is useful for functions which are strict in their first-- argument. The advantage of this version is that it reduces the stack use from the O(n) that the lazy-- version gives (when used with strict functions) to O(log n).---- Complexity: O(n)foldlAVL'::(a->e->a)->a->AVLe->afoldlAVL'f=foldUwherefoldUaE=afoldUa(Nler)=foldValerfoldUa(Zler)=foldValerfoldUa(Pler)=foldValerfoldValer=leta'=foldUala''=fa'eina'`seq`a''`seq`foldUa''r-- | The AVL equivalent of 'foldl1' on lists. This is a the lazy version (as lazy as the folding function-- anyway). Using this version with a function that is strict in it's first argument will result in O(n)-- stack use. See 'foldl1AVL'' for a strict version.---- > foldl1AVL f avl = foldl1 f (asListL avl)---- This function raises an error if the tree is empty.---- Complexity: O(n)foldl1AVL::(e->e->e)->AVLe->efoldl1AVLf=foldUwherefoldUE=error"foldl1AVL: Empty Tree"foldU(Nler)=foldWler-- l might be EfoldU(Zler)=foldWler-- l might be EfoldU(Pler)=foldVler-- l can't be E-- Use this when l can't be EfoldVler=foldlAVLf(f(foldUl)e)r-- Use this when l might be EfoldWEer=foldlAVLferfoldW(Nlllelr)er=foldXlllelrer-- ll might be EfoldW(Zlllelr)er=foldXlllelrer-- ll might be EfoldW(Plllelr)er=foldlAVLf(f(foldVlllelr)e)r-- ll can't be E-- Common code for foldW (Z and P cases)foldXlllelrer=foldlAVLf(f(foldWlllelr)e)r-- | The strict version of 'foldl1AVL', which is useful for functions which are strict in their first-- argument. The advantage of this version is that it reduces the stack use from the O(n) that the lazy-- version gives (when used with strict functions) to O(log n).---- Complexity: O(n)foldl1AVL'::(e->e->e)->AVLe->efoldl1AVL'f=foldUwherefoldUE=error"foldl1AVL': Empty Tree"foldU(Nler)=foldWler-- l might be EfoldU(Zler)=foldWler-- l might be EfoldU(Pler)=foldVler-- l can't be E-- Use this when l can't be EfoldVler=leta=foldUla'=faeina`seq`a'`seq`foldlAVL'fa'r-- Use this when l might be EfoldWEer=foldlAVL'ferfoldW(Nlllelr)er=foldXlllelrer-- ll might be EfoldW(Zlllelr)er=foldXlllelrer-- ll might be EfoldW(Plllelr)er=leta=foldVlllelr-- ll can't be Ea'=faeina`seq`a'`seq`foldlAVL'fa'r-- Common code for foldW (Z and P cases)foldXlllelrer=leta=foldWlllelra'=faeina`seq`a'`seq`foldlAVL'fa'r-- | This fold is a hybrid between 'foldlAVL' and 'foldl1AVL'. As with 'foldl1AVL', it requires-- a non-empty tree, but instead of treating the leftmost element as an initial value, it applies-- a function to it (second function argument) and uses the result instead. This allows-- a more flexible type for the main folding function (same type as that used by 'foldlAVL').-- As with 'foldlAVL' and 'foldl1AVL', this function is lazy, so it's best not to use it with functions-- that are strict in their first argument. See 'foldl2AVL'' for a strict version.---- Complexity: O(n)foldl2AVL::(a->e->a)->(e->a)->AVLe->afoldl2AVLfg=foldUwherefoldUE=error"foldl2AVL: Empty Tree"foldU(Nler)=foldWler-- l might be EfoldU(Zler)=foldWler-- l might be EfoldU(Pler)=foldVler-- l can't be E-- Use this when l can't be EfoldVler=foldlAVLf(f(foldUl)e)r-- Use this when l might be EfoldWEer=foldlAVLf(ge)rfoldW(Nlllelr)er=foldXlllelrer-- ll might be EfoldW(Zlllelr)er=foldXlllelrer-- ll might be EfoldW(Plllelr)er=foldlAVLf(f(foldVlllelr)e)r-- ll can't be E-- Common code for foldW (Z and P cases)foldXlllelrer=foldlAVLf(f(foldWlllelr)e)r-- | The strict version of 'foldl2AVL', which is useful for functions which are strict in their first-- argument. The advantage of this version is that it reduces the stack use from the O(n) that the lazy-- version gives (when used with strict functions) to O(log n).---- Complexity: O(n)foldl2AVL'::(a->e->a)->(e->a)->AVLe->afoldl2AVL'fg=foldUwherefoldUE=error"foldl2AVL': Empty Tree"foldU(Nler)=foldWler-- l might be EfoldU(Zler)=foldWler-- l might be EfoldU(Pler)=foldVler-- l can't be E-- Use this when l can't be EfoldVler=leta=foldUla'=faeina`seq`a'`seq`foldlAVL'fa'r-- Use this when l might be EfoldWEer=leta=geina`seq`foldlAVL'farfoldW(Nlllelr)er=foldXlllelrer-- ll might be EfoldW(Zlllelr)er=foldXlllelrer-- ll might be EfoldW(Plllelr)er=leta=foldVlllelr-- ll can't be Ea'=faeina`seq`a'`seq`foldlAVL'fa'r-- Common code for foldW (Z and P cases)foldXlllelrer=leta=foldWlllelra'=faeina`seq`a'`seq`foldlAVL'fa'r-- | This is a specialised version of 'foldrAVL'' for use with an-- /unboxed/ Int accumulator (with GHC). Defaults to boxed Int-- for other Haskells.---- Complexity: O(n)foldrAVL_UINT::(e->UINT->UINT)->UINT->AVLe->UINT#ifdef __GLASGOW_HASKELL__foldrAVL_UINTf=foldUwherefoldUaE=afoldUa(Nler)=foldValerfoldUa(Zler)=foldValerfoldUa(Pler)=foldValerfoldValer=foldU(fe(foldUar))l#elsefoldrAVL_UINT=foldrAVL'-- Strict version!{-# INLINE foldrAVL_UINT #-}#endif-- | The AVL equivalent of 'Data.List.mapAccumL' on lists.-- It behaves like a combination of 'mapAVL' and 'foldlAVL'.-- It applies a function to each element of a tree, passing an accumulating parameter from-- left to right, and returning a final value of this accumulator together with the new tree.---- Using this version with a function that is strict in it's first argument will result in-- O(n) stack use. See 'mapAccumLAVL'' for a strict version.---- Complexity: O(n)mapAccumLAVL::(z->a->(z,b))->z->AVLa->(z,AVLb)mapAccumLAVLfzta=casemapALztaofUBT2(zt,tb)->(zt,tb)wheremapALz_E=UBT2(z_,E)mapALz_(Nlaara)=mapAL'z_NlaaramapALz_(Zlaara)=mapAL'z_ZlaaramapALz_(Plaara)=mapAL'z_Plaara{-# INLINE mapAL' #-}mapAL'z'claara=casemapALz'laofUBT2(zl,lb)->let(za,b)=fzlaincasemapALzaraofUBT2(zr,rb)->UBT2(zr,clbbrb)-- | This is a strict version of 'mapAccumLAVL', which is useful for functions which-- are strict in their first argument. The advantage of this version is that it reduces-- the stack use from the O(n) that the lazy version gives (when used with strict functions)-- to O(log n).---- Complexity: O(n)mapAccumLAVL'::(z->a->(z,b))->z->AVLa->(z,AVLb)mapAccumLAVL'fzta=casemapALztaofUBT2(zt,tb)->(zt,tb)wheremapALz_E=UBT2(z_,E)mapALz_(Nlaara)=mapAL'z_NlaaramapALz_(Zlaara)=mapAL'z_ZlaaramapALz_(Plaara)=mapAL'z_Plaara{-# INLINE mapAL' #-}mapAL'z'claara=casemapALz'laofUBT2(zl,lb)->casefzlaof(za,b)->casemapALzaraofUBT2(zr,rb)->UBT2(zr,clbbrb)-- | The AVL equivalent of 'Data.List.mapAccumR' on lists.-- It behaves like a combination of 'mapAVL' and 'foldrAVL'.-- It applies a function to each element of a tree, passing an accumulating parameter from-- right to left, and returning a final value of this accumulator together with the new tree.---- Using this version with a function that is strict in it's first argument will result in-- O(n) stack use. See 'mapAccumRAVL'' for a strict version.---- Complexity: O(n)mapAccumRAVL::(z->a->(z,b))->z->AVLa->(z,AVLb)mapAccumRAVLfzta=casemapARztaofUBT2(zt,tb)->(zt,tb)wheremapARz_E=UBT2(z_,E)mapARz_(Nlaara)=mapAR'z_NlaaramapARz_(Zlaara)=mapAR'z_ZlaaramapARz_(Plaara)=mapAR'z_Plaara{-# INLINE mapAR' #-}mapAR'z'claara=casemapARz'raofUBT2(zr,rb)->let(za,b)=fzraincasemapARzalaofUBT2(zl,lb)->UBT2(zl,clbbrb)-- | This is a strict version of 'mapAccumRAVL', which is useful for functions which-- are strict in their first argument. The advantage of this version is that it reduces-- the stack use from the O(n) that the lazy version gives (when used with strict functions)-- to O(log n).---- Complexity: O(n)mapAccumRAVL'::(z->a->(z,b))->z->AVLa->(z,AVLb)mapAccumRAVL'fzta=casemapARztaofUBT2(zt,tb)->(zt,tb)wheremapARz_E=UBT2(z_,E)mapARz_(Nlaara)=mapAR'z_NlaaramapARz_(Zlaara)=mapAR'z_ZlaaramapARz_(Plaara)=mapAR'z_Plaara{-# INLINE mapAR' #-}mapAR'z'claara=casemapARz'raofUBT2(zr,rb)->casefzraof(za,b)->casemapARzalaofUBT2(zl,lb)->UBT2(zl,clbbrb)-------------------------------------------------------------------------------------------------- These two functions attempt to make the strict mapAccums more efficient and reduce heap-- burn rate with ghc by using an accumulating function that returns an unboxed pair.------------------------------------------------------------------------------------------------#ifdef __GLASGOW_HASKELL__-- | Glasgow Haskell only. Similar to 'mapAccumLAVL'' but uses an unboxed pair in the-- accumulating function.---- Complexity: O(n)mapAccumLAVL''::(z->a->UBT2(z,b))->z->AVLa->(z,AVLb)mapAccumLAVL''fzta=casemapALztaofUBT2(zt,tb)->(zt,tb)wheremapALz_E=UBT2(z_,E)mapALz_(Nlaara)=mapAL'z_NlaaramapALz_(Zlaara)=mapAL'z_ZlaaramapALz_(Plaara)=mapAL'z_Plaara{-# INLINE mapAL' #-}mapAL'z'claara=casemapALz'laofUBT2(zl,lb)->casefzlaofUBT2(za,b)->casemapALzaraofUBT2(zr,rb)->UBT2(zr,clbbrb)-- | Glasgow Haskell only. Similar to 'mapAccumRAVL'' but uses an unboxed pair in the-- accumulating function.---- Complexity: O(n)mapAccumRAVL''::(z->a->UBT2(z,b))->z->AVLa->(z,AVLb)mapAccumRAVL''fzta=casemapARztaofUBT2(zt,tb)->(zt,tb)wheremapARz_E=UBT2(z_,E)mapARz_(Nlaara)=mapAR'z_NlaaramapARz_(Zlaara)=mapAR'z_ZlaaramapARz_(Plaara)=mapAR'z_Plaara{-# INLINE mapAR' #-}mapAR'z'claara=casemapARz'raofUBT2(zr,rb)->casefzraofUBT2(za,b)->casemapARzalaofUBT2(zl,lb)->UBT2(zl,clbbrb)#endif-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | Convert a list of known length into an AVL tree, such that the head of the list becomes-- the leftmost tree element. The resulting tree is flat (and also sorted if the supplied list-- is sorted in ascending order).---- If the actual length of the list is not the same as the supplied length then-- an error will be raised.---- Complexity: O(n)asTreeLenL::Int->[e]->AVLeasTreeLenLnes=casesubst(replicateAVLn())esofUBT2(tree,es_)->casees_of[]->tree_->error"asTreeLenL: List too long."where-- Substitute template values for real values taken from the listsubstEas=UBT2(E,as)subst(Nl_r)as=subst'Nlrassubst(Zl_r)as=subst'Zlrassubst(Pl_r)as=subst'Plras{-# INLINE subst' #-}subst'flras=casesubstlasofUBT2(l_,xs)->casexsofa:as'->casesubstras'ofUBT2(r_,as__)->lett_=fl_ar_int_`seq`UBT2(t_,as__)[]->error"asTreeLenL: List too short."-- | As 'asTreeLenL', except the length of the list is calculated internally, not supplied-- as an argument.---- Complexity: O(n)asTreeL::[e]->AVLeasTreeLes=asTreeLenL(lengthes)es-- | Convert a list of known length into an AVL tree, such that the head of the list becomes-- the rightmost tree element. The resulting tree is flat (and also sorted if the supplied list-- is sorted in descending order).---- If the actual length of the list is not the same as the supplied length then-- an error will be raised.---- Complexity: O(n)asTreeLenR::Int->[e]->AVLeasTreeLenRnes=casesubst(replicateAVLn())esofUBT2(tree,es_)->casees_of[]->tree_->error"asTreeLenR: List too long."where-- Substitute template values for real values taken from the listsubstEas=UBT2(E,as)subst(Nl_r)as=subst'Nlrassubst(Zl_r)as=subst'Zlrassubst(Pl_r)as=subst'Plras{-# INLINE subst' #-}subst'flras=casesubstrasofUBT2(r_,xs)->casexsofa:as'->casesubstlas'ofUBT2(l_,as__)->lett_=fl_ar_int_`seq`UBT2(t_,as__)[]->error"asTreeLenR: List too short."-- | As 'asTreeLenR', except the length of the list is calculated internally, not supplied-- as an argument.---- Complexity: O(n)asTreeR::[e]->AVLeasTreeRes=asTreeLenR(lengthes)es-- | Reverse an AVL tree (swaps and reverses left and right sub-trees).-- The resulting tree is the mirror image of the original.---- Complexity: O(n)reverseAVL::AVLe->AVLereverseAVLE=EreverseAVL(Nler)=letl'=reverseAVLlr'=reverseAVLrinl'`seq`r'`seq`Pr'el'reverseAVL(Zler)=letl'=reverseAVLlr'=reverseAVLrinl'`seq`r'`seq`Zr'el'reverseAVL(Pler)=letl'=reverseAVLlr'=reverseAVLrinl'`seq`r'`seq`Nr'el'-- | Apply a function to every element in an AVL tree. This function preserves the tree shape.-- There is also a strict version of this function ('mapAVL'').---- N.B. If the tree is sorted the result of this operation will only be sorted if-- the applied function preserves ordering (for some suitable ordering definition).---- Complexity: O(n)mapAVL::(a->b)->AVLa->AVLbmapAVLf=map'wheremap'E=Emap'(Nlar)=letl'=map'lr'=map'rinl'`seq`r'`seq`Nl'(fa)r'map'(Zlar)=letl'=map'lr'=map'rinl'`seq`r'`seq`Zl'(fa)r'map'(Plar)=letl'=map'lr'=map'rinl'`seq`r'`seq`Pl'(fa)r'-- | Similar to 'mapAVL', but the supplied function is applied strictly.---- Complexity: O(n)mapAVL'::(a->b)->AVLa->AVLbmapAVL'f=map'wheremap'E=Emap'(Nlar)=letl'=map'lr'=map'rb=fainb`seq`l'`seq`r'`seq`Nl'br'map'(Zlar)=letl'=map'lr'=map'rb=fainb`seq`l'`seq`r'`seq`Zl'br'map'(Plar)=letl'=map'lr'=map'rb=fainb`seq`l'`seq`r'`seq`Pl'br'#if __GLASGOW_HASKELL__ > 604traverseAVL::Applicativef=>(a->fb)->AVLa->f(AVLb)traverseAVL_fE=pureEtraverseAVLf(Nlvr)=N<$>traverseAVLfl<*>fv<*>traverseAVLfrtraverseAVLf(Zlvr)=Z<$>traverseAVLfl<*>fv<*>traverseAVLfrtraverseAVLf(Plvr)=P<$>traverseAVLfl<*>fv<*>traverseAVLfr#endif-- | Construct a flat AVL tree of size n (n>=0), where all elements are identical.---- Complexity: O(log n)replicateAVL::Int->e->AVLereplicateAVLme=repmwhere-- Functional spaghetti follows :-)repn|oddn=repOddn-- n is odd , >=1repn=repEvnn-- n is even, >=0-- n is known to be odd (>=1), so left and right sub-trees are identicalrepOddn=letsub=rep(n`shiftR`1)insub`seq`Zsubesub-- n is known to be even (>=0)repEvnn|n.&.(n-1)==0=repP2n-- treat exact powers of 2 specially, traps n=0 toorepEvnn=letnl=n`shiftR`1-- size of left subtree (odd or even)nr=nl-1-- size of right subtree (even or odd)inifoddnrthenletl=repEvnnl-- right sub-tree is odd , so left is even (>=2)r=repOddnrinl`seq`r`seq`Zlerelseletl=repOddnl-- right sub-tree is even, so left is odd (>=2)r=repEvnnrinl`seq`r`seq`Zler-- n is an exact power of 2 (or 0), I.E. 0,1,2,4,8,16..repP20=ErepP21=ZEeErepP2n=letnl=n`shiftR`1-- nl is also an exact power of 2nr=nl-1-- nr is one less that an exact power of 2l=repP2nlr=repP2M1nrinl`seq`r`seq`Pler-- BF=+1-- n is one less than an exact power of 2, I.E. 0,1,3,7,15..repP2M10=ErepP2M1n=letsub=repP2M1(n`shiftR`1)insub`seq`Zsubesub-- | Flatten an AVL tree, preserving the ordering of the tree elements.---- Complexity: O(n)flatten::AVLe->AVLeflattent=asTreeLenL(sizet)(asListLt)-- | Similar to 'flatten', but the tree elements are reversed. This function has higher constant-- factor overhead than 'reverseAVL'.---- Complexity: O(n)flatReverse::AVLe->AVLeflatReverset=asTreeLenL(sizet)(asListRt)-- | Similar to 'mapAVL', but the resulting tree is flat.-- This function has higher constant factor overhead than 'mapAVL'.---- Complexity: O(n)flatMap::(a->b)->AVLa->AVLbflatMapft=asTreeLenL(sizet)(mapf(asListLt))-- | Same as 'flatMap', but the supplied function is applied strictly.---- Complexity: O(n)flatMap'::(a->b)->AVLa->AVLbflatMap'ft=asTreeLenL(sizet)(map'f(asListLt))wheremap'_[]=[]map'g(a:as)=letb=gainb`seq`(b:map'fas)-- | Remove all AVL tree elements which do not satisfy the supplied predicate.-- Element ordering is preserved. The resulting tree is flat.-- See 'filterAVL' for an alternative implementation which is probably more efficient.---- Complexity: O(n)filterViaList::(e->Bool)->AVLe->AVLefilterViaListpt=filter'[]0(asListRt)wherefilter'sen[]=asTreeLenLnsefilter'sen(e:es)=ifpethenletn'=n+1inn'`seq`filter'(e:se)n'eselsefilter'senes-- | Remove all AVL tree elements which do not satisfy the supplied predicate.-- Element ordering is preserved.---- Complexity: O(n)filterAVL::(e->Bool)->AVLe->AVLefilterAVLpt0=casefilter_L(0)t0ofUBT3(_,t_,_)->t_-- Work with relative heights!!wherefilter_ht=casetofE->UBT3(False,E,h)Nler->flDECINT2(h)erDECINT1(h)Zler->flDECINT1(h)erDECINT1(h)Pler->flDECINT1(h)erDECINT2(h)whereflhlerhr=casefilter_hllofUBT3(bl,l_,hl_)->casefilter_hrrofUBT3(br,r_,hr_)->ifpethenifbl||brthencasespliceHl_hl_er_hr_ofUBT2(t_,h_)->UBT3(True,t_,h_)elseUBT3(False,t,h)elsecasejoinHl_hl_r_hr_ofUBT2(t_,h_)->UBT3(True,t_,h_)-- | Partition an AVL tree using the supplied predicate. The first AVL tree in the-- resulting pair contains all elements for which the predicate is True, the second-- contains all those for which the predicate is False. Element ordering is preserved.-- Both of the resulting trees are flat.---- Complexity: O(n)partitionAVL::(e->Bool)->AVLe->(AVLe,AVLe)partitionAVLpt=part0[]0[](asListRt)wherepartnTlstTnFlstF[]=letavlT=asTreeLenLnTlstTavlF=asTreeLenLnFlstFin(avlT,avlF)-- Non strict in avlT, avlF !!partnTlstTnFlstF(e:es)=ifpethenletnT'=nT+1innT'`seq`partnT'(e:lstT)nFlstFeselseletnF'=nF+1innF'`seq`partnTlstTnF'(e:lstF)es-- | Remove all AVL tree elements for which the supplied function returns 'Nothing'.-- Element ordering is preserved. The resulting tree is flat.-- See 'mapMaybeAVL' for an alternative implementation which is probably more efficient.---- Complexity: O(n)mapMaybeViaList::(a->Maybeb)->AVLa->AVLbmapMaybeViaListft=map'[]0(asListRt)wheremap'sbn[]=asTreeLenLnsbmap'sbn(a:as)=casefaofJustb->letn'=n+1inn'`seq`map'(b:sb)n'asNothing->map'sbnas-- | Remove all AVL tree elements for which the supplied function returns 'Nothing'.-- Element ordering is preserved.---- Complexity: O(n)mapMaybeAVL::(a->Maybeb)->AVLa->AVLbmapMaybeAVLft0=casemapMaybe_L(0)t0ofUBT2(t_,_)->t_-- Work with relative heights!!wheremapMaybe_ht=casetofE->UBT2(E,h)Nlar->mlDECINT2(h)arDECINT1(h)Zlar->mlDECINT1(h)arDECINT1(h)Plar->mlDECINT1(h)arDECINT2(h)wheremlhlarhr=casemapMaybe_hllofUBT2(l_,hl_)->casemapMaybe_hrrofUBT2(r_,hr_)->casefaofJustb->spliceHl_hl_br_hr_Nothing->joinHl_hl_r_hr_-- | Invokes 'genPushList' on the empty AVL tree.---- Complexity: O(n.(log n)){-# INLINE genAsTree #-}genAsTree::(e->e->COrderinge)->[e]->AVLegenAsTreec=genPushListcempty-- | Push the elements of an unsorted List in a sorted AVL tree using the supplied combining comparison.---- Complexity: O(n.(log (m+n))) where n is the list length, m is the tree size.genPushList::(e->e->COrderinge)->AVLe->[e]->AVLegenPushListcavl=foldl'addElemavlwhereaddElemte=genPush(ce)et