Pairing heap

A pairing heap is a type of heap data structure with relatively simple implementation and excellent practical amortized performance, introduced by Michael Fredman, Robert Sedgewick, Daniel Sleator, and Robert Tarjan in 1986.[1] Pairing heaps are heap-ordered multiway tree structures, and can be considered simplified Fibonacci heaps. They are considered a "robust choice" for implementing such algorithms as Prim's MST algorithm,[2] and support the following operations (assuming a min-heap):

The analysis of pairing heaps' time complexity was initially inspired by that of splay trees.[1] The amortized time per delete-min is O(log n), and the operations find-min, merge, and insert run in O(1) amortized time.[3]

Determining the precise asymptotic running time of pairing heaps when a decrease-key operation is needed has turned out to be difficult. Initially, the time complexity of this operation was conjectured on empirical grounds to be O(1),[4] but Fredman proved that the amortized time per decrease-key is at least for some sequences of operations.[5] Using a different amortization argument, Pettie then proved that insert, meld, and decrease-key all run in amortized time, which is .[6] Elmasry later introduced a variant of pairing heaps for which decrease-key runs in amortized time and with all other operations matching Fibonacci heaps,[7] but no tight bound is known for the original data structure.[6][3] Moreover, it is an open question whether a amortized time bound for decrease-key and a amortized time bound for insert can be achieved simultaneously.[8]

Although this is worse than other priority queue algorithms such as Fibonacci heaps, which perform decrease-key in amortized time, the performance in practice is excellent. Stasko and Vitter,[4] Moret and Shapiro,[9] and Larkin, Sen, and Tarjan[8] conducted experiments on pairing heaps and other heap data structures. They concluded that pairing heaps are often faster in practice than array-based binary heaps and d-ary heaps, and almost always faster in practice than other pointer-based heaps, including data structures like Fibonacci heaps that are theoretically more efficient.

Structure

A pairing heap is either an empty heap, or a pair consisting of a root element and a possibly empty list of pairing heaps. The heap ordering property requires that all the root elements of the subheaps in the list are not smaller than the root element of the heap. The following description assumes a purely functional heap that does not support the decrease-key operation.

type PairingHeap[Elem] = Empty | Heap(elem: Elem, subheaps: List[PairingHeap[Elem]])

A pointer-based implementation for RAM machines, supporting decrease-key, can be achieved using three pointers per node, by representing the children of a node by a singly-linked list: a pointer to the node's first child, one to its next sibling, and one to the parent. Alternatively, the parent pointer can be omitted by letting the last child point back to the parent, if a single boolean flag is added to indicate "end of list". This achieves a more compact structure at the expense of a constant overhead factor per operation.[1]

Operations

find-min

The function find-min simply returns the root element of the heap:

function find-min(heap)
  if heap == Empty
    error
  else
    return heap.elem


merge

Merging with an empty heap returns the other heap, otherwise a new heap is returned that has the minimum of the two root elements as its root element and just adds the heap with the larger root to the list of subheaps:

function merge(heap1, heap2)
  if heap1 == Empty
    return heap2
  elsif heap2 == Empty
    return heap1
  elsif heap1.elem < heap2.elem
    return Heap(heap1.elem, heap2 :: heap1.subheaps)
  else
    return Heap(heap2.elem, heap1 :: heap2.subheaps)


insert

The easiest way to insert an element into a heap is to merge the heap with a new heap containing just this element and an empty list of subheaps:

function insert(elem, heap)
  return merge(Heap(elem, []), heap)


delete-min

The only non-trivial fundamental operation is the deletion of the minimum element from the heap. The standard strategy first merges the subheaps in pairs (this is the step that gave this datastructure its name) from left to right and then merges the resulting list of heaps from right to left:

function delete-min(heap)
  if heap == Empty
    error
  else
    return merge-pairs(heap.subheaps)


This uses the auxiliary function merge-pairs:

function merge-pairs(l)
  if length(l) == 0
    return Empty
  elsif length(l) == 1
    return l[0]
  else
    return merge(merge(l[0], l[1]), merge-pairs(l[2.. ]))


That this does indeed implement the described two-pass left-to-right then right-to-left merging strategy can be seen from this reduction:

   merge-pairs([H1, H2, H3, H4, H5, H6, H7])
=> merge(merge(H1, H2), merge-pairs([H3, H4, H5, H6, H7]))
     # merge H1 and H2 to H12, then the rest of the list
=> merge(H12, merge(merge(H3, H4), merge-pairs([H5, H6, H7])))
     # merge H3 and H4 to H34, then the rest of the list
=> merge(H12, merge(H34, merge(merge(H5, H6), merge-pairs([H7]))))
     # merge H5 and H6 to H56, then the rest of the list
=> merge(H12, merge(H34, merge(H56, H7)))
     # switch direction, merge the last two resulting heaps, giving H567
=> merge(H12, merge(H34, H567))
     # merge the last two resulting heaps, giving H34567
=> merge(H12, H34567) 
     # finally, merge the first merged pair with the result of merging the rest
=> H1234567


Summary of running times

In the following time complexities[10] O(f) is an asymptotic upper bound and Θ(f) is an asymptotically tight bound (see Big O notation). Function names assume a min-heap.

Operation Binary[10] Binomial[10] Fibonacci[10] Pairing[11] Brodal[12][lower-alpha 1] Rank-pairing[14] Strict Fibonacci[15]
find-min Θ(1) Θ(log n) Θ(1) Θ(1) Θ(1) Θ(1) Θ(1)
delete-min Θ(log n) Θ(log n) O(log n)[lower-alpha 2] O(log n)[lower-alpha 2] O(log n) O(log n)[lower-alpha 2] O(log n)
insert O(log n) Θ(1)[lower-alpha 2] Θ(1) Θ(1) Θ(1) Θ(1) Θ(1)
decrease-key Θ(log n) Θ(log n) Θ(1)[lower-alpha 2] o(log n)[lower-alpha 2][lower-alpha 3] Θ(1) Θ(1)[lower-alpha 2] Θ(1)
merge Θ(n) O(log n)[lower-alpha 4] Θ(1) Θ(1) Θ(1) Θ(1) Θ(1)
  1. Brodal and Okasaki later describe a persistent variant with the same bounds except for decrease-key, which is not supported. Heaps with n elements can be constructed bottom-up in O(n).[13]
  2. 1 2 3 4 5 6 7 Amortized time.
  3. Bounded by [16][17]
  4. n is the size of the larger heap.

References

  1. 1 2 3 Fredman, Michael L.; Sedgewick, Robert; Sleator, Daniel D.; Tarjan, Robert E. (1986). "The pairing heap: a new form of self-adjusting heap" (PDF). Algorithmica. 1 (1): 111–129. doi:10.1007/BF01840439.
  2. Mehlhorn, Kurt; Sanders, Peter (2008). Algorithms and Data Structures: The Basic Toolbox (PDF). Springer. p. 231.
  3. 1 2 Iacono, John (2000). Improved upper bounds for pairing heaps (PDF). Proc. 7th Scandinavian Workshop on Algorithm Theory. Lecture Notes in Computer Science. 1851. Springer-Verlag. pp. 63–77. arXiv:1110.4428Freely accessible. doi:10.1007/3-540-44985-X_5. ISBN 978-3-540-67690-4.
  4. 1 2 Stasko, John T.; Vitter, Jeffrey S. (1987), "Pairing heaps: experiments and analysis", Communications of the ACM, 30 (3): 234–249, CiteSeerX 10.1.1.106.2988Freely accessible, doi:10.1145/214748.214759
  5. Fredman, Michael L. (1999). "On the efficiency of pairing heaps and related data structures" (PDF). Journal of the ACM. 46 (4): 473–501. doi:10.1145/320211.320214.
  6. 1 2 Pettie, Seth (2005), "Towards a final analysis of pairing heaps" (PDF), Proc. 46th Annual IEEE Symposium on Foundations of Computer Science, pp. 174–183, doi:10.1109/SFCS.2005.75, ISBN 0-7695-2468-0
  7. Elmasry, Amr (2009), "Pairing heaps with decrease cost" (PDF), Proc. 20th Annual ACM-SIAM Symposium on Discrete Algorithms, pp. 471–476, doi:10.1137/1.9781611973068.52
  8. 1 2 Larkin, Daniel H.; Sen, Siddhartha; Tarjan, Robert E. (2014), "A back-to-basics empirical study of priority queues", Proceedings of the 16th Workshop on Algorithm Engineering and Experiments, pp. 61–72, arXiv:1403.0252Freely accessible, doi:10.1137/1.9781611973198.7
  9. Moret, Bernard M. E.; Shapiro, Henry D. (1991), "An empirical analysis of algorithms for constructing a minimum spanning tree", Proc. 2nd Workshop on Algorithms and Data Structures, Lecture Notes in Computer Science, 519, Springer-Verlag, pp. 400–411, CiteSeerX 10.1.1.53.5960Freely accessible, doi:10.1007/BFb0028279, ISBN 3-540-54343-0
  10. 1 2 3 4 Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L. (1990). Introduction to Algorithms (1st ed.). MIT Press and McGraw-Hill. ISBN 0-262-03141-8.
  11. Iacono, John (2000), "Improved upper bounds for pairing heaps", Proc. 7th Scandinavian Workshop on Algorithm Theory, Lecture Notes in Computer Science, 1851, Springer-Verlag, pp. 63–77, doi:10.1007/3-540-44985-X_5
  12. Brodal, Gerth S. (1996), "Worst-Case Efficient Priority Queues", Proc. 7th Annual ACM-SIAM Symposium on Discrete Algorithms (PDF), pp. 52–58
  13. Goodrich, Michael T.; Tamassia, Roberto (2004). "7.3.6. Bottom-Up Heap Construction". Data Structures and Algorithms in Java (3rd ed.). pp. 338341.
  14. Haeupler, Bernhard; Sen, Siddhartha; Tarjan, Robert E. (2009). "Rank-pairing heaps" (PDF). SIAM J. Computing: 1463–1485.
  15. Brodal, G. S. L.; Lagogiannis, G.; Tarjan, R. E. (2012). Strict Fibonacci heaps (PDF). Proceedings of the 44th symposium on Theory of Computing - STOC '12. p. 1177. doi:10.1145/2213977.2214082. ISBN 9781450312455.
  16. Fredman, Michael Lawrence; Tarjan, Robert E. (1987). "Fibonacci heaps and their uses in improved network optimization algorithms" (PDF). Journal of the Association for Computing Machinery. 34 (3): 596615. doi:10.1145/28869.28874.
  17. Pettie, Seth (2005). "Towards a Final Analysis of Pairing Heaps" (PDF). Max Planck Institut für Informatik.

External links

This article is issued from Wikipedia - version of the 11/3/2016. The text is available under the Creative Commons Attribution/Share Alike but additional terms may apply for the media files.