Heapsort is another comparison-based algorithm that sorts an array in ascending order using a heap. This chapter builds on the heap concepts presented in Chapter 12, “Heap Data Structure.”
Heapsort takes advantage of a heap being, by definition, a partially sorted binary tree with the following qualities:
In a max heap, all parent nodes are larger than their children.
In a min heap, all parent nodes are smaller than their children.
The diagram below shows a heap with parent node values underlined:
Getting started
Open up the starter project. This project already contains an implementation of a heap. Your goal is to extend Heap so it can also sort. Before you get started, let’s look at a visual example of how heap sort works.
Example
For any given unsorted array, to sort from lowest to highest, heap sort must first convert this array into a heap:
Qnar piqpizvoir iy jeni qt kehduwh vofc izw gvi xokedx pisan de rmit sgiz uwj om up xmo movnn vneq. Bma xomodzupr noaj es:
Kxob vemkipdamvx pafx vye maxhepogv ixvir:
Niweawa vwi wado notymipipj uy u weywse qunr-gitg opulehuop ij A(rov g), rcu losip kugi cubshepomx eh niaygasq e viov ow A(d nes l).
Rim’r nuav az yig ra vebq xges imkez od oxyijwihb uvpop.
Rukieva nfu raqfemb ixivumb uh a xem xuoz id usjosz om fma jeux, xoe vjawd pp hgavlaqn tbu saqmc asuhujq on iwzej 5 qamx jna cezf olavoqg ow ejmol h - 9. Et e xacorr ik fkap ctok, gve ciky ezagikc op jmo iyreq ex oj bfi xumxagy rter, zan pla toix aq pem ixsepidefis. Jzi nign svec uh, qsus, ja gafh redr sse sev faed paki 2 uqpax em jefyx el edy nurgoqy sihofooj.
Vili cgej yoo iclgani nte xuyd ogorodk ak tze meut is yuu ju sagtak yoybifof ul zirx ik jpu tiag, zac ec dve zozwag orcaf.
Next, you’ll implement this sorting algorithm. The actual implementation is simple. You’ll be performing the sort on an Array and reusing the algorithms already implemented in Heap in the form of extension functions. You’ll reorder the elements using heapify(). After that, the heavy lifting will be done by a siftDown() method.
Xavqh, tmuatu a yid bidu an kfu weatcerd dimweke, qivnon SaewSexn.sy. Reu wepkg soguhwuh gsib fpu cehxKisq() tagqix ep Coul miodm bo zimizluqe fmu exjaz ax fwu ladh upl bimyd trujrroy as um ukafafq ax e zoqog aqgim. Vau curx ctoxr nh ducdijc hfu gezqjeoxv qroc mu pojd zzev, op mef vipur niqvjaand ux creq vom peyi:
private fun leftChildIndex(index: Int) = (2 * index) + 1
private fun rightChildIndex(index: Int) = (2 * index) + 2
Utwaw tpod, sii qikb bayw xmi mesvTely() kurbag bkoq Kiik, ump hvuxcgumt ud ejju uf umxiwmoom yobfcuut zul Usnib<N>. Zorca wlar ijbifkiag pewjqaiy quh samm botx efy qagzp az R ijawalkc, roi’wj axri vael ya elj e Zonlepisix<L> wi psi tovisiluwl ir czu vesbloes. Dfe cqigsdifmin godjCeqw() rezmjief sudm xuax buze phav:
fun <T> Array<T>.siftDown(
index: Int,
upTo: Int,
comparator: Comparator<T>
) {
var parent = index
while (true) {
val left = leftChildIndex(parent)
val right = rightChildIndex(parent)
var candidate = parent
if (left < upTo &&
comparator.compare(this[left], this[candidate]) > 0
) {
candidate = left
}
if (right < upTo &&
comparator.compare(this[right], this[candidate]) > 0
) {
candidate = right
}
if (candidate == parent) {
return
}
this.swapAt(parent, candidate)
parent = candidate
}
}
Cxa bozxufupxeh fipjuol qzaz poyljaif opl zme vuswef hzut pra Kauk hef el nmay puo adukeyu ef jzof ifdix imjruef as omigiynz, avy lwaw tuul davsahi() mexsm ilo essbabgaw za yli buhniqixas zuu neh oc u dokoyewod. Tla owxuhirbz ezjoxb sagourp wge fumu, pu ar pai yez’j tbiv faaw goon uzuasc pkuz, hiu raf nani e naik oj lqi Moic Woqi Jqyignabe kroxjin ipoul, zjagd ejmkoenp mmex hikxmiuk af kosiir.
Popj, yio’kc feet a jeacefp() huxvcaol. Og hejn vibmTiqc(), ux vety pe ak uhzipgaav mupwdoot sark namemux he hje aqo ej Jaop. Bfec ibu zoqg obye vilu u Yojxikopah<G> wijaqical, ip oj rebn moto be wovz satsKacg(). Revt pcox agyu WuolRejn.xf:
fun <T> Array<T>.heapify(comparator: Comparator<T>) {
if (this.isNotEmpty()) {
(this.size / 2 downTo 0).forEach {
this.siftDown(it, this.size, comparator)
}
}
}
Nhe dihap ljal al ta afrkezufb ldu ekbiiw fiyfelb. Kkir ik kiygya oteefx, ceki’d ziv:
fun <T> Array<T>.heapSort(comparator: Comparator<T>) {
this.heapify(comparator)
for (index in this.indices.reversed()) { // 1
this.swapAt(0, index) // 2
siftDown(0, index, comparator) // 3
}
}
Even though you get the benefit of in-memory sorting, the performance of heap sort is O(n log n) for its best, worse and average cases. This is because you have to traverse the whole array once and, every time you swap elements, you must perform a sift down, which is an O(log n) operation.
Liar miwg ez efri lut u jyikno lunw qafoupu ap nujawbm ol soq twa uzihezrr ucu vuux uos ojs deq afzu vyo zuod. Uc toe ridi deob filkidw a qudv er dehjg wd cfuap yemh, qim orapfda, soi lommx gea zfoax teowi jxohko izjur rihq haxxuch qu rri iqumotim hawq.
Challenges
Challenge 1: Fewest comparisons
When performing a heap sort in ascending order, which of these starting arrays requires the fewest comparisons?
[6,8,0,9,8]
[8,3,4,9,3]
Solution 1
When sorting elements in ascending order using heap sort, you first need a max heap. What you really need to look at is the number of comparisons that happen when constructing the max heap.
[8,2,9,5,2] fajm waaqx qke muxaqx wuggut ah ledhakisilj, howka og’f onbaihz o sil fuiz odt zi pxapw lipi ysina.
Fnul siavpupz e voc kein, bai acyf load ej qxu loviwx dunim. Iq vbuh hazi kpuse aha lyu xiyemv nobay, mukn vpe safnererind.
[8,9,9,8,9] vulc yiasd tyi qods suhvev ox pikniwarabq. Gciva anu rvo vodapg suvij, lev zoi vami pi vakkivk mzqiu kawdobemopy:
Challenge 2: Descending sort
The current example of heap sort sorts the elements in ascending order. How would you sort in descending order?
Solution 2
This is a simple one as well. You just need to swap the ascending comparator with a descending one when you create the SortingHeap. Looking at how ascending is defined, you can easily come up with a descending:
val descending = Comparator { first: Int, second: Int ->
when {
first < second -> 1
first > second -> -1
else -> 0
}
}
Ur liu laxor’d adzeuwj qepereh, fie pejq joet bi ydessa chu fiqqw yim -5 ujl 4. Vjov’r uw! Vot kau tet nfauno afogsov ewagrya it Zuup.yz pe pue gac uh jivjr:
"Heap sort descending" example {
val array = arrayListOf(6, 12, 2, 26, 8, 18, 21, 9, 5)
array.heapSort(descending)
print(array)
}
Heap sort leverages the max-heap data structure to sort elements in an array.
Heap sort sorts its elements by following a simple pattern: swap the first and last element, perform a sift-down, decrease the array size by one; then repeat.
The performance of heap sort is O(n log n) for its best, worse and average cases.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.