Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
Help about MediaWiki
Special pages
Niidae Wiki
Search
Search
Appearance
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Heapsort
(section)
Page
Discussion
English
Read
Edit
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
View history
General
What links here
Related changes
Page information
Appearance
move to sidebar
hide
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
== 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 {{code|heapify()}} function on the array. This builds a heap from an array in {{math|''O''(''n'')}} 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 {{code|siftDown()}} 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 {{code|heapify()}} operation is run once, and is {{math|''O''(''n'')}} in performance. The {{code|siftDown()}} function is called {{mvar|n}} times and requires {{math|''O''(log ''n'')}} work each time, due to its traversal starting from the root node. Therefore, the performance of this algorithm is {{math|1=''O''(''n'' + ''n'' log ''n'') = ''O''(''n'' log ''n'')}}. The heart of the algorithm is the {{code|siftDown()}} 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 {{code|siftDown()}} operation on the subtree rooted at the newly demoted ex-root. The number of iterations in any one {{code|siftdown()}} call is bounded by the height of the tree, which is {{math|1={{floor|log{{sub|2}} ''n''}} = ''O''(log ''n'')}}. === Pseudocode === The following is a simple way to implement the algorithm in [[pseudocode]]. Arrays are [[Comparison of programming languages (array)|zero-based]] and {{code|swap}} 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 {{code|a[0]}}, while at the end of the sort, the largest element is in {{code|a[end]}}. '''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 [[Loop invariant|invariants]] that a[0:endβ1] is a heap, and'' ''every element a[end:countβ1] beyond end is greater than everything before it,'' ''i.e. a[end:countβ1] is in sorted order.)'' end β count '''while''' end > 1 '''do''' ''(the heap size is reduced by one)'' end β end β 1 ''(a[0] is the root and largest value. The swap moves it in front of the sorted elements.)'' swap(a[end], a[0]) ''(the swap ruined the heap property, so restore it)'' siftDown(a, 0, end) The sorting routine uses two subroutines, {{code|heapify}} and {{code|siftDown}}. The former is the common in-place heap construction routine, while the latter is a common subroutine for implementing {{code|heapify}}. ''(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[child] < a[child+1] '''then''' child β child + 1 '''if''' a[root] < a[child] '''then''' swap(a[root], a[child]) 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 {{code|heapify}} procedure operates by building small heaps and repeatedly merging them using {{code|siftDown}}. It starts with the leaves, observing that they are trivial but valid heaps by themselves, and then adds parents. Starting with element {{math|''n''/2}} 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 {{math|''O''(''n'')}} time, count the worst-case number of {{code|siftDown}} 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 {{code|siftDown}} 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 {{math|1=''n''/2 + ''n''/4 + ''n''/8 + β― = nβ (1/2 + 1/4 + 1/8 + β―)}}, where the infinite sum is a well-known [[geometric series]] whose sum is {{math|1}}, thus the product is simply {{mvar|n}}. 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 {{math|2''n'' β 2''s''<sub>2</sub>(''n'') β ''e''<sub>2</sub>(''n'')}}, where {{math|''s''<sub>2</sub>(''n'')}} is the [[Hamming weight|number of 1 bits]] in the binary representation of {{mvar|n}} and {{math|''e''<sub>2</sub>(''n'')}} is the [[Find first set|number of trailing 0 bits]].<ref>{{cite journal | last1 = Suchenek | first1 = Marek A. | title = Elementary Yet Precise Worst-Case Analysis of Floyd's Heap-Construction Program | doi = 10.3233/FI-2012-751 | pages = 75β92 | journal = [[Fundamenta Informaticae]] | volume = 120 | issue = 1 | year = 2012}}</ref><ref>{{cite arXiv | last = Suchenek | first = Marek A. | title = A Complete Worst-Case Analysis of Heapsort with Experimental Verification of Its Results, A manuscript | date = 2015-04-07 | eprint = 1504.01459 | class = cs.DS }}</ref> === Standard implementation === Although it is convenient to think of the two phases separately, most implementations combine the two, allowing a single instance of {{code|siftDown}}to be [[Inline expansion|expanded inline]].<ref>{{harvnb|Knuth|1997}}</ref>{{rp|Algorithm H}} Two variables (here, {{code|start}} and {{code|end}}) keep track of the bounds of the heap area. The portion of the array before {{code|start}} is unsorted, while the portion beginning at {{code|end}} is sorted. Heap construction decreases {{code|start}} until it is zero, after which heap extraction decreases {{code|end}} 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[end], a[0]) ''(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[child] < a[child+1] '''then''' child β child + 1 '''if''' a[root] < a[child] '''then''' swap(a[root], a[child]) root β child ''(repeat to continue sifting down the child now)'' '''else''' '''break''' ''(return to outer loop)''
Summary:
Please note that all contributions to Niidae Wiki may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
Encyclopedia:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Search
Search
Editing
Heapsort
(section)
Add topic