Triangular Heaps Henk J.M. Goeman Walter A. Kosters Department of Mathematics and Computer Science , Leiden University , P.O. Box 9512 , 2300 RA Leiden , The Netherlands Email : fgoeman,kostersg@wi.LeidenUniv.nl Abstract In this paper we introduce the triangular heap , a heap with the special property that for every father node its right child -LRB- if present -RRB- is smaller than its left child . We show how triangular heaps can be applied to the traditional problem of sorting an array in situ in ways quite similar to well-known methods using ordinary heaps . An average case analysis is presented for the construction and for the sorting process of both ordinary and triangular heaps . 1 Introduction In this paper we propose the triangular heap , a heap with the special property that for every father node -LRB- the key of -RRB- its right child | if present | is smaller than -LRB- the key of -RRB- its left child . Whereas in a heap the largest node always takes the first position -LRB- i.e. the root -RRB- , in a triangular heap both the largest and the second largest node can always be found in first and second position -LRB- i.e. in the root and in the left child of the root -RRB- . The heap and its use for sorting an array in situ were first introduced by Williams and Floyd , see -LSB- 11 -RSB- and -LSB- 3 -RSB- . An important part of the algorithm | the procedure siftdown | builds a heap from a rootnode and two smaller heaps , represented in its two subtrees , by repeatedly interchanging the node with the largest of its children until the node eventually reaches a position where it is larger than its children -LRB- if any -RRB- . This requires two comparisons for each level encountered . The heap construction algorithm consists of a bottom-up series of these operations . Repeatedly removing the largest node and re-establishing the heap structure for the remaining nodes , again with the procedure siftdown , gives rise to a sorting method called heapsort . Efficient and improved implementations of this method were , for instance , given in -LSB- 1 -RSB- , -LSB- 7 -RSB- , -LSB- 9 -RSB- and -LSB- 10 -RSB- . These implementations contain more and more efficient realisations of the procedure siftdown -LRB- effectively resulting in the same heap -RRB- where first a vacant position is sent down to the lowest level at a cost of only one comparison per level , and then the new node is inserted in its proper place in a bottom-up fashion , again at a cost of only one comparison for each level . The name trickledown is commonly used to refer to these improved realisations of siftdown . Note that in a triangular heap more relations between the nodes of the tree are | in a sense | remembered in the tree structure . Thus the triangular heap structure reveals more information on the ordering of its nodes than the ordinary heap structure . Yet it turns out that this extra information can be easily maintained . The central question here is : is it possible to exploit the extra available information in applications of the triangular heap in such a way that this outweighs the extra effort to maintain the stronger structure ? In this paper we shall consider that question applying the triangular heap to the traditional problem of sorting an array in situ . This will result in several new sorting algorithms using procedures quite similar to those often used for the ordinary heap structure . 2 Definitions and Prerequisites A heap is a finite binary tree on a totally ordered set such that each node is larger than its children . Whenever a finite binary tree is a heap we will say that the tree satisfies the heap property . Note that for a heap the underlying complete binary tree corresponds directly to the Hasse diagram of the partial order of known relations between the nodes as implied by the heap structure . To obtain the Hasse diagram one should just ignore the partitioning of outgoing edges in left and right ones . When applying the heap structure to the problem of sorting in situ an array A with indexset f1 : : : ng , the heaps are usually represented within the array itself where node i -LRB- 1 < = i < = n -RRB- has 2i as its left child -LRB- if 2i < = n -RRB- and 2i + 1 as its right child -LRB- if 2i + 1 < = n -RRB- . For the whole array to be a heap we should have A -LSB- i -RSB- < A -LSB- i div 2 -RSB- for every i with 1 < i < = n. Indeed , for every node i with 1 < i < = n its parent is node i div 2 . With this representation a heap is always a complete binary tree . Here complete means that nodes may be absent only at the bottom level of the tree and there only as far to the right as possible . Now , a triangular heap is a heap with the special property that for every father node , having two children , its right child is smaller than its left child . Whenever a finite binary tree is a triangular heap we will say that the tree satisfies the triangular heap property . For a triangular heap the underlying complete binary tree does not correspond directly to the Hasse diagram of the partial order of known relations between the nodes as implied by the triangular heap structure . However , as we shall see shortly , we can easily construct another heap for the same set of nodes , whose corresponding Hasse diagram will also be the Hasse diagram of implied relations for the original triangular heap . There is a well-known and important construction , that establishes a 1-1 correspondence between ordered forests and binary trees . To get the corresponding binary tree from a given ordered forest one should just remove all the original edges and then install a left outgoing edge for each original parent node to its original left-most child and a right outgoing edge for each node to its original next sibling -LRB- if it had any -RRB- . This construction is sometimes called the left-child , right sibling representation . If we apply this construction to a forest , containing just one binary tree T , we will get another binary tree , which will be called its stretched form . The new binary tree will be a heap if and only if the original tree is a triangular heap , and its Hasse diagram is just the Hasse diagram for the original triangular heap . So , to be a triangular heap , the complete binary tree , represented as above in the array A with indexset f1 : : : ng , should have for every i with 1 < i < = n , A -LSB- i -RSB- < A -LSB- i div 2 -RSB- if even -LRB- i -RRB- , and A -LSB- i -RSB- < A -LSB- i ? 1 -RSB- if odd -LRB- i -RRB- . Its stretched form is then easily recognised to be a binary tree , again satisfying the heap property , where node i -LRB- 1 < = i < = n -RRB- has 2i as its left child -LRB- if 2i < = n -RRB- , and i + 1 as its right child -LRB- if i + 1 < = n and even -LRB- i -RRB- -RRB- . And , indeed , every node i with 1 < i < = n now has node i div 2 as its parent if even -LRB- i -RRB- and it has node i ? 1 as its parent if odd -LRB- i -RRB- . Of course , for n > 2 the resulting tree is not complete any more , although it still occupies just the indexset f1 : : : ng . Throughout this paper lg will denote the binary logarithm . The height of a tree is defined in a usual way : the height of an empty tree equals 0 , and the height of a non-empty tree is equal to 1 plus the maximum of the heights of the subtrees of the root . 3 Implementations and Algorithms In this section we will present our algorithms in a procedural notation using a call by value parameter mechanism . The algorithms will be given in a clear and compact form . Several obvious variants and optimisations could have been chosen as well , without a significant effect on the analysis . For instance , when we count the number of swaps in the procedure SiftDown below , it can also be read as counting the number of data movements in an obvious variant for this procedure SiftDown , where a cyclic exchange is done instead of the repetition of swaps . Let an integer m and an array A : array 1 : : : m of SomeType be given , where m > and where SomeType is a totally ordered set . We will assume that elements in different positions of the array are always different . 3.1 Procedures for HeapSort We first present and explain the program HeapSort which sorts an array in situ using ordinary heaps . Obviously , the following procedure Swap -LRB- k ; j -RRB- interchanges two elements of the array A , whenever 1 < = k < = m , 1 < = j < = m and k < > j. Swap -LRB- k ; j -RRB- : A -LRB- k -RRB- ; A -LRB- j -RRB- : = A -LRB- j -RRB- ; A -LRB- k -RRB- For 1 < = k < = n < = m , the procedure SiftDown -LRB- k ; n -RRB- reorders the subtree in the array A , rooted at node k and restricted to the indexset 1 : : : n , into a heap , whenever both of its subtrees rooted at node 2k and at node 2k + 1 , again restricted to the indexset 1 : : : n , are heaps already -LRB- they can be empty -RRB- . SiftDown -LRB- k ; n -RRB- : while k < = n div 2 do j : = 2 ? k ; if j < n then if A -LRB- j -RRB- < A -LRB- j + 1 -RRB- then j : = j + 1 ; if A -LRB- k -RRB- < A -LRB- j -RRB- then Swap -LRB- k ; j -RRB- ; k : = j else k : = n od Then , the procedure MakeHeap establishes the heap property for the array A . This will also be called the construction phase of the sorting process . MakeHeap : k : = m div 2 ; while k > do SiftDown -LRB- k ; m -RRB- ; k : = k ? 1 od Now , finally , the procedure HeapSort sorts the array A in situ . HeapSort : n : = m ; MakeHeap ; while n > 1 do Swap -LRB- 1 ; n -RRB- ; n : = n ? 1 ; SiftDown -LRB- 1 ; n -RRB- od The procedure TrickleDown -LRB- k ; n -RRB- , a trickledown version of SiftDown , may replace SiftDown everywhere above , and can be given as follows : TrickleDown -LRB- k ; n -RRB- : t : = A -LRB- k -RRB- ; l : = k ; while k < = n div 2 do j : = 2 ? k ; if j < n then if A -LRB- j -RRB- < A -LRB- j + 1 -RRB- then j : = j + 1 ; A -LRB- k -RRB- : = A -LRB- j -RRB- ; k : = j od ; i : = k ; while k > l do j : = k div 2 ; if t > A -LRB- j -RRB- then A -LRB- k -RRB- : = A -LRB- j -RRB- ; k : = j ; i : = k else k : = l od ; A -LRB- i -RRB- : = t 3.2 Procedures for Triangular HeapSort We can now present and explain the program TriangularHeapSort which sorts an array in situ using triangular heaps . For 1 < = k < = n < = m , the procedure TriangularSiftDown -LRB- k ; n -RRB- reorders for the stretched form of the tree in array A , the subtree rooted at node k into a heap , whenever its subtrees are heaps already . As we explained earlier , now every node involved is larger than its right sibling and its left-most child -LRB- if present -RRB- as seen in the original unstretched form of the tree in array A. TriangularSiftDown -LRB- k ; n -RRB- : while k < = n div 2 _ -LRB- even -LRB- k -RRB- ^ k < n -RRB- do if k < = n div 2 then j : = 2 ? k ; if even -LRB- k -RRB- then if A -LRB- j -RRB- < A -LRB- k + 1 -RRB- then j : = k + 1 else j : = k + 1 ; if A -LRB- k -RRB- < A -LRB- j -RRB- then Swap -LRB- k ; j -RRB- ; k : = j else k : = n od Then , the analogon of the procedure MakeHeap is the procedure MakeTriangularHeap establishing the triangular heap property for the array A. Note especially that it is necessary here to start at m ? 1 , instead of m div 2 . MakeTriangularHeap : k : = m ? 1 ; while k > do TriangularSiftDown -LRB- k ; m -RRB- ; k : = k ? 1 od Again , finally , the procedure TriangularHeapSort sorts the array A in situ . This algorithm is an easy analogon of the well-known algorithm for HeapSort . TriangularHeapSort : n : = m ; MakeTriangularHeap ; while n > 1 do Swap -LRB- 1 ; n -RRB- ; n : = n ? 1 ; TriangularSiftDown -LRB- 1 ; n -RRB- od We also have a TrickleDown version of TriangularSiftDown , namely the procedure TriangularTrickleDown -LRB- k ; n -RRB- , which can be given as follows : TriangularTrickleDown -LRB- k ; n -RRB- : t : = A -LRB- k -RRB- ; l : = k ; while k < = n div 2 _ -LRB- even -LRB- k -RRB- ^ k < n -RRB- do if k < = n div 2 then j : = 2 ? k ; if even -LRB- k -RRB- then if A -LRB- j -RRB- < A -LRB- k + 1 -RRB- then j : = k + 1 else j : = k + 1 ; A -LRB- k -RRB- : = A -LRB- j -RRB- ; k : = j od ; i : = k ; while k > l do if odd -LRB- k -RRB- then j : = k ? 1 else j : = k div 2 ; if t > A -LRB- j -RRB- then A -LRB- k -RRB- : = A -LRB- j -RRB- ; k : = j ; i : = k else k : = l od ; A -LRB- i -RRB- : = t All these algoritms will be compared and analysed in the following sections . 4 Counting Heaps and Triangular Heaps If f -LRB- n -RRB- denotes the number of heaps on n distinct keys , then -LRB- see -LSB- 8 -RSB- , p. 79 -RRB- f -LRB- n -RRB- = n ! = Y 1 < = k < = n S -LRB- k ; n -RRB- ; where for 1 < = k < = n , S -LRB- k ; n -RRB- is the size of the subtree rooted at k. Analogous to the formula for f -LRB- n -RRB- we can compute g -LRB- n -RRB- , the number of triangular heaps on n distinct keys . It is easily seen that g -LRB- n -RRB- -LRB- n ? 1 -RRB- ! = 1 -LRB- n ? 1 -RRB- s2 g -LRB- s1 -RRB- -LRB- s1 ? 1 -RRB- ! g -LRB- s2 -RRB- -LRB- s2 ? 1 -RRB- ! ; where s1 and s2 are the sizes of the subtrees of the root , S -LRB- 2 ; n -RRB- resp . S -LRB- 3 ; n -RRB- . They satisfy s1 + s2 = n ? 1 . This formula leads to g -LRB- n -RRB- = -LRB- n ? 1 -RRB- ! = Y 1 < = k < = -LRB- n ? 1 -RRB- div 2 -LRB- S -LRB- k ; n -RRB- ? 1 -RRB- S -LRB- 2k + 1 ; n -RRB- : If we take the tree in its stretched form and interpret S -LRB- k ; n -RRB- as the size of the subtree rooted at k in that tree , then we have again , as should be expected , g -LRB- n -RRB- = n ! = Y 1 < = k < = n S -LRB- k ; n -RRB- : If n = 2t ? 1 for some integer t then g -LRB- n -RRB- = f -LRB- n -RRB- = 2 -LRB- n ? 1 -RRB- = 2 . This last result also follows easily if one notes that an ordinary heap with 2t ? 1 elements can be turned into a triangular heap in a unique way by interchanging subtrees whenever the roots of these subtrees are not in correct order . If n = 2t ? 1 one can not lose completeness here . 5 An Analysis of the Algorithms In this section we will analyse the algorithms we have given before . Sorting an array in situ using heaps consists of two parts : the construction phase and the sorting phase . We will examine these phases in separate sections . 5.1 The Construction Phase Since every triangular heap is an \ ordinary '' heap , it is clear that in general the construction requires more comparisons of array elements , and also more data movements . It is easy to show that the number of comparisons needed to construct a heap from a random permutation of f1 ; 2 ; : : : ; ng -LRB- where n = 2k ? 1 for some integer k > 0 -RRB- , using the siftdown algorithm , is always between n ? 1 and 2n ? 2 lg -LRB- n + 1 -RRB- . Using the trickledown version of this algorithm , the number of comparisons is between 32 n ? lg -LRB- n + 1 -RRB- ? 12 and 2n ? 2 lg -LRB- n + 1 -RRB- . The number of data movements -LRB- or swaps -RRB- is between and n ? lg -LRB- n + 1 -RRB- , both for the siftdown version and the trickledown version -LRB- the arrays elements are only moved when the correct place for the \ new node '' | which is the same for both algorithms | is found -RRB- . In the following the next lemma will be used frequently . Lemma . -LRB- i -RRB- Suppose that real numbers a , b and c , and a function G are given . The solution of the recurrence M -LRB- n -RRB- = 2 M -LRB- n ? 1 2 -RRB- + a lg -LRB- n + 1 -RRB- + b + G -LRB- n -RRB- ; M -LRB- 3 -RRB- = c ; where n = 2k ? 1 for integer k > = 3 , is given by M -LRB- n -RRB- = 8 < : lg -LRB- n +1 -RRB- X l = 3 G -LRB- 2l ? 1 -RRB- 2l + a + b + c 4 9 = ; -LRB- n + 1 -RRB- ? a lg -LRB- n + 1 -RRB- ? -LRB- 2a + b -RRB- : -LRB- ii -RRB- Suppose that real numbers a , b , c and d are given . Let , for n = 2k ? 1 with integer k > 0 , L -LRB- n -RRB- = lg -LRB- n + 1 -RRB- n -LRB- an + b -RRB- + c + d n and G -LRB- n -RRB- = -LRB- a ? b -RRB- lg -LRB- n + 1 -RRB- n + ? a + 2b + c ? d n + a : Then L -LRB- n -RRB- satisfies the recurrence L -LRB- n -RRB- = G -LRB- n -RRB- + n ? 1 n L -LRB- n ? 1 2 -RRB- : Proof . Straightforward . 2 For triangular heaps we have : Theorem . The number of comparisons needed to construct a triangular heap from a random permutation of f1 ; 2 ; : : : ; ng -LRB- where n = 2k ? 1 for some integer k > 0 -RRB- , using the staightforward algorithm , is between n ? 1 and 134 n ? 3 lg -LRB- n + 1 -RRB- ? 34 , and using the trickledown version between 32 n ? lg -LRB- n + 1 -RRB- ? 12 and 134 n ? 3 lg -LRB- n + 1 -RRB- ? 34 . If n = 1 both upper bounds are 0 . Proof . For the siftdown algorithm , a siftdown at a node that is the root of a subtree of height h > 1 takes between 2 and 3h ? 2 comparisons if the node is a left child in the original tree , and between 1 and 3h ? 4 comparisons if the node is a right child in -LRB- or the root of -RRB- the original tree . For leaves the values are 1 , 1 , and respectively . For the trickledown version the lower bounds are h for left children and h ? 1 for right children ; the upper bounds are the same as those for the siftdown algorithm . The lower bound for the number of comparisons needed for the construction of a triangular heap using the siftdown algorithm follows by solving the recurrence B -LRB- n -RRB- = 2 B -LRB- n ? 1 2 -RRB- + 2 ; B -LRB- 1 -RRB- = : The upper bounds for the construction of a triangular heap using the two algorithms coincide . Let U -LRB- n -RRB- denote this upper bound . In order to construct a triangular heap , the left and right subtrees of the root have to be triangular heaps -LRB- requiring at most U -LRB- n ? 12 -RRB- +2 resp . U -LRB- n ? 12 -RRB- comparisons ; remember that a siftdown at the left child may involve the right subtree -RRB- , and we should add 3 lg -LRB- n + 1 -RRB- ? 4 comparisons for the siftdown at the root . We are led to the recurrence U -LRB- n -RRB- = 2 U -LRB- n ? 1 2 -RRB- + 3 lg -LRB- n + 1 -RRB- ? 2 ; with boundary value U -LRB- 3 -RRB- = 3 , from which the formula for the upper bound follows , using the Lemma . The lower bound for the trickledown version is derived in a similar way . -LRB- As we will see shortly , it is also possible to proceed in a more general manner . -RRB- 2 Doberkat -LRB- see -LSB- 2 -RSB- or -LSB- 4 -RSB- , p. 213 -RRB- proved that the number of comparisons for the siftdown algorithm is approximately 1:88 n in the average case . Using this result Wegener -LRB- see -LSB- 9 -RSB- -RRB- showed that for the trickledown version it is approximately 1:65 n . We shall now give similar results for triangular heaps . Our methods are also applicable to ordinary heaps , where they confirm the results of Doberkat and Wegener . We need a result that holds in a more general setting . Let us consider ordered oriented trees -LRB- this means that the children of a node are ordered from left to right -RRB- . In order to establish the heap property for such a tree we use an obvious generalisation of the siftdown algorithm : in a bottom-up fashion all subtrees are heapified by repeatly interchanging -LRB- as long as necessary -RRB- the root of the subtree with its largest child . In a similar way we have an obvious generalisation of the trickledown version . We let M1 -LRB- T -RRB- resp . M2 -LRB- T -RRB- denote the average number of comparisons needed to establish the heap property for the ordered oriented tree T using the generalisation of the siftdown version resp . the trickledown version . Here we suppose that all permutations of f1 ; 2 ; : : : ; tg are equally likely -LRB- where t is the number of nodes in T -RRB- . Let L1 -LRB- T -RRB- resp . L2 -LRB- T -RRB- denote the average number of comparisons during the final siftdown resp . trickledown at the root for the siftdown version resp . the trickledown version , and let H -LRB- T -RRB- be the average number of comparisons needed -LRB- for the trickledown version , again during the final trickledown -RRB- when the root of T already contains t , the largest number in T . For empty trees T we define Mj -LRB- T -RRB- = Lj -LRB- T -RRB- = -LRB- j = 1 ; 2 -RRB- . We have : Proposition . Let T be an ordered oriented tree with t > 1 nodes , where the root has w > = 1 -LRB- non-empty -RRB- subtrees T1 , T2 , ... , Tw . Suppose that Ti has ti nodes -LRB- i = 1 ; 2 ; : : : ; w -RRB- . Then , for j = 1 ; 2 , we have Mj -LRB- T -RRB- = wX i = 1 Mj -LRB- Ti -RRB- + Lj -LRB- T -RRB- ; Lj -LRB- T -RRB- = Gj -LRB- T -RRB- + wX i = 1 ti t L1 -LRB- Ti -RRB- ; G1 -LRB- T -RRB- = w and G2 -LRB- T -RRB- = w ? 1 + 1 t + 1 t H -LRB- T -RRB- ; where H -LRB- T -RRB- satisfies H -LRB- T -RRB- = w + wX i = 1 ti t ? 1H -LRB- Ti -RRB- with boundary value H -LRB- T -RRB- = if T has one node . If T has one node we have M1 -LRB- T -RRB- = M2 -LRB- T -RRB- = L1 -LRB- T -RRB- = L2 -LRB- T -RRB- = 0 . Proof . The probability that just before the final siftdown t is in the root of T equals 1 = t . If a node has w children , it takes w ? 1 comparisons to find its largest child . If t is in the root , the siftdown algorithm needs w comparisons , whereas the trickledown version needs | by definition | H -LRB- T -RRB- comparisons . Key t is with probability ti = t in subtree Ti , just before the final siftdown . In this case the siftdown algorithm takes -LRB- in the average case -RRB- w + L1 -LRB- Ti -RRB- comparisons . In fact , the numbers in Ti turn out to be random . For the trickledown version the argument is a little more intricate . In this case , if t happens to be in subtree Ti , we need w ? 1 + L2 -LRB- Ti -RRB- comparisons , except for the case when the original root of the tree turns out to be the largest number in Ti -LRB- after the removal of t from this tree -RRB- ; this happens with probability 1 = ti . We then have one extra comparison , leading to a total of L2 -LRB- T -RRB- = 1 t H -LRB- T -RRB- + wX i = 1 ti t -LRB- L2 -LRB- Ti -RRB- + w ? 1 + 1 ti -RRB- = 1 t H -LRB- T -RRB- + wX i = 1 ti t L2 -LRB- Ti -RRB- + -LRB- w ? 1 -RRB- -LRB- t ? 1 -RRB- + w t comparisons ; the desired formula easily follows . The recursion for H -LRB- T -RRB- can be proved in the following way . At the root level we need w ? 1 comparisons to find the largest child , which is the root of subtree Ti with probability ti = -LRB- t ? 1 -RRB- -LRB- note that the denominator is t ? 1 instead of t , since the root value t is already fixed -RRB- . In this subtree we use L2 -LRB- Ti -RRB- comparisons on average . Finally , key t returns to the root using one extra comparison . 2 One should be aware of the fact that all these quantities depend on the shape of T . As a degenerate case we have lists : all father nodes in T have exactly one child . Then one can compute L1 -LRB- T -RRB- = L2 -LRB- T -RRB- = 1 2t -LRB- t ? 1 -RRB- -LRB- t + 2 -RRB- and M1 -LRB- T -RRB- = M2 -LRB- T -RRB- = 1 4 -LRB- t ? 1 -RRB- -LRB- t + 4 -RRB- ? Ht + 1 = 1 4t2 + O -LRB- t -RRB- ; where the harmonic numbers Ht are defined by Ht = Pti = 1 1 = i . This result is not surprising : for lists both algorithms boil down to insertion sort . Note that in a similar way formulas can be given for the average number of data movements or swaps . Now we define Ak and Bk for integer k > = by Ak = kX l = 1 l 2l -LRB- 2l ? 1 -RRB- and Bk = kX l = 1 1 2l -LRB- 2l ? 1 -RRB- ; so A0 = B0 = 1 , A1 = B1 = 1 = 2 , A2 = 2 = 3 and B2 = 7 = 12 . Let A = limk ! 1 Ak ss :744 and B = limk ! 1 Bk ss :607 . In -LSB- 2 -RSB- and -LSB- 9 -RSB- the numbers 1 , 2 and are defined by : 1 = 1X l = 1 1 2l ? 1 ; 2 = 1X l = 1 1 -LRB- 2l ? 1 -RRB- 2 and = B ? 12 . They can also be defined as certain basic hypergeometric series . Note that = 1X l = 2 1 2l -LRB- 2l ? 1 -RRB- = 1X l = 2 1 2l ? 1 ? 1X l = 2 1 2l = 1 ? 3 2 : Furthermore A = 1 + 2 ? 2 , since 1 + 2 = 1X l = 1 2l -LRB- 2l ? 1 -RRB- 2 = 1X l = 1 1 = 2l -LRB- 1 ? 1 = 2l -RRB- 2 = 1X l = 1 1X j = 1 j -LRB- 1 = 2l -RRB- j = 1X j = 1 j 1X l = 1 -LRB- 1 = 2j -RRB- l = 1X j = 1 j 1 = 2j 1 ? 1 = 2j = 1X l = 1 l 2l ? 1 = 1X l = 1 l 2l -LRB- 2l ? 1 -RRB- + 1X l = 1 l 2l = A + 2 ; where we used 1X l = 1 xl = x 1 ? x and 1X l = 1 l xl = x -LRB- 1 ? x -RRB- 2 for real x with ? 1 < x < 1 . As a consequence of the proposition we have Theorem . The construction of a heap on n = 2k ? 1 -LRB- integer k > 0 -RRB- elements using the siftdown algorithm takes -LRB- 1 + 2Ak ? Bk -RRB- -LRB- n + 1 -RRB- ? 2 lg -LRB- n + 1 -RRB- ? 1 comparisons in the average case . For the trickledown version it takes -LRB- 3 ? Ak ? Bk -RRB- -LRB- n + 1 -RRB- ? lg -LRB- n + 1 -RRB- ? 3 comparisons in the average case . For triangular heaps the siftdown algorithm takes -LRB- 9 8 + 5 2Ak ? 3 4Bk -RRB- -LRB- n + 1 -RRB- ? 5 2 lg -LRB- n + 1 -RRB- ? 7 4 comparisons in the average case -LRB- if n > = 3 -RRB- and the trickledown version between -LRB- 77 24 ? 3 2Ak -RRB- -LRB- n + 1 -RRB- ? lg -LRB- n + 1 -RRB- ? 25 6 and -LRB- 37 12 ? 3 2Ak ? 9 40Bk -RRB- -LRB- n + 1 -RRB- ? lg -LRB- n + 1 -RRB- ? 503 120 comparisons -LRB- again for n > = 3 -RRB- . Proof . Let us first examine ordinary heaps , so all trees considered are complete binary trees . We write Lj -LRB- n -RRB- = Lj -LRB- T -RRB- and Mj -LRB- n -RRB- = Mj -LRB- T -RRB- -LRB- j = 1 ; 2 -RRB- , where n = 2k ? 1 is the number of nodes in T . Using the proposition , we get L1 -LRB- n -RRB- = 2 + n ? 1 n L1 -LRB- n ? 1 2 -RRB- ; L1 -LRB- 1 -RRB- = ; with solution L1 -LRB- n -RRB- = 2 n lg -LRB- n + 1 -RRB- -LRB- n + 1 -RRB- ? 3 ? 1 n : We arrive at M1 -LRB- n -RRB- = 2 M1 -LRB- n ? 1 2 -RRB- + 2 n lg -LRB- n + 1 -RRB- -LRB- n + 1 -RRB- ? 3 ? 1 n ; M1 -LRB- 1 -RRB- = : In case of the trickledown version we have to compute H -LRB- T -RRB- , but for a complete binary tree T of height h this is easy : H -LRB- T -RRB- = 2 -LRB- h ? 1 -RRB- . We are led to L2 -LRB- n -RRB- = 1 + 1 n -LRB- 1 + 2 -LRB- lg -LRB- n + 1 -RRB- ? 1 -RRB- -RRB- + n ? 1 n L2 -LRB- n ? 1 2 -RRB- ; L2 -LRB- 1 -RRB- = ; with solution L2 -LRB- n -RRB- = -LRB- lg -LRB- n + 1 -RRB- + 1 -RRB- -LRB- 1 ? 1 n -RRB- ; leading to M2 -LRB- n -RRB- = 2 M2 -LRB- n ? 1 2 -RRB- + -LRB- lg -LRB- n + 1 -RRB- + 1 -RRB- -LRB- 1 ? 1 n -RRB- ; M2 -LRB- 1 -RRB- = : Using the Lemma we get the solutions mentioned above . These formulas support the intuition that most keys have to sink down to one of the lowest levels , thereby favouring the trickledown version : L1 -LRB- n -RRB- ss 2 lg -LRB- n + 1 -RRB- ? 3 , whereas L2 -LRB- n -RRB- ss lg -LRB- n + 1 -RRB- + 1 . For triangular heaps we have to do more . We apply the proposition to the stretched form of the tree . In the following we will examine Mj -LRB- T -RRB- , where T is now the stretched form of the original tree . We will also write Mj -LRB- n -RRB- instead of Mj -LRB- T -RRB- , if T has n nodes ; remember that in general the shape of the tree can not be inferred from the number n , but this will be clear from the context . For the moment we drop the index j . In the following we shall derive different recurrences for M -LRB- n -RRB- and M -LRB- n ? 1 -RRB- -LRB- n = 2k ? 1 -RRB- , reflecting the fact that in triangular heaps left and right children play an asymmetric role . We shall always try to rephrase our recurrences in such a way that they are restricted to left children only : we eliminate the terms corresponding to right children . We have M -LRB- n -RRB- = M -LRB- n ? 1 -RRB- + L -LRB- n -RRB- and M -LRB- n ? 1 -RRB- = M -LRB- n ? 32 -RRB- + M -LRB- n ? 12 -RRB- + L -LRB- n ? 1 -RRB- -LRB- n > = 3 -RRB- . Of course , M -LRB- 1 -RRB- = L -LRB- 1 -RRB- = 0 . From these equations it follows that M -LRB- n -RRB- = 2M -LRB- n ? 1 2 -RRB- + -LRB- L -LRB- n -RRB- + L -LRB- n ? 1 -RRB- ? L -LRB- n ? 1 2 -RRB- -RRB- : For L -LRB- n -RRB- we have L -LRB- n -RRB- = G -LRB- n -RRB- + n ? 1 n L -LRB- n ? 1 -RRB- and L -LRB- n ? 1 -RRB- = G -LRB- n ? 1 -RRB- + n ? 3 2 -LRB- n ? 1 -RRB- L -LRB- n ? 3 2 -RRB- + 1 2L -LRB- n ? 1 2 -RRB- : From these equations it follows that L -LRB- n -RRB- = G -LRB- n -RRB- + n ? 1 n ae G -LRB- n ? 1 -RRB- ? 1 2G -LRB- n ? 1 2 -RRB- oe + n ? 1 n L -LRB- n ? 1 2 -RRB- and L -LRB- n ? 1 -RRB- ? L -LRB- n ? 1 2 -RRB- = G -LRB- n ? 1 -RRB- ? 1 2G -LRB- n ? 1 2 -RRB- : Now we look at the triangular siftdown algorithm . For L = L1 we have G -LRB- n -RRB- = 1 and G -LRB- n ? 1 -RRB- = 2 . Note that G -LRB- 2 -RRB- = 1 . We find L1 -LRB- n -RRB- = 5n ? 3 2n + n ? 1 n L1 -LRB- n ? 1 2 -RRB- ; L1 -LRB- 3 -RRB- = 5 = 3 : Using the Lemma we get L1 -LRB- n -RRB- = 5 lg -LRB- n + 1 -RRB- 2n -LRB- n + 1 -RRB- ? 19 4 ? 3 4n ; so -LRB- note the term ? 134 -RRB- : M1 -LRB- n -RRB- = 2M1 -LRB- n ? 1 2 -RRB- + 5 lg -LRB- n + 1 -RRB- 2n -LRB- n + 1 -RRB- ? 13 4 ? 3 4n ; M1 -LRB- 3 -RRB- = 8 = 3 ; and finally , again using the Lemma , we arrive at M1 -LRB- n -RRB- = -LRB- 9 8 + 5 2Ak ? 3 4Bk -RRB- -LRB- n + 1 -RRB- ? 5 2 lg -LRB- n + 1 -RRB- ? 7 4 : For L = L2 we have to compute H -LRB- T -RRB- = H -LRB- n -RRB- , since here G -LRB- n -RRB- = 1 n -LRB- H -LRB- n -RRB- + 1 -RRB- and G -LRB- n ? 1 -RRB- = 1 + 1 n ? 1 -LRB- H -LRB- n ? 1 -RRB- + 1 -RRB- : The H -LRB- n -RRB- satisfy the recurrence H -LRB- n -RRB- = 5 2 + 1 2 -LRB- n ? 2 -RRB- + H -LRB- n ? 1 2 -RRB- -LRB- use H -LRB- n -RRB- = 1 + H -LRB- n ? 1 -RRB- and H -LRB- n ? 1 -RRB- = 2 + n ? 1 2 -LRB- n ? 2 -RRB- H -LRB- n ? 12 -RRB- + n ? 3 2 -LRB- n ? 2 -RRB- H -LRB- n ? 32 -RRB- -RRB- , leading to H -LRB- n -RRB- = 5 2 lg -LRB- n + 1 -RRB- ? 3 + 1 2 k ? 3 X i = 0 1 = -LRB- 2k ? i ? 3 -RRB- -LRB- remember n = 2k ? 1 -RRB- , with H -LRB- 1 -RRB- = and H -LRB- 3 -RRB- = 2 . So we have L2 -LRB- n -RRB- = -LRB- 5 lg -LRB- n + 1 -RRB- 2n + 1 + 1 n `` n + 1 2 -LRB- n ? 2 -RRB- ? 3 2 ! -RRB- + n ? 1 n L2 -LRB- n ? 1 2 -RRB- -LRB- n > = 7 -RRB- ; where `` n = 1 2 k ? 3 X i = 0 1 = -LRB- 2k ? i ? 3 -RRB- : The boundary value is L2 -LRB- 3 -RRB- = 5 = 3 . Now for n > = 7 1 = 6 < = `` n + 1 2 -LRB- n ? 2 -RRB- < = 1 = 5 : This leads to a lower bound recurrence and an upper bound recurrence for L2 -LRB- n -RRB- : L2 -LRB- n -RRB- = -LRB- 5 lg -LRB- n + 1 -RRB- 2n + 1 ? n -RRB- + n ? 1 n L2 -LRB- n ? 1 2 -RRB- -LRB- n > = 7 -RRB- ; L2 -LRB- 3 -RRB- = 5 = 3 ; where = 4 = 3 for the lower bound and = 13 = 10 for the upper bound , with solutions -LRB- again using the Lemma -RRB- L ? 2 -LRB- n -RRB- = lg -LRB- n + 1 -RRB- n -LRB- n ? 3 = 2 -RRB- + 7 6 ? 3 2n as a lower bound and L +2 -LRB- n -RRB- = lg -LRB- n + 1 -RRB- n -LRB- n ? 3 = 2 -RRB- + 47 40 ? 61 40n as an upper bound . Again we can see the positive effect of the trickledown operation : L1 -LRB- n -RRB- ss 52 lg -LRB- n + 1 -RRB- ? 194 , whereas L2 -LRB- n -RRB- ss lg -LRB- n + 1 -RRB- + 1:2 : In a similar way we can handle M2 . We get M2 -LRB- n -RRB- = 2 M2 -LRB- n ? 1 2 -RRB- + 8 < : L2 -LRB- n -RRB- + 1 + 1 2 -LRB- n ? 2 -RRB- + 3 = 2 n ? 1 9 = ; with boundary value M2 -LRB- 3 -RRB- = 8 = 3 . Now we can use 3 2n < = 1 2 -LRB- n ? 2 -RRB- + 3 = 2 n ? 1 < = 1 60 + 7 4n -LRB- n > = 7 -RRB- ; the bounds for L2 and the Lemma to show that -LRB- 77 24 ? 3 2Ak -RRB- -LRB- n + 1 -RRB- ? 25 6 < = M2 -LRB- n -RRB- + lg -LRB- n + 1 -RRB- < = -LRB- 37 12 ? 3 2Ak + 9 40Bk -RRB- -LRB- n + 1 -RRB- ? 503 120 ; thereby finishing the proof . 2 Note that , as k ! 1 , 1 + 2Ak ? Bk ! 1 + 2A ? B = 1 + 2 2 ? 2 ss 1:88 -LRB- Doberkat 's result -RRB- , 3 ? Ak ? Bk ! 3 ? A ? B = 9 2 ? 1 ? 2 ? ss 1:65 -LRB- Wegener 's result -RRB- and 9 8 + 5 2Ak ? 3 4Bk ! 9 8 + 5 2A ? 3 4B ss 2:53 : Thus it takes approximately 2:53 n comparisons to construct a triangular heap on n nodes using the siftdown algorithm . For the trickledown version , 77 24 ? 3 2Ak ! 77 24 ? 3 2A ss 2:09 ; whereas 37 12 ? 3 2Ak + 9 40Bk ! 37 12 ? 3 2A + 9 40B ss 2:10 ; so it takes approximately 2:1 n comparisons to construct a triangular heap using this algorithm . Again , formulas for the average number of data movements or swaps can be given in a similar way . We conclude that with little extra work a much stronger structure can be accomplished . 5.2 The Sorting Phase So let us now pay attention to the sorting phase . In -LSB- 8 -RSB- Schaffer and Sedgewick show that the average number of data movements -LRB- in fact , assignments between array elements -RRB- required to sort a random permutation of n distinct keys using ordinary heapsort is approximately n lg n -LRB- for large n -RRB- . Our implementation of the ordinary heapsort uses swaps , but these can easily be replaced with data movements . Then , counting the number of swaps in our version is exactly the same as counting the number of data movements in the terminology of -LSB- 8 -RSB- . This justifies a direct comparison of our results with those of -LSB- 8 -RSB- . As is easily seen , the siftdown algorithm for triangular heaps never does more than 2n lg n swaps . As usual we assume that all permutations are equally likely . We will show : Theorem . The average number of swaps needed to sort a random permutation of n distinct keys -LRB- where n = 2k ? 1 for some integer k > 0 -RRB- using the siftdown algorithm for triangular heaps is bounded from below by -LRB- 1 = lg OE -RRB- n lg n , where OE = 12 -LRB- 1 + p5 -RRB- ; 1 = lg OE ss 1:44 . This bound holds for sufficiently large n. Proof . The proof proceeds analogous to that of Theorem 3 in -LSB- 8 -RSB- , where so-called pulldown sequences are used ; for triangular heaps they can be defined in a similar way . As we will see , it is also possible to argue without these sequences . We already know that the construction phase takes a linear number of swaps ; indeed , in Section 5.1 we proved that the number of comparisons is at most 134 n , and the number of swaps is at most equal to the number of comparisons . So we may restrict our attention to the sorting phase . The next observation is that in a triangular heap the number of keys that may have reached their position -LRB- during a fixed siftdown at the root -RRB- at the cost of l swaps is bounded from above by OEl . -LRB- For \ ordinary '' heaps this upper bound is 2l , the maximal number of keys at level l + 1 . -RRB- This follows from the fact that in a triangular heap with height larger than l + 1 there are exactly fib -LRB- l -RRB- of those keys ; here fib -LRB- l -RRB- denotes the lth Fibonacci number , defined by fib -LRB- l -RRB- = fib -LRB- l ? 1 -RRB- + fib -LRB- l ? 2 -RRB- for l > = 2 and fib -LRB- 0 -RRB- = fib -LRB- 1 -RRB- = 1 . It is well-known that fib -LRB- l -RRB- = Round -LRB- OEp5 OEl -RRB- < = OEl . Any possible value for l is bounded from above by 2blg nc , being the length of the longest \ search path '' in a triangular heap with n nodes . Now suppose that the sorting phase requires li swaps during the ith siftdown -LRB- i = 1 ; 2 ; : : : ; n -RRB- . These numbers are uniquely determined by the key that is sifted down . Summing over all sequences l1 ; l2 ; : : : ; ln with Pi li < M -LRB- this sum being the total number of swaps -RRB- we may conclude that there are at most -LRB- 2 lg n -RRB- n 1OE ? 1 OEM triangular heaps that require fewer than M swaps to sort . In fact , from our observations it follows that there are at most 2 lg n OEli triangular heaps requiring exactly li swaps during the ith siftdown . Now let M = n -LRB- logOEn ? logOE -LRB- 2 lg n -RRB- ? 4 -RRB- . We have seen that the number of triangular heaps that require fewer than M swaps to sort is bounded from above by A -LRB- n -RRB- = 1OE ? 1 -LRB- n = OE4 -RRB- n. Therefore the number of swaps required by the siftdown algorithm in the average case is bounded from below by g -LRB- n -RRB- ? A -LRB- n -RRB- g -LRB- n -RRB- M = M ? nA -LRB- n -RRB- g -LRB- n -RRB- -LRB- logOEn ? logOE -LRB- 2 lg n -RRB- ? 4 -RRB- : In order to complete the proof it is sufficient to show that g -LRB- n -RRB- , the number of triangular heaps on n keys , is exponentially larger than A -LRB- n -RRB- . We have g -LRB- n -RRB- = f -LRB- n -RRB- = 2 -LRB- n ? 1 -RRB- = 2 , which is larger than -LRB- n = 4ep2 -RRB- n -LRB- use the fact that f -LRB- n -RRB- > -LRB- n = 4e -RRB- n -RRB- , and finally note that 4ep2 < OE4 . 2 Experiments suggest that this lower bound is rather tight . Therefore , the number of swaps is somewhat larger than that for ordinary heapsort . 6 Discussion In this paper we introduced the triangular heap and examined some of its properties . We have applied triangular heaps to the traditional problem of sorting an array in situ . Several interesting and efficient sorting algorithms are described . The stronger structure of the triangular heap can be established and maintained with only little extra work . Good bounds for the average number of comparisons for the construction phase and for the average number of data movements for the sorting phase are derived . Still many questions can be asked and remain to be investigated . It would be interesting , for instance , to find applications of heaps , where the stronger structure of the triangular heap is particularly useful . Conjectures like those in -LSB- 9 -RSB- can also be formulated for triangular heaps : experiments suggest that the average number of comparisons used by the trickledown algorithm for triangular heaps is approximately n lg n + :30 n , outbeating its ordinary heap counterpart -LRB- that uses less swaps -RRB- . It would also be interesting to examine the expected height -LRB- or position -RRB- of a given number in a triangular heap -LRB- cf. -LSB- 5 -RSB- -RRB- . References -LSB- 1 -RSB- S. Carlsson , A Variant of Heapsort with Almost Optimal Number of Comparisons , Information Processing Letters 24 -LRB- 1987 -RRB- , 247 -LCB- 250 . -LSB- 2 -RSB- E.E. Doberkat , An Average Case Analysis of Floyd 's Algorithm to Construct Heaps , Information and Control 61 -LRB- 1984 -RRB- , 114 -LCB- 131 . -LSB- 3 -RSB- R.W. Floyd , Algorithm 245 : Treesort 3 , Communications of the ACM 7 -LRB- 1964 -RRB- , 701 . -LSB- 4 -RSB- G.H. Gonnet and R. Baeza-Yates , Handbook of Algorithms and Data Structures , Second edition , Addison-Wesley , 1991 . -LSB- 5 -RSB- J.M. de Graaf and W.A. Kosters , Expected Heights in Heaps , BIT 32 -LRB- 1992 -RRB- , 570 -LCB- 579 . -LSB- 6 -RSB- D.E. Knuth , The Art of Computer Programming , Volume 3 , Sorting and Searching , Addison-Wesley , 1973 . -LSB- 7 -RSB- C.J.H. McDiarmid and B.A. Reed , Building Heaps Fast , Journal of Algorithms 10 -LRB- 1989 -RRB- , 352 -LCB- 365 . -LSB- 8 -RSB- R. Schaffer and R. Sedgewick , The Analysis of Heapsort , Journal of Algorithms 15 -LRB- 1993 -RRB- , 76 -LCB- 100 . -LSB- 9 -RSB- I. Wegener , Bottom-up-heap Sort , a New Variant of Heap Sort Beating on Average Quick Sort , p. 516 -LCB- 522 in Proceedings Mathematical Foundations of Computer Science , LNCS 452 , Springer-Verlag , 1990 . -LSB- 10 -RSB- I. Wegener , A Simple Modification of Xunrang and Yuzhang 's HEAPSORT Variant Improving its Complexity Significantly , The Computer Journal 36 -LRB- 1993 -RRB- , 286 -LCB- 288 . -LSB- 11 -RSB- J.W.J. Williams , Algorithm 232 : HEAPSORT , Communications of the ACM 7 -LRB- 1964 -RRB- , 347 -LCB- 348 . Leiden , December 1994

O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O B O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O B O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O O O O O O O O O O B O O O O O O O O O O O O O O O O O O