In
computer science
Computer science is the study of computation, information, and automation. Computer science spans Theoretical computer science, theoretical disciplines (such as algorithms, theory of computation, and information theory) to Applied science, ...
, heapsort is an efficient,
comparison-based sorting algorithm
In computer science, a sorting algorithm is an algorithm that puts elements of a List (computing), list into an Total order, order. The most frequently used orders are numerical order and lexicographical order, and either ascending or descending ...
that reorganizes an input array into a
heap (a data structure where each node is greater than its children) and then repeatedly removes the largest node from that heap, placing it at the end of the array in a similar manner to
Selection sort
In computer science, selection sort is an in-place comparison sorting algorithm. It has a O(''n''2) time complexity, which makes it inefficient on large lists, and generally performs worse than the similar insertion sort. Selection sort is note ...
.
Although somewhat slower in practice on most machines than a well-implemented
quicksort
Quicksort is an efficient, general-purpose sorting algorithm. Quicksort was developed by British computer scientist Tony Hoare in 1959 and published in 1961. It is still a commonly used algorithm for sorting. Overall, it is slightly faster than ...
, it has the advantages of very simple implementation and a more favorable worst-case runtime. Most real-world quicksort variants include an implementation of heapsort as a fallback should they detect that quicksort is becoming degenerate. Heapsort is an
in-place algorithm
In computer science, an in-place algorithm is an algorithm that operates directly on the input data structure without requiring extra space proportional to the input size. In other words, it modifies the input in place, without creating a separa ...
, but it is not a
stable sort
In computer science, a sorting algorithm is an algorithm that puts elements of a list into an order. The most frequently used orders are numerical order and lexicographical order, and either ascending or descending. Efficient sorting is importa ...
.
Heapsort was invented by
J. W. J. Williams in 1964. The paper also introduced the
binary heap
A binary heap is a heap (data structure), 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 fo ...
as a useful data structure in its own right.
In the same year,
Robert W. Floyd
Robert W. Floyd (born Robert Willoughby Floyd; June 8, 1936 – September 25, 2001) was an American computer scientist. His contributions include the design of the Floyd–Warshall algorithm (independently of Stephen Warshall), which efficientl ...
published an improved version that could sort an array in-place, continuing his earlier research into the
treesort algorithm.
Overview
The heapsort algorithm can be divided into two phases: heap construction, and heap extraction.
The heap is an
implicit data structure
In computer science, an implicit data structure or space-efficient data structure is a data structure that stores very little information other than the main or required data: a data structure that requires low overhead. They are called "implicit" ...
which takes no space beyond the array of objects to be sorted; the array is interpreted as a
complete binary tree
In computer science, a binary tree is a Tree (data structure), tree data structure in which each node has at most two child node, children, referred to as the ''left child'' and the ''right child''. That is, it is a m-ary tree, ''k''-ary tree wi ...
where each array element is a node and each node's parent and child links are defined by simple arithmetic on the array indexes. For a zero-based array, the root node is stored at index 0, and the nodes linked to node are
iLeftChild(i) = 2⋅i + 1
iRightChild(i) = 2⋅i + 2
iParent(i) = floor((i−1) / 2)
where the
floor function
In mathematics, the floor function is the function that takes as input a real number , and gives as output the greatest integer less than or equal to , denoted or . Similarly, the ceiling function maps to the least integer greater than or eq ...
rounds down to the preceding integer. For a more detailed explanation, see .
This binary tree is a max-heap when each node is greater than or equal to both of its children. Equivalently, each node is less than or equal to its parent. This rule, applied throughout the tree, results in the maximum node being located at the root of the tree.
In the first phase, a heap is built out of the data (see ).
In the second phase, the heap is converted to a sorted array by repeatedly removing the largest element from the heap (the root of the heap), and placing it at the end of the array. The heap is updated after each removal to maintain the heap property. Once all objects have been removed from the heap, the result is a sorted array.
Heapsort is normally performed in place. During the first phase, the array is divided into an unsorted prefix and a heap-ordered suffix (initially empty). Each step shrinks the prefix and expands the suffix. When the prefix is empty, this phase is complete. During the second phase, the array is divided into a heap-ordered prefix and a sorted suffix (initially empty). Each step shrinks the prefix and expands the suffix. When the prefix is empty, the array is sorted.
Algorithm
The heapsort algorithm begins by rearranging the array into a binary max-heap. The algorithm then repeatedly swaps the root of the heap (the greatest element remaining in the heap) with its last element, which is then declared to be part of the sorted suffix. Then the heap, which was damaged by replacing the root, is repaired so that the greatest element is again at the root. This repeats until only one value remains in the heap.
The steps are:
# Call the function on the array. This builds a heap from an array in operations.
# Swap the first element of the array (the largest element in the heap) with the final element of the heap. Decrease the considered range of the heap by one.
# Call the function on the array to move the new first element to its correct place in the heap.
# Go back to step (2) until the remaining array is a single element.
The operation is run once, and is in performance. The function is called times and requires work each time, due to its traversal starting from the root node. Therefore, the performance of this algorithm is .
The heart of the algorithm is the function. This constructs binary heaps out of smaller heaps, and may be thought of in two equivalent ways:
* given two binary heaps, and a shared parent node which is not part of either heap, merge them into a single larger binary heap; or
* given a "damaged" binary heap, where the max-heap property (no child is greater than its parent) holds everywhere ''except'' possibly between the root node and its children, repair it to produce an undamaged heap.
To establish the max-heap property at the root, up to three nodes must be compared (the root and its two children), and the greatest must be made the root. This is most easily done by finding the greatest child, then comparing that child to the root. There are three cases:
# If there are no children (the two original heaps are empty), the heap property trivially holds, and no further action is required.
# If root is greater than or equal to the greatest child, the heap property holds and likewise, no further action is required.
# If the root is less than the greatest child, exchange the two nodes. The heap property now holds at the newly promoted node (it is greater than or equal to both of its children, and in fact greater than any descendant), but may be violated between the newly demoted ex-root and its new children. To correct this, repeat the operation on the subtree rooted at the newly demoted ex-root.
The number of iterations in any one call is bounded by the height of the tree, which is .
Pseudocode
The following is a simple way to implement the algorithm in
pseudocode
In computer science, pseudocode is a description of the steps in an algorithm using a mix of conventions of programming languages (like assignment operator, conditional operator, loop) with informal, usually self-explanatory, notation of actio ...
. Arrays are
zero-based and is used to exchange two elements of the array. Movement 'down' means from the root towards the leaves, or from lower indices to higher. Note that during the sort, the largest element is at the root of the heap at , while at the end of the sort, the largest element is in .
procedure heapsort(a, count) is
input: an unordered array ''a'' of length ''count''
''(Build the heap in array a so that largest value is at the root)''
heapify(a, count)
''(The following loop maintains the
invariants that a
:end−1is a heap, and''
''every element a
nd:count−1beyond end is greater than everything before it,''
''i.e. a
nd:count−1is in sorted order.)''
end ← count
while end > 1 do
''(the heap size is reduced by one)''
end ← end − 1
''(a
is the root and largest value. The swap moves it in front of the sorted elements.)''
swap(a
nd a
''(the swap ruined the heap property, so restore it)''
siftDown(a, 0, end)
The sorting routine uses two subroutines, and . The former is the common in-place heap construction routine, while the latter is a common subroutine for implementing .
''(Put elements of 'a' in heap order, in-place)''
procedure heapify(a, count) is
''(start is initialized to the first leaf node)''
''(the last element in a 0-based array is at index count-1; find the parent of that element)''
start ← iParent(count-1) + 1
while start > 0 do
''(go to the last non-heap node)''
start ← start − 1
''(sift down the node at index 'start' to the proper place such that all nodes below''
'' the start index are in heap order)''
siftDown(a, start, count)
''(after sifting down the root all nodes/elements are in heap order)''
''(Repair the heap whose root element is at index 'start', assuming the heaps rooted at its children are valid)''
procedure siftDown(a, root, end) is
while iLeftChild(root) < end do ''(While the root has at least one child)''
child ← iLeftChild(root) ''(Left child of root)''
''(If there is a right child and that child is greater)''
if child+1 < end and a
hild
Hild or Hildr may refer to:
* Hildr or Hild is one of the Valkyries in Norse mythology, a personification of battle
* Hild or Hilda of Whitby is a Christian saint who was a British abbess and nun in the Middle Ages
* Hild (Oh My Goddess!), the ult ...
< a
hild+1then
child ← child + 1
if a
oot< a
hild
Hild or Hildr may refer to:
* Hildr or Hild is one of the Valkyries in Norse mythology, a personification of battle
* Hild or Hilda of Whitby is a Christian saint who was a British abbess and nun in the Middle Ages
* Hild (Oh My Goddess!), the ult ...
then
swap(a
oot a
hild
Hild or Hildr may refer to:
* Hildr or Hild is one of the Valkyries in Norse mythology, a personification of battle
* Hild or Hilda of Whitby is a Christian saint who was a British abbess and nun in the Middle Ages
* Hild (Oh My Goddess!), the ult ...
root ← child ''(repeat to continue sifting down the child now)''
else
''(The root holds the largest element. Since we may assume the heaps rooted''
'' at the children are valid, this means that we are done.)''
return
The procedure operates by building small heaps and repeatedly merging them using . It starts with the leaves, observing that they are trivial but valid heaps by themselves, and then adds parents. Starting with element and working backwards, each internal node is made the root of a valid heap by sifting down. The last step is sifting down the first element, after which the entire array obeys the heap property.
To see that this takes time, count the worst-case number of iterations. The last half of the array requires zero iterations, the preceding quarter requires at most one iteration, the eighth before that requires at most two iterations, the sixteenth before that requires at most three, and so on.
Looked at a different way, if we assume every call requires the maximum number of iterations, the first half of the array requires one iteration, the first quarter requires one more (total 2), the first eighth requires yet another (total 3), and so on.
This totals , where the infinite sum is a well-known
geometric series
In mathematics, a geometric series is a series (mathematics), series summing the terms of an infinite geometric sequence, in which the ratio of consecutive terms is constant. For example, 1/2 + 1/4 + 1/8 + 1/16 + ⋯, the series \tfrac12 + \tfrac1 ...
whose sum is , thus the product is simply .
The above is an approximation. The exact worst-case number of comparisons during the heap-construction phase of heapsort is known to be equal to , where is the
number of 1 bits in the binary representation of and is the
number of trailing 0 bits.
Standard implementation
Although it is convenient to think of the two phases separately, most implementations combine the two, allowing a single instance of to be
expanded inline. Two variables (here, and ) keep track of the bounds of the heap area. The portion of the array before is unsorted, while the portion beginning at is sorted. Heap construction decreases until it is zero, after which heap extraction decreases until it is 1 and the array is entirely sorted.
procedure heapsort(a, count) is
input: an unordered array ''a'' of length ''count''
start ← floor(count/2)
end ← count
while end > 1 do
if start > 0 then ''(Heap construction)''
start ← start − 1
else ''(Heap extraction)''
end ← end − 1
swap(a
nd a
''(The following is siftDown(a, start, end))''
root ← start
while iLeftChild(root) < end do
child ← iLeftChild(root)
''(If there is a right child and that child is greater)''
if child+1 < end and a
hild
Hild or Hildr may refer to:
* Hildr or Hild is one of the Valkyries in Norse mythology, a personification of battle
* Hild or Hilda of Whitby is a Christian saint who was a British abbess and nun in the Middle Ages
* Hild (Oh My Goddess!), the ult ...
< a
hild+1then
child ← child + 1
if a
oot< a
hild
Hild or Hildr may refer to:
* Hildr or Hild is one of the Valkyries in Norse mythology, a personification of battle
* Hild or Hilda of Whitby is a Christian saint who was a British abbess and nun in the Middle Ages
* Hild (Oh My Goddess!), the ult ...
then
swap(a
oot a
hild
Hild or Hildr may refer to:
* Hildr or Hild is one of the Valkyries in Norse mythology, a personification of battle
* Hild or Hilda of Whitby is a Christian saint who was a British abbess and nun in the Middle Ages
* Hild (Oh My Goddess!), the ult ...
root ← child ''(repeat to continue sifting down the child now)''
else
break ''(return to outer loop)''
Variations
Williams' heap construction
The description above uses Floyd's improved heap-construction algorithm, which operates in time and uses the same primitive as the heap-extraction phase. Although this algorithm, being both faster and simpler to program, is used by all practical heapsort implementations, Williams' original algorithm may be easier to understand, and is needed to implement a more general binary heap
priority queue
In computer science, a priority queue is an abstract data type similar to a regular queue (abstract data type), queue or stack (abstract data type), stack abstract data type.
In a priority queue, each element has an associated ''priority'', which ...
.
Rather than merging many small heaps, Williams' algorithm maintains one single heap at the front of the array and repeatedly appends an additional element using a primitive. Being at the end of the array, the new element is a leaf and has no children to worry about, but may violate the heap property by being greater than its parent. In this case, exchange it with its parent and repeat the test until the parent is greater or there is no parent (we have reached the root). In pseudocode, this is:
procedure siftUp(a, end) is
input: ''a is the array, which heap-ordered up to end-1.''
''end is the node to sift up.''
while end > 0
parent := iParent(end)
if a
arent Arent can refer to:
* Arent (given name)
* Arent (surname)
* Arent Fox Schiff, American law firm and lobbying group
See also
* Angela Ahrendts (born 1960), US businesswoman
* Arent Arentsz (1585–1631), Dutch painter
* Ahrén
* Ahrend
* Ahre ...
< a
ndthen ''(out of max-heap order)''
swap(a
arent Arent can refer to:
* Arent (given name)
* Arent (surname)
* Arent Fox Schiff, American law firm and lobbying group
See also
* Angela Ahrendts (born 1960), US businesswoman
* Arent Arentsz (1585–1631), Dutch painter
* Ahrén
* Ahrend
* Ahre ...
a
nd
end := parent ''(continue sifting up)''
else
return
procedure heapify(a, count) is
''(start with a trivial single-element heap)''
end := 1
while end < count
''(sift up the node at index end to the proper place such that''
'' all nodes above the end index are in heap order)''
siftUp(a, end)
end := end + 1
''(after sifting up the last node all nodes are in heap order)''

To understand why this algorithm can take asymptotically more time to build a heap ( vs. worst case), note that in Floyd's algorithm, almost all the calls to operations apply to very ''small'' heaps. Half the heaps are height-1 trivial heaps and can be skipped entirely, half of the remainder are height-2, and so on. Only two calls are on heaps of size , and only one operation is done on the full -element heap. The overall average operation takes time.
In contrast, in Williams' algorithm most of the calls to are made on ''large'' heaps of height . Half of the calls are made with a heap size of or more, three-quarters are made with a heap size of or more, and so on. Although the ''average'' number of steps is similar to Floyd's technique, pre-sorted input will cause the worst case: each added node is sifted up to the root, so the average call to will require approximately iterations.
Because it is dominated by the second heap-extraction phase, the heapsort algorithm itself has time complexity using either version of heapify.
Bottom-up heapsort
Bottom-up heapsort is a variant that reduces the number of comparisons required by a significant factor. While ordinary "top-down" heapsort requires comparisons worst-case and on average, the bottom-up variant requires comparisons on average, and in the worst case.
If comparisons are cheap (e.g. integer keys) then the difference is unimportant, as top-down heapsort compares values that have already been loaded from memory. If, however, comparisons require a
function call
In computer programming, a function (also procedure, method, subroutine, routine, or subprogram) is a callable unit of software logic that has a well-defined interface and behavior and can be invoked multiple times.
Callable units provide a p ...
or other complex logic, then bottom-up heapsort is advantageous.
This is accomplished by using a more elaborate procedure. The change improves the linear-time heap-building phase slightly, but is more significant in the second phase. Like top-down heapsort, each iteration of the second phase extracts the top of the heap, , and fills the gap it leaves with , then sifts this latter element down the heap. But this element came from the lowest level of the heap, meaning it is one of the smallest elements in the heap, so the sift-down will likely take many steps to move it back down.
In top-down heapsort, each step of requires two comparisons, to find the minimum of three elements: the new node and its two children.
Bottom-up heapsort conceptually replaces the root with a value of −∞ and sifts it down using only one comparison per level (since no child can possibly be less than −∞) until the leaves are reached, then replaces the −∞ with the correct value and sifts it ''up'' (again, using one comparison per level) until the correct position is found.
This places the root in the same location as top-down , but fewer comparisons are required to find that location. For any single operation, the bottom-up technique is advantageous if the number of downward movements is at least of the height of the tree (when the number of comparisons is times the height for both techniques), and it turns out that this is more than true on average, even for worst-case inputs.
[ Also available as ]
A naïve implementation of this conceptual algorithm would cause some redundant data copying, as the sift-up portion undoes part of the sifting down. A practical implementation searches downward for a leaf where −∞ ''would'' be placed, then upward for where the root ''should'' be placed. Finally, the upward traversal continues to the root's starting position, performing no more comparisons but exchanging nodes to complete the necessary rearrangement. This optimized form performs the same number of exchanges as top-down .
Because it goes all the way to the bottom and then comes back up, it is called heapsort with bounce by some authors.
function leafSearch(a, i, end) is
j ← i
while iRightChild(j) < end do
''(Determine which of j's two children is the greater)''
if a
RightChild(j)> a
LeftChild(j)then
j ← iRightChild(j)
else
j ← iLeftChild(j)
''(At the last level, there might be only one child)''
if iLeftChild(j) < end then
j ← iLeftChild(j)
return j
The return value of the
leafSearch
is used in the modified
siftDown
routine:
procedure siftDown(a, i, end) is
j ← leafSearch(a, i, end)
while a
> a
do
j ← iParent(j)
while j > i do
swap(a
a
j ← iParent(j)
Bottom-up heapsort was announced as beating quicksort (with median-of-three pivot selection) on arrays of size ≥16000.
A 2008 re-evaluation of this algorithm showed it to be no faster than top-down heapsort for integer keys, presumably because modern
branch prediction
In computer architecture, a branch predictor is a digital circuit that tries to guess which way a branch (e.g., an if–then–else structure) will go before this is known definitively. The purpose of the branch predictor is to improve the flow ...
nullifies the cost of the predictable comparisons that bottom-up heapsort manages to avoid.
A further refinement does a
binary search
In computer science, binary search, also known as half-interval search, logarithmic search, or binary chop, is a search algorithm that finds the position of a target value within a sorted array. Binary search compares the target value to the m ...
in the upward search, and sorts in a worst case of comparisons, approaching
the information-theoretic lower bound of comparisons.
A variant that uses two extra bits per internal node (''n''−1 bits total for an ''n''-element heap) to cache information about which child is greater (two bits are required to store three cases: left, right, and unknown)
uses less than compares.
Other variations
*Ternary heapsort uses a
ternary heap
The -ary heap or -heap is a priority queue data structure, a generalization of the binary heap in which the nodes have 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., - ...
instead of a binary heap; that is, each element in the heap has three children. It is more complicated to program but does a constant number of times fewer swap and comparison operations. This is because each sift-down step in a ternary heap requires three comparisons and one swap, whereas in a binary heap, two comparisons and one swap are required. Two levels in a ternary heap cover 3
2 = 9 elements, doing more work with the same number of comparisons as three levels in the binary heap, which only cover 2
3 = 8. This is primarily of academic interest, or as a student exercise, as the additional complexity is not worth the minor savings, and bottom-up heapsort beats both.
*Memory-optimized heapsort improves heapsort's
locality of reference
In computer science, locality of reference, also known as the principle of locality, is the tendency of a processor to access the same set of memory locations repetitively over a short period of time. There are two basic types of reference localit ...
by increasing the number of children even more. This increases the number of comparisons, but because all children are stored consecutively in memory, reduces the number of
cache line
A CPU cache is a hardware cache used by the central processing unit (CPU) of a computer to reduce the average cost (time or energy) to access data from the main memory. A cache is a smaller, faster memory, located closer to a processor core, which ...
s accessed during heap traversal, a net performance improvement.
*The standard implementation of Floyd's heap-construction algorithm causes a large number of
cache miss
In computing, a cache ( ) is a hardware or software component that stores data so that future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation or a copy of data stored elsew ...
es once the size of the data exceeds that of the
CPU cache
A CPU cache is a hardware cache used by the central processing unit (CPU) of a computer to reduce the average cost (time or energy) to access data from the main memory. A cache is a smaller, faster memory, located closer to a processor core, whi ...
. Better performance on large data sets can be obtained by merging in
depth-first
Depth-first search (DFS) is an algorithm for traversing or searching tree or graph data structures. The algorithm starts at the root node (selecting some arbitrary node as the root node in the case of a graph) and explores as far as possible al ...
order, combining subheaps as soon as possible, rather than combining all subheaps on one level before proceeding to the one above.
[Alternate PDF source]
*Out-of-place heapsort improves on bottom-up heapsort by eliminating the worst case, guaranteeing comparisons. When the maximum is taken, rather than fill the vacated space with an unsorted data value, fill it with a sentinel value, which never "bounces" back up. It turns out that this can be used as a primitive in an in-place (and non-recursive) "QuickHeapsort" algorithm. First, you perform a quicksort-like partitioning pass, but reversing the order of the partitioned data in the array. Suppose (
without loss of generality
''Without loss of generality'' (often abbreviated to WOLOG, WLOG or w.l.o.g.; less commonly stated as ''without any loss of generality'' or ''with no loss of generality'') is a frequently used expression in mathematics. The term is used to indicat ...
) that the smaller partition is the one greater than the pivot, which should go at the end of the array, but our reversed partitioning step places it at the beginning. Form a heap out of the smaller partition and do out-of-place heapsort on it, exchanging the extracted maxima with values from the end of the array. These are less than the pivot, meaning less than any value in the heap, so serve as sentinel values. Once the heapsort is complete (and the pivot moved to just before the now-sorted end of the array), the order of the partitions has been reversed, and the larger partition at the beginning of the array may be sorted in the same way. (Because there is no non-
tail recursion
In computer science, a tail call is a subroutine call performed as the final action of a procedure. If the target of a tail is the same subroutine, the subroutine is said to be tail recursive, which is a special case of direct recursion. Tail recur ...
, this also eliminates quicksort's stack usage.)
*The
smoothsort
In computer science, smoothsort is a comparison sort, comparison-based sorting algorithm. A variant of heapsort, it was invented and published by Edsger Dijkstra in 1981. Like heapsort, smoothsort is an in-place algorithm with an upper bound of ...
algorithm is a variation of heapsort developed by
Edsger W. Dijkstra
Edsger Wybe Dijkstra ( ; ; 11 May 1930 – 6 August 2002) was a Dutch computer scientist, programmer, software engineer, mathematician, and science essayist.
Born in Rotterdam in the Netherlands, Dijkstra studied mathematics and physics and the ...
in 1981. Like heapsort, smoothsort's upper bound is . The advantage of smoothsort is that it comes closer to time if the
input is already sorted to some degree, whereas heapsort averages regardless of the initial sorted state. Due to its complexity, smoothsort is rarely used.
*Levcopoulos and Petersson describe a variation of heapsort based on a heap of
Cartesian tree
In computer science, a Cartesian tree is a binary tree derived from a sequence of distinct numbers. To construct the Cartesian tree, set its root to be the minimum number in the sequence, and recursively construct its left and right subtrees fro ...
s. First, a Cartesian tree is built from the input in time, and its root is placed in a 1-element binary heap. Then we repeatedly extract the minimum from the binary heap, output the tree's root element, and add its left and right children (if any) which are themselves Cartesian trees, to the binary heap. As they show, if the input is already nearly sorted, the Cartesian trees will be very unbalanced, with few nodes having left and right children, resulting in the binary heap remaining small, and allowing the algorithm to sort more quickly than for inputs that are already nearly sorted.
* Several variants such as
weak heapsort require comparisons in the worst case, close to the theoretical minimum, using one extra bit of state per node. While this extra bit makes the algorithms not truly in-place, if space for it can be found inside the element, these algorithms are simple and efficient, but still slower than binary heaps if key comparisons are cheap enough (e.g. integer keys) that a constant factor does not matter.
* Katajainen's "ultimate heapsort" requires no extra storage, performs comparisons, and a similar number of element moves. It is, however, even more complex and not justified unless comparisons are very expensive.
Comparison with other sorts
Heapsort primarily competes with
quicksort
Quicksort is an efficient, general-purpose sorting algorithm. Quicksort was developed by British computer scientist Tony Hoare in 1959 and published in 1961. It is still a commonly used algorithm for sorting. Overall, it is slightly faster than ...
, another very efficient general purpose in-place unstable comparison-based sort algorithm.
Heapsort's primary advantages are its simple, non-
recursive
Recursion occurs when the definition of a concept or process depends on a simpler or previous version of itself. Recursion is used in a variety of disciplines ranging from linguistics to logic. The most common application of recursion is in m ...
code, minimal auxiliary storage requirement, and reliably good performance: its best and worst cases are within a small constant factor of each other, and of the
theoretical lower bound on comparison sorts. While it cannot do better than for pre-sorted inputs, it does not suffer from quicksort's worst case, either.
Real-world quicksort implementations use a variety of
heuristic
A heuristic or heuristic technique (''problem solving'', '' mental shortcut'', ''rule of thumb'') is any approach to problem solving that employs a pragmatic method that is not fully optimized, perfected, or rationalized, but is nevertheless ...
s to avoid the worst case, but that makes their implementation far more complex, and implementations such as
introsort
Introsort or introspective sort is a hybrid sorting algorithm that provides both fast average performance and (asymptotically) optimal worst-case performance. It begins with quicksort, it switches to heapsort when the recursion depth exceeds a l ...
and pattern-defeating quicksort use heapsort as a last-resort fallback if they detect degenerate behaviour. Thus, their worst-case performance is slightly worse than if heapsort had been used from the beginning.
Heapsort's primary disadvantages are its poor
locality of reference
In computer science, locality of reference, also known as the principle of locality, is the tendency of a processor to access the same set of memory locations repetitively over a short period of time. There are two basic types of reference localit ...
and its inherently serial nature; the accesses to the implicit tree are widely scattered and mostly random, and there is no straightforward way to convert it to a
parallel algorithm
In computer science, a parallel algorithm, as opposed to a traditional serial algorithm, is an algorithm which can do multiple operations in a given time. It has been a tradition of computer science to describe serial algorithms in abstract mach ...
.
The worst-case performance guarantees make heapsort popular in
real-time computing
Real-time computing (RTC) is the computer science term for Computer hardware, hardware and software systems subject to a "real-time constraint", for example from Event (synchronization primitive), event to Event (computing), system response. Rea ...
, and systems concerned with maliciously chosen inputs such as the Linux kernel. The combination of small implementation and dependably
"good enough" performance make it popular in
embedded system
An embedded system is a specialized computer system—a combination of a computer processor, computer memory, and input/output peripheral devices—that has a dedicated function within a larger mechanical or electronic system. It is e ...
s, and generally any application where sorting is not a
performance bottleneck. heapsort is ideal for sorting a list of
filename
A filename or file name is a name used to uniquely identify a computer file in a file system. Different file systems impose different restrictions on filename lengths.
A filename may (depending on the file system) include:
* name – base ...
s for display, but a
database management system
In computing, a database is an organized collection of data or a type of data store based on the use of a database management system (DBMS), the software that interacts with end users, applications, and the database itself to capture and an ...
would probably want a more aggressively optimized sorting algorithm.
A well-implemented quicksort is usually 2–3 times faster than heapsort.
[ See particularly figure 9c on p. 98.] Although quicksort requires fewer comparisons, this is a minor factor. (Results claiming twice as many comparisons are measuring the top-down version; see .) The main advantage of quicksort is its much better locality of reference: partitioning is a linear scan with good spatial locality, and the recursive subdivision has good temporal locality. With additional effort, quicksort can also be implemented in mostly
branch-free code,
and multiple CPUs can be used to sort subpartitions in parallel. Thus, quicksort is preferred when the additional performance justifies the implementation effort.
The other major sorting algorithm is
merge sort
In computer science, merge sort (also commonly spelled as mergesort and as ) is an efficient, general-purpose, and comparison sort, comparison-based sorting algorithm. Most implementations of merge sort are Sorting algorithm#Stability, stable, wh ...
, but that rarely competes directly with heapsort because it is not in-place. Merge sort's requirement for extra space (roughly half the size of the input) is usually prohibitive except in the situations where merge sort has a clear advantage:
* When a
stable sort
In computer science, a sorting algorithm is an algorithm that puts elements of a list into an order. The most frequently used orders are numerical order and lexicographical order, and either ascending or descending. Efficient sorting is importa ...
is required
* When taking advantage of (partially) pre-sorted input
* Sorting
linked list
In computer science, a linked list is a linear collection of data elements whose order is not given by their physical placement in memory. Instead, each element points to the next. It is a data structure consisting of a collection of nodes whi ...
s (in which case merge sort requires minimal extra space)
* Parallel sorting; merge sort parallelizes even better than quicksort and can easily achieve close to
linear speedup
In computer architecture, speedup is a number that measures the relative performance of two systems processing the same problem. More technically, it is the improvement in speed of execution of a task executed on two similar architectures with ...
*
External sorting
External sorting is a class of sorting algorithms that can handle massive amounts of data. External sorting is required when the data being sorted do not fit into the main memory of a computing device (usually RAM) and instead they must reside i ...
; merge sort has excellent locality of reference
Example
The examples sort the values in increasing order using both heap-construction algorithms. The elements being compared are shown in a bold font. There are typically two when sifting up, and three when sifting down, although there may be fewer when the top or bottom of the tree is reached.
Heap construction (Williams' algorithm)
Heap construction (Floyd's algorithm)
Heap extraction
Notes
References
*
*
*
*
* Chapters 6 and 7 Respectively: Heapsort and Priority Queues
A PDF of Dijkstra's original paper on Smoothsortby David Carlson, St. Vincent College
External links
* – graphical demonstration
– With text, animations and interactive exercises
*
ttp://www.codecodex.com/wiki/Heapsort Heapsort implemented in 12 languages
Sorting revisitedby Paul Hsieh
A PowerPoint presentation demonstrating how Heap sort worksthat is for educators.
Pat Morin
{{sorting
Articles with example pseudocode
Comparison sorts
Heaps (data structures)