Skew binomial heap

Last updated
Skew binomial heap
Type heap
Invented1996
Invented by Gerth Stølting Brodal and Chris Okasaki
Time complexity in big O notation
OperationAverageWorst case
InsertΘ(1)Θ(1)
Find-minΘ(1)
Delete-min O(log n)
Decrease-key O(log n)
Merge O(log n)
Space complexity

In computer science, a skew binomial heap (or skew binomial queue) is a data structure for priority queue operations. It is a variant of the binomial heap that supports constant-time insertion operations in the worst case, rather than amortized time.

Contents

Motivation

Just as binomial heaps are based on the binary number system, skew binary heaps are based on the skew binary number system. [1] Ordinary binomial heaps suffer from worst case logarithmic complexity for insertion, because a carry operation may cascade, analogous to binary addition. Skew binomial heaps are based on the skew binary number system, where the th digit (zero-indexed) represents , instead of . Digits are either 0 or 1, except the lowest non-zero digit, which may be 2. An advantage of this system is that at most one carry operation is needed. For example, 60 is represented as 11200 in skew binary (31 + 15 + 7 + 7), and adding 1 produces 12000 (31 + 15 + 15). Since the next higher digit is guaranteed not to be 2, a carry is performed at most once. This analogy is applied to the insertion operation by introducing ternary (skew) links, which link 3 trees together. This allows the insertion operation to execute in constant time.

Structure

Skew binomial heap containing numbers 1 to 19, showing trees of ranks 0, 1, 2, and 3 constructed from various types of links Skew binomial heap.svg
Skew binomial heap containing numbers 1 to 19, showing trees of ranks 0, 1, 2, and 3 constructed from various types of links
Simple, type a skew, and type b skew links Skew binomial heap links.svg
Simple, type a skew, and type b skew links

A skew binomial heap is a forest of skew binomial trees, which are defined inductively:

When performing any link, the tree with the smallest key always becomes the root. Additionally, we impose the invariant that there may be only one tree of each rank, except the lowest rank which may have up to two.

The following OCaml code demonstrates the linking operations:

type'aheap='atreelistand'atree=Treeof'a*int*'atreelistletrank(Tree(_,r,_))=rletsimple_link(Tree(k1,r,c1)ast1)(Tree(k2,r,c2)ast2)=ifk1<=k2thenTree(k1,r+1,t2::c1)elseTree(k2,r+1,t1::c2)letskew_linkk1(Tree(k2,r,c2)ast2)(Tree(k3,r,c3)ast3)=ifk1<=k2&&k1<=k3then(* type A *)Tree(k1,r+1,[t2;t3])else(* type B *)lett1=Tree(k1,0,[])inifk2<=k3thenTree(k2,r+1,t1::t3::c2)elseTree(k3,r+1,t1::t2::c3)

From these properties, it can be deduced that the root of a rank skew binomial tree has up to children. The number of nodes in a skew binomial tree of rank is also bounded by . Since trees of the same rank may have different numbers of nodes, there may be more than one way to distribute the ranks in the heap.

These constructions may be seen as a generalisation of binary trees and binomial trees. A skew binomial tree constructed using only simple links is an ordinary binomial tree, and using only type A skew links results in a perfectly balanced binary tree.

Operations

Find-min

Search the list of roots to find the node containing the minimum key. This takes time.

In an imperative setting, one can maintain a pointer to the root containing the minimum key, allowing access in time. This pointer must be updated after every operation, adding only a constant overhead in time complexity.

In a functional setting without random access to nodes, one can instead represent the heap as a single tree with skew binomial trees as its children. The root of this tree is the minimum of the heap, allowing access. Note that this tree will not necessarily be a skew binomial tree itself. The other operations must be modified to deal with this single tree. This concept of a global root is used in the optimizations described below, albeit slightly differently.

Merge

To merge two skew binomial heaps together, first eliminate any duplicate rank trees in each heap by performing simple links. Then, merge the heaps in the same fashion as ordinary binomial heaps, which is similar to binary addition. Trees with the same ranks are linked with a simple link, and a 'carry' tree is passed upwards if necessary. Because the rank of trees in each heap is now unique, at most three trees of the same rank are considered, which is sufficient to establish a bound.

letrecunique=function|t1::t2::tswhenrankt1=rankt2->unique(simple_linkt1t2::ts)|ts->tsletrecmerge_uniqh1h2=matchh1,h2with|h1,[]->h1|[],h2->h2|t1::ts1,t2::ts2->ifrankt1<rankt2thent1::merge_uniqts1h2elseifrankt1>rankt2thent2::merge_uniqh1ts2elseunique(simple_linkt1t2::merge_uniqts1ts2)letmergeh1h2=merge_uniq(uniqueh1)(uniqueh2)

Insert

Create a skew binomial tree of rank 0 (a singleton node), containing the key to be inserted. The smallest two trees in the heap are then considered:

As up to one link is performed, this operation executes in worst case time, improving on the binomial heap which relies on amortized analysis for its bound, with a worst case of .

letinsertk=function|t2::t3::tswhenrankt2=rankt3->skew_linkkt2t3::ts|ts->Tree(k,0,[])::ts

Delete-min

Find and discard the node containing the minimum key. This node must be the root of a tree. Divide its children into two groups, those with rank 0, and those with rank > 0. Note that there may be more than two children with rank 0, due to skew links. The children whose rank > 0 form a valid skew binomial heap, as they are already ordered, and have no duplicates. Merging these children into the heap takes time. Afterwards, reinsert each of the rank 0 children into the heap at a cost of each. The total time required is .

Decrease-key

This operation is unchanged from binomial heaps. Decreasing the key of a node may cause it to be smaller than its parent. Repeatedly exchange it with its parent until the minimum-heap property is satisfied, at a cost of time complexity. This operation requires a pointer to the node containing the key in question, and is easiest done in an imperative setting.

Optimizations

Brodal and Okasaki showed how the time complexity of the merge operation can be reduced to , by applying the 'bootstrapping' technique of Buchsbaum and Tarjan. [2]

Let the type of a primitive skew binomial heap containing elements of type be . Instead of the forest of trees representation described above, we mainintain a single tree with a global root as its minimum.

Let the type of a rooted skew binomial heap be

,

that is, a pair containing an element of type and a primitive heap of rooted heaps.

Finally, we define the type of a bootstrapped heap by enclosing rooted heaps in an option type:

which permits the empty heap.

The operations on this bootstrapped heap are redefined accordingly. In the following OCaml code, the prime symbol ' denotes operations for bootstrapped heaps.

type'abootstrapped=|Empty|Rootof'arootedletfind_min'(Root(k,h))=kletmerge'bh1bh2=matchbh1,bh2with|_,Empty->bh1|Empty,_->bh2|Root(k1,h1),Root(k2,h2)->ifk1<=k2thenRoot(k1,insertbh2h1)elseRoot(k2,insertbh1h2)letinsert'kh=merge'(Root(k,[]))hletdelete_min'(Root(x,h))=letRoot(y,h1)=find_minhinleth2=delete_minhinRoot(y,mergeh1h2)

The new merge operation uses only insert operations on primitive heaps. Thus, it executes in time. This technique can be applied to any priority queue with constant time insertion, and logarithmic merging.

Summary of running times

Here are time complexities [3] of various heap data structures. The abbreviation am. indicates that the given complexity is amortized, otherwise it is a worst-case complexity. For the meaning of "O(f)" and "Θ(f)" see Big O notation. Names of operations assume a min-heap.

Operationfind-mindelete-mindecrease-keyinsertmeldmake-heap [a]
Binary [3] Θ(1)Θ(log n)Θ(log n)Θ(log n)Θ(n)Θ(n)
Skew [4] Θ(1)O(log n) am.O(log n) am.O(log n) am.O(log n) am.Θ(n) am.
Leftist [5] Θ(1)Θ(log n)Θ(log n)Θ(log n)Θ(log n)Θ(n)
Binomial [3] [7] Θ(1)Θ(log n)Θ(log n)Θ(1) am.Θ(log n) [b] Θ(n)
Skew binomial [8] Θ(1)Θ(log n)Θ(log n)Θ(1)Θ(log n) [b] Θ(n)
2–3 heap [10] Θ(1)O(log n) am.Θ(1)Θ(1) am.O(log n) [b] Θ(n)
Bottom-up skew [4] Θ(1)O(log n) am.O(log n) am.Θ(1) am.Θ(1) am.Θ(n) am.
Pairing [11] Θ(1)O(log n) am.o(log n) am. [c] Θ(1)Θ(1)Θ(n)
Rank-pairing [14] Θ(1)O(log n) am.Θ(1) am.Θ(1)Θ(1)Θ(n)
Fibonacci [3] [15] Θ(1)O(log n) am.Θ(1) am.Θ(1)Θ(1)Θ(n)
Strict Fibonacci [16] [d] Θ(1)Θ(log n)Θ(1)Θ(1)Θ(1)Θ(n)
Brodal [17] [d] Θ(1)Θ(log n)Θ(1)Θ(1)Θ(1)Θ(n) [18]
  1. make-heap is the operation of building a heap from a sequence of n unsorted elements. It can be done in Θ(n) time whenever meld runs in O(log n) time (where both complexities can be amortized). [4] [5] Another algorithm achieves Θ(n) for binary heaps. [6]
  2. 1 2 3 For persistent heaps (not supporting decrease-key), a generic transformation reduces the cost of meld to that of insert, while the new cost of delete-min is the sum of the old costs of delete-min and meld. [9] Here, it makes meld run in Θ(1) time (amortized, if the cost of insert is) while delete-min still runs in O(log n). Applied to skew binomial heaps, it yields Brodal-Okasaki queues, persistent heaps with optimal worst-case complexities. [8]
  3. Lower bound of [12] upper bound of [13]
  4. 1 2 Brodal queues and strict Fibonacci heaps achieve optimal worst-case complexities for heaps. They were first described as imperative data structures. The Brodal-Okasaki queue is a persistent data structure achieving the same optimum, except that decrease-key is not supported.

Related Research Articles

<span class="mw-page-title-main">AVL tree</span> Self-balancing binary search tree

In computer science, an AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Lookup, insertion, and deletion all take O(log n) time in both the average and worst cases, where is the number of nodes in the tree prior to the operation. Insertions and deletions may require the tree to be rebalanced by one or more tree rotations.

<span class="mw-page-title-main">Heap (data structure)</span> Computer science data structure

In computer science, a heap is a tree-based data structure that satisfies the heap property: In a max heap, for any given node C, if P is a parent node of C, then the key of P is greater than or equal to the key of C. In a min heap, the key of P is less than or equal to the key of C. The node at the "top" of the heap is called the root node.

In computer science, a priority queue is an abstract data type similar to a regular queue or stack abstract data type. Each element in a priority queue has an associated priority. In a priority queue, elements with high priority are served before elements with low priority. In some implementations, if two elements have the same priority, they are served in the same order in which they were enqueued. In other implementations, the order of elements with the same priority is undefined.

A splay tree is a binary search tree with the additional property that recently accessed elements are quick to access again. Like self-balancing binary search trees, a splay tree performs basic operations such as insertion, look-up and removal in O(log n) amortized time. For random access patterns drawn from a non-uniform random distribution, their amortized time can be faster than logarithmic, proportional to the entropy of the access pattern. For many patterns of non-random operations, also, splay trees can take better than logarithmic time, without requiring advance knowledge of the pattern. According to the unproven dynamic optimality conjecture, their performance on all access patterns is within a constant factor of the best possible performance that could be achieved by any other self-adjusting binary search tree, even one selected to fit that pattern. The splay tree was invented by Daniel Sleator and Robert Tarjan in 1985.

<span class="mw-page-title-main">Dijkstra's algorithm</span> Algorithm for finding shortest paths

Dijkstra's algorithm is an algorithm for finding the shortest paths between nodes in a weighted graph, which may represent, for example, road networks. It was conceived by computer scientist Edsger W. Dijkstra in 1956 and published three years later.

<span class="mw-page-title-main">Binary heap</span> Variant of heap data structure

A binary heap is a heap data structure that takes the form of a binary tree. Binary heaps are a common way of implementing priority queues. The binary heap was introduced by J. W. J. Williams in 1964 as a data structure for implementing heapsort.

<span class="mw-page-title-main">Treap</span> Random search tree data structure

In computer science, the treap and the randomized binary search tree are two closely related forms of binary search tree data structures that maintain a dynamic set of ordered keys and allow binary searches among the keys. After any sequence of insertions and deletions of keys, the shape of the tree is a random variable with the same probability distribution as a random binary tree; in particular, with high probability its height is proportional to the logarithm of the number of keys, so that each search, insertion, or deletion operation takes logarithmic time to perform.

In computer science, a binomial heap is a data structure that acts as a priority queue. It is an example of a mergeable heap, as it supports merging two heaps in logarithmic time. It is implemented as a heap similar to a binary heap but using a special tree structure that is different from the complete binary trees used by binary heaps. Binomial heaps were invented in 1978 by Jean Vuillemin.

In computer science, a Fibonacci heap is a data structure for priority queue operations, consisting of a collection of heap-ordered trees. It has a better amortized running time than many other priority queue data structures including the binary heap and binomial heap. Michael L. Fredman and Robert E. Tarjan developed Fibonacci heaps in 1984 and published them in a scientific journal in 1987. Fibonacci heaps are named after the Fibonacci numbers, which are used in their running time analysis.

In computer science, a 2–3 heap is a data structure, a variation on the heap, designed by Tadao Takaoka in 1999. The structure is similar to the Fibonacci heap, and borrows from the 2–3 tree.

In computer science, a disjoint-set data structure, also called a union–find data structure or merge–find set, is a data structure that stores a collection of disjoint (non-overlapping) sets. Equivalently, it stores a partition of a set into disjoint subsets. It provides operations for adding new sets, merging sets, and finding a representative member of a set. The last operation makes it possible to find out efficiently if any two elements are in the same or different sets.

In computer science, a leftist tree or leftist heap is a priority queue implemented with a variant of a binary heap. Every node x has an s-value which is the distance to the nearest leaf in subtree rooted at x. In contrast to a binary heap, a leftist tree attempts to be very unbalanced. In addition to the heap property, leftist trees are maintained so the right descendant of each node has the lower s-value.

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. 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, and support the following operations :

A skew heap is a heap data structure implemented as a binary tree. Skew heaps are advantageous because of their ability to merge more quickly than binary heaps. In contrast with binary heaps, there are no structural constraints, so there is no guarantee that the height of the tree is logarithmic. Only two conditions must be satisfied:

In computer science, weight-balanced binary trees (WBTs) are a type of self-balancing binary search trees that can be used to implement dynamic sets, dictionaries (maps) and sequences. These trees were introduced by Nievergelt and Reingold in the 1970s as trees of bounded balance, or BB[α] trees. Their more common name is due to Knuth.

The d-ary heap or d-heap is a priority queue data structure, a generalization of the binary heap in which the nodes have d children instead of 2. Thus, a binary heap is a 2-heap, and a ternary heap is a 3-heap. According to Tarjan and Jensen et al., d-ary heaps were invented by Donald B. Johnson in 1975.

In computer science, the Brodal queue is a heap/priority queue structure with very low worst case time bounds: for insertion, find-minimum, meld and decrease-key and for delete-minimum and general deletion. They are the first heap variant to achieve these bounds without resorting to amortization of operational costs. Brodal queues are named after their inventor Gerth Stølting Brodal.

In computer science, join-based tree algorithms are a class of algorithms for self-balancing binary search trees. This framework aims at designing highly-parallelized algorithms for various balanced binary search trees. The algorithmic framework is based on a single operation join. Under this framework, the join operation captures all balancing criteria of different balancing schemes, and all other functions join have generic implementation across different balancing schemes. The join-based algorithms can be applied to at least four balancing schemes: AVL trees, red–black trees, weight-balanced trees and treaps.

This is a comparison of the performance of notable data structures, as measured by the complexity of their logical operations. For a more comprehensive listing of data structures, see List of data structures.

In computer science, a strict Fibonacci heap is a priority queue data structure with low worst case time bounds. It matches the amortized time bounds of the Fibonacci heap in the worst case. To achieve these time bounds, strict Fibonacci heaps maintain several invariants by performing restoring transformations after every operation. These transformations can be done in constant time by using auxiliary data structures to track invariant violations, and the pigeonhole principle guarantees that these can be fixed. Strict Fibonacci heaps were invented in 2012 by Gerth S. Brodal, George Lagogiannis, and Robert E. Tarjan.

References

  1. Brodal, Gerth Stølting; Okasaki, Chris (November 1996), "Optimal purely functional priority queues", Journal of Functional Programming, 6 (6): 839–857, doi: 10.1017/s095679680000201x
  2. Buchsbaum, A.L.; Tarjan, R.E. (May 1995). "Confluently Persistent Deques via Data-Structural Bootstrapping". Journal of Algorithms. 18 (3): 513–547. doi:10.1006/jagm.1995.1020. ISSN   0196-6774.
  3. 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.
  4. 1 2 3 Sleator, Daniel Dominic; Tarjan, Robert Endre (February 1986). "Self-Adjusting Heaps". SIAM Journal on Computing . 15 (1): 52–69. CiteSeerX   10.1.1.93.6678 . doi:10.1137/0215004. ISSN   0097-5397.
  5. 1 2 Tarjan, Robert (1983). "3.3. Leftist heaps". Data Structures and Network Algorithms. pp. 38–42. doi:10.1137/1.9781611970265. ISBN   978-0-89871-187-5.
  6. Hayward, Ryan; McDiarmid, Colin (1991). "Average Case Analysis of Heap Building by Repeated Insertion" (PDF). J. Algorithms. 12: 126–153. CiteSeerX   10.1.1.353.7888 . doi:10.1016/0196-6774(91)90027-v. Archived from the original (PDF) on 2016-02-05. Retrieved 2016-01-28.
  7. "Binomial Heap | Brilliant Math & Science Wiki". brilliant.org. Retrieved 2019-09-30.
  8. 1 2 Brodal, Gerth Stølting; Okasaki, Chris (November 1996), "Optimal purely functional priority queues", Journal of Functional Programming, 6 (6): 839–857, doi: 10.1017/s095679680000201x
  9. Okasaki, Chris (1998). "10.2. Structural Abstraction". Purely Functional Data Structures (1st ed.). pp. 158–162. ISBN   9780521631242.
  10. Takaoka, Tadao (1999), Theory of 2–3 Heaps (PDF), p. 12
  11. Iacono, John (2000), "Improved upper bounds for pairing heaps", Proc. 7th Scandinavian Workshop on Algorithm Theory (PDF), Lecture Notes in Computer Science, vol. 1851, Springer-Verlag, pp. 63–77, arXiv: 1110.4428 , CiteSeerX   10.1.1.748.7812 , doi:10.1007/3-540-44985-X_5, ISBN   3-540-67690-2
  12. Fredman, Michael Lawrence (July 1999). "On the Efficiency of Pairing Heaps and Related Data Structures" (PDF). Journal of the Association for Computing Machinery . 46 (4): 473–501. doi:10.1145/320211.320214.
  13. Pettie, Seth (2005). Towards a Final Analysis of Pairing Heaps (PDF). FOCS '05 Proceedings of the 46th Annual IEEE Symposium on Foundations of Computer Science. pp. 174–183. CiteSeerX   10.1.1.549.471 . doi:10.1109/SFCS.2005.75. ISBN   0-7695-2468-0.
  14. Haeupler, Bernhard; Sen, Siddhartha; Tarjan, Robert E. (November 2011). "Rank-pairing heaps" (PDF). SIAM J. Computing. 40 (6): 1463–1485. doi:10.1137/100785351.
  15. Fredman, Michael Lawrence; Tarjan, Robert E. (July 1987). "Fibonacci heaps and their uses in improved network optimization algorithms" (PDF). Journal of the Association for Computing Machinery . 34 (3): 596–615. CiteSeerX   10.1.1.309.8927 . doi:10.1145/28869.28874.
  16. Brodal, Gerth Stølting; Lagogiannis, George; Tarjan, Robert E. (2012). Strict Fibonacci heaps (PDF). Proceedings of the 44th symposium on Theory of Computing - STOC '12. pp. 1177–1184. CiteSeerX   10.1.1.233.1740 . doi:10.1145/2213977.2214082. ISBN   978-1-4503-1245-5.
  17. Brodal, Gerth S. (1996), "Worst-Case Efficient Priority Queues" (PDF), Proc. 7th Annual ACM-SIAM Symposium on Discrete Algorithms, pp. 52–58
  18. Goodrich, Michael T.; Tamassia, Roberto (2004). "7.3.6. Bottom-Up Heap Construction". Data Structures and Algorithms in Java (3rd ed.). pp. 338–341. ISBN   0-471-46983-1.