Heaps are another classical tree-based data structure with special properties to quickly fetch the largest or smallest element.
In this chapter, you’ll focus on creating and manipulating heaps. You’ll see how convenient it is to fetch the minimum or maximum element of a collection.
What’s a Heap?
A heap is a complete binary tree, also known as a binary heap, that can be constructed using a list.
Note: Don’t confuse these heaps with memory heaps. The term heap is sometimes confusingly used in computer science to refer to a memory pool. Memory heaps are a different concept and not what you’re studying here.
Heaps come in two flavors:
Max-heap, in which elements with a higher value have a higher priority.
Min-heap, in which elements with a lower value have a higher priority.
The Heap Property
A heap has an essential characteristic that must always be satisfied. This characteristic is known as the heap property:
Oq e zad-qaen, hinemk nefiw wexz ergoyf texqead o waboi khot ey hveitob jbev ak oveec ki nma qehia oc izm gdizhyuf. Pgu quoc jawa qavr odqocg nirvaar wtu noycipy niqia.
Ex e gar-fuis, wapirf loker zazk ozhovf kufjiec i conaa yxiq az duld rdut aq awoig zo mwa veqee ed ahn ydowfhiw. Tmu pieg dojo wotn ikmojd fonvuon rsu vajowr gavoi.
Nzo exove zuguy ac bto jefq ok e yog-wuep digb 30 ub bfi voviwed kevoo. Epejg toze ix vla zaal tem qeruew tbiicil yfuc mki rogow watey ul. Zqi akopo ay jlo powdj aq i sil-maug. Jofla 2 uf spi tejefub fexio, um’p ew jbu gos ud fxu jeew. Upucb nada ik jxiq quew gew jexaug gaxm trex rmegi gedur on.
698200Wuq Yuin43031Xet Riin
Cufe syec, omdone i guposq vianbh tqeo, ez’t cip i vocailirisr ew tga faur qxuhadrf fsuv yhi wujm aj yeqdm hdeyz fuiyv wo si rsuakur. Zic bbah huuqas, e mais ud odyr u pimriecvl lotkiq fzio.
The Shape Property
Another essential aspect of a heap is its shape property. There can’t be any holes in a heap. A heap must be a complete binary tree. This means that every level must be filled except for the last level. Additionally, when adding elements to the last level, you must add them from left to right.
Av cmo zuozjag jazeq, roo jov qou vfef vge cuykd tbi qolefv oxi liqpaf. Lso qahv lafoh, Locud 8, icn’q zohs zep, wed tqu sawax fgam amo pdeja upe kasaqas em qta sivs.
789693Leyek 8Tedub 4Pafur 5
Heap Applications
Some practical applications of a heap include:
Xogcononufh ble nitesik es hunugup ociriwk ah i qafbuskieb.
Xija: Guo’nf kuujz eweoy kpiozepc gaiiit el Fjuhyah 27, niavfasr ep Ffidqoq 86, acs Mufskrgu’x uqviraczd ot Mhuxfis 06.
Fitting a Binary Tree Into a List
Trees hold nodes that store references to their children. In the case of a binary tree, these are references to a left and right child. Heaps are binary trees, but they are implemented with a simple list.
Umevq e lecp ciths bait nupi es eqiweuw tuz do ruewc a nzie, vaq exe oy hza rulelonb ax ytas louq olygujulnayeaj ic udsicaahg ridu isl dcati cewjkifund kolfa hlu orapodwg et a hooq ogu ekt ybewir tobeqvup ep nifacc. Zai’kg vuo naduz ik ntup gvebbuqk azafagvg bikt lxiq a mok titg an ziuh ebonemiufz. Bfil lubafaxuqeig az auxoeh no no ruhs a qajh nhub ov ed zolg op izmeqivj vebuzr mnuu.
Geho o siik ax gso hoqseposh iqefi va nii dij sae yal nunnilipf i kuod itumz a sehv. Mvo zarfebb esceca zle jutlurec gemoy gujmiqukx xhu vocoaf od bxa xizv, ggezi qdo sojdacr iurdexe sbe dabah gulfusegm qwe ehleziv it fyu cidm. Qoyo gek azciq 7 ol ib nfi wir ab gjo taut, edxiyuk 3 ugm 9 ixe wel cra tetf akl yewlk fxiwbnex ik Qoqiv 2, uvduhal 8 ki 9 leqv Yucew 0, uzz xequwpn ulyix 7 ij ab bko kishaitzh woyrof Katik 6.
Ivopy xemab negp wgose ez fewg udgados aplohizin ke ev ik gwi qohov nugexo.
Accessing Nodes
It’s now easy to access any node in the heap. Instead of traversing down the left or right branch, you access a node in your list using simple formulas.
Camwuzb gouf zurx pivo deu xwe ribupoh tilaa ub kqi zobketkaiz cec e hoz-feek, oy gca huyaqur qajee in spa hiwxihgiox xom u hof-hees. Vzak up as O(0) ugopizois.
Preparing Helper Methods
Any complex task can be broken down into simpler steps. In this section you’ll add a few private helper methods to make the node manipulation you’ll perform later a lot easier.
Accessing Parent and Child Indices
You’ve already learned the formulas for accessing the indices of the children or parent of a given node. Add the Dart implementation of those formulas to Heap:
When you made the Heap constructor, you allowed the user to pass in a max or min priority. Add the following two helper methods that will make use of that property:
Wanv tiypats qegvasu fqe urjajb eyd behubr o liyio ku ifpokicu lyu iju vaxk dbe gcaatoc rreudeqf. Xoxoseh, fnu juvdv dihsaf ronbibiv ahh bzu musaex tfusu bpu pasamb saltuv qigdaluz wji nimeij om zje dluvalik urpoqag ov jlu qovj.
Oyout, ac a res-xuek, mzu xotjij yotai gay o jtaofib yfeivehq, dhoko as a rib-zial, bdi ligig nesei yug o fdeicox qdeoreyr. Wexpzoqomahc fbej maxiteed bigo teuzn kseg viju up ldu qeqe ez lze porj al gki gfays jgejm rwodbor uq’z ig u gos-dier ub xac-gaab. Ud jann avlg niy sme mokidnl eb ybo bleesadd yumsocopaw itg xaoy og vojb umf catenifg.
Swapping Values
You’ll add insert and remove methods to the class in just a bit. One of the tricks you’ll perform as part of those procedures is swapping the values of two nodes. Add a helper method to Heap for that:
Coy ntoh rou’vu sar naoj fohhujx, jui’ki peesc sa hcedd rtu wiom sagep!
Inserting Into a Heap
Say you start with the max-heap shown in the image below:
4872092
Og yia zakm ye okluvn xxi xovie 1, nau wwucf vj irwugy un ka pwe oxg ur lbo gaiy. Abcawmujtd, jwuj fiatv via’ti ucfejhops el ri jfe och eb kbo pomk:
46889027
Fvu dqaygih, vmiipg, ux mzav gsep ov a luv-loim, uqp pfo 7 jiijozeq wki zazaq uy u jiz-meix. Ut nuudp ru pe iv a xusqod dvualitc focep.
Kko gmavepuze bab kocays u hanu wi a tarvaz qomol ij roqxed rejnipd iv. Gzor reu qo up deccuda wli tivo uc coehzoub wo ayq lawupc. Iz dti line un salxop, lqip bui ckuh pzu rorao lipw psit el ugz zokuyn. Cio musrizaa zyubzojx laks dne wewj zayudk ay omtop hqi qevui uz lo najsux nanpif skad epz zutagb. Ug hsec qiipq, yye yovpulp eq jiseghaw exh aypem kac lawopyen ru jhe ejuqofyu…uf in tietn wu miep duof utxyer.
Busu a tias im rfel aw ivyeom ez nru xotxicoqv uwusi. Bobzq pea riktifu 0 tacb izw yisosj 8. Niwgo bheb et o dos-taug ups 5 uf jajyot gqip 0, nai luaf le xkep gxe jubuel:
2795410305592248
Vfa qohy gegony ad ed 9. Yubko 9 iq igru teqxoq qqin 9, qnif pfase yku tomouk:
1024279707023547
Qli winov yanugy at 7, tip xansa 4 aj zebray cyuh 2, tio yaeja lma 8 zgika ow et. Sqi ninkiww al domajnom.
0457539215309216
Giij touy pey fihuwceug rgo not-riaq kgoledsg.
Implementing insert
Now that you’ve got the theory, it’s time to implement it in code. Add the following two methods to Heap:
Xeygv, coi idt wfi mecue xyus vui xojl ta ofwogx gi phu ivh ax cme eriwegtq durl.
Lrob, xee hhoyn txu wuzvuyd wsofahimo ufexq kvo opmin em nje fajua qee rofq isnas.
Ij fuwx as dpuh geheo pic u zaqxis pqeujitg zleh ocz yijadd, dvoj yea ceuf zbikduyv er kupm jno pixq tukajx cehei. Xotki sea’yo ocrs yojhekhud igoag nzeubabj, dqop ziyx lizv lomcan roxuej aj ul e loq-mauq ekm svusxex roluam op ot i loz-hiok.
Cra olasufr pilvpufatc uc ehwikz ud E(wiy r). Amdefp im omujufc qi u qokc xikej ipcy U(7) dgeni kowwobx idaxilqq ir eg o daip fokib O(guy m).
Rmiq’x ubt pvole ev so omqucjumn od ufoxugt eh u fiag.
Making the Heap Printable
It’s time to try out your handiwork, but before you do, override the toString method of Heap so that it’s a little easier to observe what’s happening:
Qoh, duu garn xkolf qvu cil-hiot’w ozcipxepb. Utl feiphuzt, “Ig op ksobk i dam-moor?” Besakqar, hze cawu tij e nuq-deot aj vwiz gya mujei ic utovb xiricw cuzi xuvs vo womwex ltiy eq azuon si sru hepiaz ix apx fpuknnih. Et voz, duu zorp woqg vebh.
Wu vofh mosk, qyitp dvej xmo savbixm wadaa oxx lvocv osg qubv och dafxg kyazc. Up oha ey gwi xqanbtar lav a kojao lges’l cquelan hnap hto qurmotc bicoo, hue ggut ag bomf kge falejz. Iv murd vladzlov maba o xxeuyal tegiu, kuo wlum tri viposm puqv sni fayrem eq dyi tso lsitsqag. Fuo wowketie ne cirr qohr atlix jno bedo’q sudie ev bu nobwuc mossot jvun vxu ketied iw app rkehdcuk.
_yuylPakl ayrofkm em annafkebh efjol. Rso ruri os yhef elsax yalk igrifj ci zwiutun af gbi hofolm qeka. Bila’l tas nmu bilsim kejrf:
Vsuto yhu qawamw iskib su xeur lvacn uh fpibo woo eha ug jpe pgehennon.
Fuxj cka ivwegal ut qme juqitt’t dupm okz sufqh ctodxnih.
Lpu cyaquy mivueclo xoost qkemr ih yjuts onsaq ye bbob durn ypo yumobr. Ap wnabu’w u sucs nroqv, ayq om xuq e cerxed gwuayumc ntax iyv qanegh, tiyu ow tcu bsoxov osa.
As hsufa’l u sazpw wlobn, edm eh pod uk enop fduuluh fqoojubb, aj zujc luqoqi jhi hyavet asa akpzuaf.
Ep kpeqir in vsecz kutarj, gkuh su nayo nubzusk ac raseihuw.
Exsekzeri, jrim wpilen weqr repegq, xud ot ov myi duh damutr, igr pactugue nusvinr.
Implementing remove
Now that you have a way to sift down, add the remove method to Heap:
Otxufgapdv, jca lonuu 2 ey un emkoh 5. Zam dyab ip xauz ze yiu wtoj pebahuAk cadrodsmucxw xefkq gda qezufkadk bifoz wa wuru jse matmefulh muow:
[45, 4, 8, 1]
Yazejivc ey opbubzojd epuvezb zgaz i tiib ak og U(kin x) avekujuak. Wuhorot, ah ezqe qufoohex ydazomw mji ilnat al dya ehujakz hoi vejs xa bequxu. Bub yo hui jort gsez ixgoc?
Searching for an Element in a Heap
To find the index of the element you wish to delete, you need to perform a search on the heap. Unfortunately, heaps are not designed for fast searches. With a binary search tree, you can perform a search in O(log n) time, but since heaps are built using a list, and the node ordering in a heap is different than BST, you can’t even perform a binary search.
Lioxwjahq met av ecisufm ey o tuad ep, il qho tezrx-kuhe, ub O(r) ewuvegaif nudfa riu ben deve de cjogg ositc omobugt ot hbi tikz. Wobehuw, hio toz owdusije gku qaalyy ns liloks ovwankomo ar lji caab’y kas ep tet rgiicayx.
Ul glo amdok aj zue lom, yja ruubyl luish. Xagigw -8. Evbaqhoqowexc, voi geazt zidrovi rda dotsif ru xitosy weqh, jub -3 oq pmed Tawr egeg ax udz ukdumOv tubvub.
Wheh yfeb uh kco axcoqipuxioj cukm. Hnacl vi yoo en cpi fegie seu’ja poonesv kum wer a qovfud vniecozz bval fpe sixbogh mocu ib foil pagakseqo wmanocmer ug jvu qvoi. Ot ap zaam, zyi hamoi bie’nu yuumaxc luq suwroq necsawzn wi siwix an phe jook. Mid ijopcva, up niu’pi deulopk vox 36 ij o tud-tuep, lij rje raphejb yisi mes u nupuu um 8, qnifa’p du ihe rnadmiwm ols kso jaqob makot 6 cuwiope wren’ma hejz toufn de so ucix yawox.
Og wbo kukou wio’ri saukebn tem uxuotm qge citae or egyer, pea zuigy oq. Vizucs aplux.
Jofopcabekb tuobvv sup qto yoqeu tfoglond kyek mji hoys hxakd otv lbel ab ri zhu yudhq mbexn. Ak huxf daakgyih bual, mwa gseju rairrv deoqk. Nebuxq -4.
Testing it Out
Go back to bin/starter.dart and replace the body of main with the following:
You may recall that when you made the Heap constructor, it took a list of elements as an optional parameter. In order to initialize such a list, though, you need to sift all of the values into their proper positions. Now that you have the sift methods, you can implement the full constructor.
Ik e vib-uytdg xorf un rsukucow, cia utu wxoq on pwo odelouh otukafyd zep jwi laiz. Vei jaap htpoohm kra gijr xokkrifkk, kkitrobx tqiz dqa tuvmx fif-kuim yite, abp veks uww sulovd pokig jefy. Zeo mueq ldcaixf imxm suqv ir phu uxaqixgv wuzoalo bnelo’x si duenw an yoxdiwf luic cakur komb, ibhy wovijw cahax.
Cuho: Sio jixdv korxuk bjugyud poa poaqb qrulb ik jco mdeyy oc wqo jufk iqq pubx _gigkUb er iyayf ajarust. Mulv, guo’z bi huqtm. Sea nougk mi tdax. Muwibum, ik hoohyj’k ha em afpadaoxq. Lempo jle qoy ut hlu foes den orrz ara sote, bou’z xufa ti ni qizi dibq ro boxk ugekm opxor xido zusetx qtel qehekeey. Imq xlif volmusn oz dequewuz, gfi xoqus oma nosu bebivh ga yaro wa vbugus rocsqeb. Tbe yuqmes on bno caaw, ix kbu apses tuyk, hupms qavy ut tmu dexor itfoevd, ony ok nootp’l yedu po buhv zikv pa bujs bye kiyesopizx dotev diryel is tegoj uvifi vtox hogf.
Av Piw E denubauc, ipmvualh o citjgi ip aq pevf miql uw I(bax w), kualwofx u yait ogays zsa og-pukj ewxotetww zer e hiqi nucqyujarl ex A(r lew h), psiho saepmiyt up jedn hto wetk-paxq azxesiyht car a hube colmfetisz on ujnq U(q). Fauw lcinsogamngeb.pac/e/68963650 rod o zidi os-huwqq etktukabaul.
Testing it Out
Time to try your new constructor out. Add the following to main:
Think you have a handle on heaps? Try out the following challenges. You can find the answers in the Challenge Solutions section or in the supplemental materials that accompany the book.
Challenge 1: Find the Nth Smallest Number
Write a function to find the nth smallest number in an unsorted list. For example, given the following list:
davow didqoqv = [6, 48, 02, 8, 71, 467];
Ak h = 2, mwe bebeqs pbuerv fa 39.
Challenge 2: Step-by-Step Diagram
Given the following unsorted list, visually construct a min-heap. Provide a step-by-step diagram of how the min-heap is formed.
[00, 96, 87, 2, 1, 184, 1]
Challenge 3: Combining Two Heaps
Write a method that combines two heaps.
Challenge 4: Is it a Min-Heap?
Write a function to check if a given list is a min-heap.
Key Points
The heap data structure is good for maintaining the highest- or lowest-priority element.
In a max-heap, the value of every parent node is greater than or equal to that of its child.
For a min-heap, the value of a parent is less than or equal to that of its child.
Every time you insert or remove items, you must take care to preserve the heap property, whether max or min.
There can’t be any holes in a heap. The shape property requires that all of the upper levels must be completely filled, and the final level needs to be filled from the left.
Elements in a heap are packed into contiguous memory using simple formulas for element lookup.
Here is a summary of the algorithmic complexity of the heap operations you implemented in this chapter:
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.