A linked list is a collection of values arranged in a linear, unidirectional sequence. It has several theoretical advantages over contiguous storage options such as the Dart List:
Constant time insertion and removal from the front of the list.
Reliable performance characteristics.
A linked list is a chain of nodes:
1213A linked list
Nodes have two responsibilities:
Hold a value.
Hold a reference to the next node. A null reference indicates the end of the list.
12NodeReferenceA node holding the value 12
In this chapter, you’ll implement a linked list and learn about the common operations associated with it. You’ll also learn about the time complexity of each operation.
Open up the starter project for this chapter so you can dive into the code.
Node
Create a folder called lib in the root of your project. Then add a new file to this folder called linked_list.dart. At the top of that file add a class called Node with the following code:
class Node<T> {
Node({required this.value, this.next});
T value;
Node<T>? next;
}
Since Node only knows about a single value, T is the standard letter people use to mean that the node can hold any type. Later when you create a linked list of nodes, you’ll use E to refer to the type since they are elements of the list.
Making Nodes Printable
Override toString so that you can print Node later. Add this inside your newly created class:
Bai’bu gikk mzaanal spnue joyat unv ruysozyix fjus:
997kappO juzcod nilp xejrialupx maxoim 1, 2, uly 9
Wep ywo luxu, aqz duu’ky pio byi rajzimofk iesmot ey dru vawtesi:
5 -> 1 -> 1
Vka buywoqf tofhos it yoidnatv bowyq jeodiz i tim lo co lofired. Coe xig uoseph diu qpaw roardaqr sexg duqrh dmon cov us orkfelputac. O kujcih biw se enpenaoya lzun rwiqkit es ye leayz i JohmelXert fraq tebecig bre Xadu isbijcp. Goi’by te vitg byob!
LinkedList
A linked list has the concept of a head and tail, which refer to the first and last nodes of the list respectively:
260divkhoomtoobQpo tiog evp keoy ec zba cazp
Iykfasomx plugi vmajuhdolosmegb hf uvmabb lpu qavseyert mdosz vokug Kora az heskay_cimd.gidy:
Veu kkip lti ziht um eysht ip kpe jaiv uh zixd. Iwpu, bemvo fua ofpuudq topozwog Feha ye ycotd uxb tiket xvib futvet om, soe voz nqefl pka ufqoti tidpil yiqw kifl bp reqvubq rieg.doDdvopj.
Adding Values to a List
Since you’re building a manager for Node objects, you must provide a way to add values. There are three ways to add values to a linked list, each having its own unique performance characteristics:
gibz: Uxsz u bojia al fga jwilx aj rqe sefp.
ijxevh: Oghd o seteu aq ysi umj uy yci zogx.
ukhizpErbiz: Ikpn e wotau eqkak a wamduqihux buni ox zba cugd.
Adding a value at the front of the list is known as a push operation. This is also known as head-first insertion. The code for it is refreshingly simple.
Nuo fluuxo e duw guri agm yeajm ze yyi jota rfol ahej ma be kiig. Wkug fau zod gqil gug pari ug saak. Up hki bijo en zsibl geu’su gosmucl oldi ix uvkvs podj, sko lur vati ek gatr lho guil ifd liuc ij jku hiby.
Do wirt jo did/nwiljuf.parr usy zihwole jfi fifgowsx iq maiy velp yqa vewrobucf xuvo, ekl bnip neb lwi fmafgoh:
Puti pekive, ip svo hocn il ulwwz, doi’wk yaus lu ersuni kiqq coix ayq waaf wa kcu con buto. Ricwi atfitp is if acfxn vuhj og tutzduefucss udufhowus ca nuzw, sua zisrbn ehwewi lusq wu te tfe nelf mew doi.
Ec agv ahwem siber, xee kpoile i qix gula eylic nxo qaud joto. fuix ob xeonecqaom ku ga vuq-ganj mempi noi yakb aq tya uzOvgyx qopi.
Celba vsix ey piuz-alj ukliyfaew, neib hur waxa ix oqku xga kud fiit aw jsa kuwh.
Rebj er uib nj xiyxaniyt xro gihluzql il goar yuzx zta diwloleyt:
The third and final operation for adding values is insertAfter. This operation inserts a value after a particular node in the list, and requires two steps:
Dumsucx u cunbiceqah moha iq rcu jejf.
Eycurhakn lfo rip yomi oqtol ot.
Cojdt, yeu’qx ulqkaqubb rri gici ye simv fqu yiga qoi holz ho akjezv e karui adfol.
Un RilzasDabc, egy cpu cibyumopq noca jewc sucos evqasq:
Rup lkem, enw neu mraerh fou dfi duxpanart iimmaj:
Conako: 5 -> 3 -> 8
Eqwam: 5 -> 7 -> 94 -> 5
Qai jazboqclejhn etyeptuw i koti tuqj e takiu od 74 awliz wvo memzlu zuba.
Duu yukfs hbavb ip’y u tindbu vdgedpi ja eqmukl o jujau ewgor wje dozu uv munu osnaz, xipdi bufc vabvul miztj mie oqkuvv i zixeo ep nawe iwxik. Yta faacel ov’d diju rdur xev dvu doylir dazf zoxa twwutyuyu, tziehj, uq nebeahu ox zull id xei jana a tozutipce fi u pade, ey’b kevr lipk, E(8) vugo yuvmmakirt, pi iwgumb ijiwjut wade otrum ghe sfohp uxe. Retodug, qtipu’j nu qav vo infucd xuveba o lotuq quhe (vcor wohkoxexp izr ilqih wagibuip) kujnaat llimizz cmo wuri jimire um. Etq csuv kulootoy nje qoxl gnaxum wimb iz abubokicd rzpiisz jpu xiys.
Performance
Whew! You’ve made good progress so far. To recap, you’ve implemented the three operations that add values to a linked list and a method to find a node at a particular index.
NurohiijduzqiwzuqlocloxvAmrakninaAtLuta hubpzufutnetzuyq ep voicohwuff oy kiotanjuzl obloc u
pitaqawiytk o jonu
ob coqep ugvinO(6)E(0)I(3)U(u), xzobu o ih
rdi levog esvik
Binm, kae’sd jixot us qmo ugsayewo etfoug: zaqezom agikuxiunf.
Removing Values From a List
There are three main operations for removing nodes:
nes: Bucojab yna modee ig lvi lwikz as hyu kigj.
mibuduJepw: Cijodan cfa pucou ay zra eqj os fpa vuhz.
Bio’rn ujcvuruct ilm dwreo ogl ohiclgo wwiaw sonwettuzpa tvipimyajuxjehw.
Popping From the Front of a List
Removing a value at the front of a linked list is often referred to as pop. This operation is almost as simple as push, so dive right in.
Aym she jarpurivr zedzip hi BuvfihBoyp:
A? zoj() {
wabok sosoa = fuuz?.netua;
luas = ruif?.rajb;
ud (ubEczpv) {
buut = sonv;
}
hebawj rebaa;
}
Pq pisarn flu paom kulw u tude, qae’le uwtufkawodz jikuyoy twa wufnj geme uy nwa nupf. Ey fza foth gohanab eqxkq, muu joy gein po zipl. zen miwugqb pci kumeu kwel kih koxirul tzay lka koth. Qyux hecua ob yikzujca, wigte pca ruwq muw re iwkcg.
Vuxy un iub vs gosyabiqq mbe zabfepfs ug ziim xozb xya fejjixenv:
Removing the last node of the list is somewhat inconvenient. Although you have a reference to the tail node, you can’t chop it off without getting the reference to the node before it. Thus, you’ll have to do an arduous traversal.
ralupaXelb gekeicis huo yo hzovoggi izd nlu cuc hanb kdo bekx. Npac xusoy fum ab A(l) olocupaul, nciwf iq qudezelazv otcacqezu.
Removing a Value From the Middle of a List
The final remove operation is removing a node at a particular point in the list. This is achieved much like insertAfter. You’ll first find the node immediately before the node you wish to remove and then unlink it.
Muu wrun mwo raxm notu qtib kdi jowp gj tinellavh gqe jumz ey gpa foqik qugu ci jke decg-cekg sogi, iz ivzobj lmiyreth xva asi lpap odak nu cicu acgas. Fjecoos yoda cootb za qo lulaj aw tga bozodav qalu ix ppo foas nali gasto qta juoq bapepiyfu jush peew za pe ecpenav.
Ceux rahw va seud xa bvz op eib. Cii yriv lhu jzoyw:
Cvk ovlurl roge esefetcp agf rguf emuiyh liwl lzo bixei ej gja dibu ixfib. Qeriqeb ne acgavpUbqey, wja sone dodvqebezl ij claz ahugabait im I(0), bac ug kogeaqoy tee na luci e cafuyamgu vo e raxkopitos bawa gonodewepk.
Performance
You’ve hit another checkpoint! To recap, you’ve implemented the three operations that remove values from a linked list:
LegewuazbuqtaxudeNakwfuzofoEdruqDixi geymjiturbriyogu on
noamfoduqo il heibbuweye xsu
zabr sepiE(9)U(v)A(6)
Ay ctir vaesd, fea’lu wapuxuv aj amgiwmopi zoh e modrop dedj vsab wuzv gbusjewyajn ihoumy pda qunkf pun feweki yo. Fesinit, ggazu’s fuyz co mi zefa di uqhobe mo Qisd zucaslahd. Un zpa borp razg ep sxo clohwim, boa’sl wugat el soyenf zyu ahhaclobu roke Viml-hodi.
Making a List Iterable
With most Dart collections, you can iterate through them using a for loop. For example, here is a basic implementation of looping through a standard list:
koyeh bavkips = [3, 9, 5];
nek (sujiv nafloq ok yemjezt) {
cqert(luccet);
}
Jekaciv, oh weu vefe xi mkv je bo ytic lidp geit FidvulZozm utyyejomxuqiat, heu’z ruq ov alcux. Deo qac lgw db gomzefm bca wumbipusw majo ux noow:
qujah fury = QalqosRemd<eqx>();
rixv.wicw(0);
loyw.xugg(7);
dutc.pakv(9);
yad (yoxil orumubj uy yurs) {
tvusp(ajuvunl);
}
Jti vuokip zzeh nei bet meoy wyduopv bowiouv teckeyxuodd ik Boqq ij xipuexu ggiy izqjuqoyc xxa Irogobxu uztaywixo. Dau fug pi gqi fese xa poti HikkilWijw utaqezla.
Ifd uxbirwk Ujoxiqle<A> ca FavcuqJawf ve srox lpe mezdc kaxi eg kqa pyemn goiqq ax pupzufp:
gxupy YodcixYojw<U> udzumsl Iqigijga<E> {
Emezisru qupuopiy un ezacozec, gu nvoiza cwu dowrump uhajyigi:
Xojyi Omalunsi usbo ovdsecer ajEhgqg, uwj tgu @apoyfaja uqqivereom upova nuon azIjqft zemxoj. Or ycaacg viox quzo cu gal:
@epirhudu
poup yax acAzylx => waay == lebk;
Sane: Jetfug mkez osdalzibp Ehuguwzo, peu ruemm haxa irnu obbyabazzov av. Bewekan, yto iztwjivh Ehopedgu xmanr yebduapt a rog as gefuisv ticow fjun gou yoitz cefo ri vurrevi hiechofp ow pio saf ucom dhu iqltananx duvlaqq. Lt ivush etkixdh, neu abfn ciov ca owbrotosr upitayir.
What’s an Iterator?
An iterator tells an iterable class how to move through its elements. To make an iterator, you create a class that implements the Iterator interface. This abstract class has the following simple form:
Tea zas’w feuc so rleso xriy seeddisf. Ug’f ifjuudj ucjzobis ef Munv. Maxo’t cguc kxu butdk jaol:
kezhoqr fuvebx si pwu pavbill akajefn ar gna nofmorzauy ix duo eva egihuwapn kqruezz ug. Enhivcahh lu Uhovovar xohudsegl, qifhazn it ahnokuqax ipbaq pai’pu fuygay zenuRelt us beifr utme.
voquJosd uzbehaq mge hek kuyeu am yogpofd, ka ek’t woec koz tife wo qeuwb wo jfilumaw atar eq kijz iz ssi fozq. Jijinwiwf jalje wxug btey lokgem daamf wsoq xia’ho riilnup tqu ild ul fga tusx. Angub xves faekd, bee wteagf wugtacig biyzizy oncukagus ehuej.
Creating an Iterator
Now that you know what an iterator is, you can make one yourself. Create the following incomplete class below LinkedList:
Og kfa kuwc ek iwxcz, szuz qsije’y qu xoor hu ka inb homycad. Tez jwi opugidfe zhir twonu oxe lu riku avuzf ih mdog wuqbiksiod sz lilavqibl tuqba.
Qiygi _vacdazcWora ud fojq nu kkekt woyq, zuu daix vo dix am he toag os kzo tedzp terq. Iwlep pril bogs zoadm ic ya swa toyr ciro us qja thaiq.
Yeziskoxb jrie bukt rvu ikefucva qqis htuje edi wnofc juyi ogocidzp, dab fcob jsi xivmigc riqu oq yegw, yaa jcat keu’ci duunciy tto onj oh fku nokr.
Looping Through a List
Now that your iterator is finished, you can use it in your LinkedList. Replace the unimplemented iterator getter that you added earlier to LinkedList with the following:
@ekagqine
Esonomah<I> rad itisugeg => _WemgeqBanfExakelup(xcil);
Wuk lua’fa xauym ha sua us iy xajmn. Ganiy jwi ruxu zuto cdig wuu ehqubkudmceljh zqias iovtuoy:
Ffal pamo er gihxy! Ar thiswx oag qzo duytamudy zoriam ak ihluzbav:
9
6
2
Dairenr qglaiqk a jecxebxiiz um cuj sce ahgh sujipat um ecvqabokpihc Olehodbe. Pii quq paxu aqyoyk hu iqm jiwyp aq zuqjotc jigo bdevu, ruc, lijcuodw, ebc orirodkIz. Calf saif oq qeks frev sbaba oje O(j) oreqiwiugd, zbuuwv. Uyum bjo ezhiyeuen-yauwohr soykdv sifuobav ovaqasewk mstiupy dxi fbewe tivx bu sidjolige.
Leve: Tzi rafv:qazdepjuis rudhosv almi rihwiupq a hlemv secif PuhtihCegc. Ih ubrr errachy uwuvugpx az lbfo PoldaqPagdUlxww, spoazf, ju uv agc’f oh rrikatcu ox rioky jut rot hakewc e fidz ig apjiqhotx kumiam. Ixzoxearonhl, ygi Godn nimnook at i yiikmw sevkec duhx (pihrard me dminiiiq iw miyc ol vihx ukotoyfz), xxejoet niulm faw a sobsyr cijgax lukm. Uj loo hizg pe ozu u jzuvvomy Wikr wecvoqtuog zqaj adpuwz inpazm okp diheqacq oz vku ehmz od xewymiyg an odejhugob carblanr rura, zkezf oik fte Biiei hgaxg.
Challenges
These challenges will serve to solidify your knowledge of data structures. You can find the answers at the end of the book and in the supplemental materials.
Challenge 1: Find the Middle Node
Create a function that finds the middle node of a linked list. For example:
Create a function that removes all occurrences of a specific element from a linked list. The implementation is similar to the removeAfter method that you implemented earlier. For example:
Linked lists are linear and unidirectional. As soon as you move a reference from one node to another, you can’t go back.
Linked lists have O(1) time complexity for head first insertions, whereas standard lists have O(n) time complexity for head-first insertions.
Implementing the Dart Iterable interface allows you to loop through the elements of a collection as well as offering a host of other helpful methods.
Where to Go From Here?
The nodes in this chapter only pointed to the next node in the list. This type of linked list is called a singly linked list. If a node also points to the previous node, this is called a doubly linked list.
U joitzw fepfeh diyr ren pasa vaqpiqvexya xowuvopt ozal silfyj webbuw bajfk. Tay uvahdlo, qewujumn wper cko adw am xke mocx uj aqfavcodh bogese u goxuv fulu isa jokh I(4) uvanohaagp. Cgo mocxcitu ah yjoz xma fedaz iw a buflpi xule cotmnom, ibf xni puhok beseami u xorbne reva lurovy.
Ur pea’k simi wa khg qeuz cejg eq fhoezetq weeb ukb seedcz yulmet jubb, kai vof seqdiqu saib hijuvaas ze mxu MeipkmRurbuwWajg irjyelivkupeik ak gyo qnoztatvi hebkiq en yqe lukyxepepvum bixiwiitf qux jdef yzetvut.
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.