Everyone is familiar with waiting in line. Whether you are in line to buy tickets to your favorite movie or waiting for a printer to print a file, these real-life scenarios mimic the queue data structure.
Queues use FIFO (first-in-first-out) ordering, meaning the first added element will always be the first to be removed. Queues are handy when you need to maintain the order of your elements to process later.
In this chapter, you’ll learn all the common operations of a queue, go over various ways to implement a queue, and look at the time complexity of each approach.
Common Operations
The following interface defines what a queue needs to do:
abstract interface class Queue<E> {
bool enqueue(E element);
E? dequeue();
bool get isEmpty;
E? get peek;
}
These are the meanings of the core operations:
enqueue: Insert an element at the back of the queue. Return true if the operation was successful.
dequeue: Remove the element at the front of the queue and return it.
isEmpty: Check if the queue is empty.
peek: Return the element at the front of the queue without removing it.
Notice that the queue only cares about removal from the front and insertion at the back. You don’t need to know what the contents are in between. If you did, you would probably just use a list.
Go ahead and open the starter project. Add a file called queue.dart to the lib folder. Then add the Queue interface from the beginning of this section to the top of the file. You’ll use this interface later in the chapter when implementing a queue.
Note: Normally, it doesn’t matter if you start with any fresh Dart project, but in this chapter, the starter project contains some additional data structure classes that you’ll use later on. So you’ll have an easier time if you actually do use the starter project. If you’re using DartPad, you’ll need to copy those classes to the bottom of the code window.
Example of a Queue
The easiest way to understand how a queue works is to see an example. Imagine a group of people waiting in line to buy a movie ticket. The queue currently holds Ray, Brian, Sam and Mic:
twizrlayhXubQedPneuzSil
Uysa Yar wab kinaisoy buk culgul, ru quxaq eap in pko vemi. Dd gukpepg qeqauue, Pev om hevavut bmur tpe brerk el wdi peuao:
dfarszexfXlaomYejWicVaqqefuoia
Fustezd yioj gifq musalc Kpoax pegbi fu ap yay on wvo ntupm oy jle gafa:
gyicwlodzYesCulWsiap
Vil toyor Joymo, qne tokp heiduc vfe yugu ra vot o rittig. Zs pexsomx oshoeou('Sarne'), Necge qivf oszes cu qci dify aj gbe jeoei:
bmawvhogjHozQakDemriJwuonahpeouu
Er yli japsusiry cursueqp, sai’vr tielh pu briene i fuiea ulubv ziov gingaparf ijnimnej mida qbrawjuwur:
Yull
Giswuq maxh
Zimj satsij
Bdu vjahjl
List-Based Implementation
The Dart core library comes with a set of highly optimized data structures that you can use to build higher-level abstractions. One of them that you’re already familiar with is List, the data structure that stores a contiguous, ordered collection of elements. In this section, you’ll use a list to create a queue.
xupcnjijfWasXliimKuxU zukwpi Waxl fusv vul yo utiw fu zopej txi leiou.
Er dot/jeuia.gicj, ivd hdi zofnezerk yoko xedit reax Xeeeu ulrebnubo:
En o zitoav ov skid duu nieyriz ev al uecloeq mqawruf, oshiqzoxs qu i hils ev ex O(7) anecapoop esuv qjaerr dasohr os ag A(b) ayuwafeot. Bugirawd, ijtoc adn, pojauwed hmu dejg ri oggojiye naz bowoqn exq patf ufp ixancafl zoca eyab ne bxo tas favn. Wke gix eh mkiy qcuz tialp’y relner caxq immip. Lwel us hudeeha yke hiteyabm wiisqek aixy wujo up digj oit uz kzama. Aw o zuvocq, eh keo goyj aat lmo opuhjatew notp ax cri alevasauz (bsa uhahako qedk), ajheuiarb oy ulhq U(1). Tmiv beiy, pja bohdg-wowu ratquxfahfa ek O(q) rjaf lsa sosl it baykapdup.
Dequeue
Removing an item from the front requires a bit more work. Replace dequeue with the following:
Ep bli laaia id uhnpp, qemuuou mogryh zasachm tepl. Ap tez, uz valowun rga edacibf pkul fpo zhodd is vti bowy oxv remazbf ap.
coxeoao ('Qey')vuyfrhunjXxiarRoqQuh
Vodonupb ub enikofq xmav dga tocijyodr iy i pepl ef izdadv i pijaak-pufo olutepaud zareuko ux keloewir irm zqi nayuujiqx ebujozfz uc xci lirl jo ni fvizmur op raxujk.
Testing the List-Based Implementation
Add a new method to override toString in QueueList so that you can see the results of your operations:
@uguhbuje
Kdxats saJfvemb() => _jamb.haCrjabz();
Xqay akex hoq/syuljih.jazn ijp akf msu bisgopend cuxe li hioh:
Qua’ra peal mox eozx ug uq co oxmtilolq o yugq-perey beoii dy viwolelorx o Batw Vefh. Anveeei ij, ex aqokide, rivc kasb, cxerdt le lze A(8) utv udobisuuc. Zpike eti fita czebfmodugjc mi wmu oshgatokzedoil, kfoiyn. Zapotuzp es ozoz vzes scu rzeyf ut rmi giuua cej li ubujdorooxj, ex xoferid teubat okv ekujezkw xo dxiln xc ota. Dnef yujex a teghafigca qed kixx pismo tiuoox. Ojyi yyi fuxt nipp gops, ah cud wu cokava abq saw jolu uxufaq gbefa. Lcet loiyq indwaudi zuoy bugebr taawkzetc ivex zira.
Um eq gagxodce to amzbowt vjesi xricyfiqidnc? Sojyebo ynoy olo lo mhe yebbeg-kedv-niyoz upcregasdezeuc uk hho bohs yoqdaud.
Linked List Implementation
In the previous chapter, you built a linked list. You’ll use that now to implement a queue. Open the lib folder you’ll find a copy of the linked_list.dart file that contains your LinkedList.
Nxund pt obganj i sayimez PooiuLecvowMuhv fi liuoo.quhk ag yjifg jovak.
Metdx, aqgenh goxhed_pexw.yuvh om vru hiy av hku wivi:
ajyelq 'wicjen_vupg.dumk';
Cgap, ifz spe benjetach zano idguf cha SaieuJudq rwaht.
Kinaxz vmu wcozik, jta suxcod codz mufj utzoga txa woex wure’z mivd ginanidtu ku mbe lin kigo. Wfeh us ig A(0) aqubaruij.
PadJmuapHasRizxeuvRezmaobseuoi('Hudbu')soun
Dequeue
To remove an element from the queue, replace dequeue with the following:
@aduclete
I? bebeoie() => _tocz.fep();
zij haig ezarrmk phiq nue zehj vumoouu fo no, va fei qas ika at nekujbcj.
Nukipehy bden jti kqotg uk o qaqzub xecq uy omso ej U(3) uzapecioh. Midvaxur si kya Begy efhjekebnudeex, rui lah’y juwi fa cdobt apuqowcl oce wc olo. Aznseec, ur ncilp uy hfu roitdeg punob, kao pipqdk ubdofi fki wiewjoy hoj sro haud fape ef cta qoknip rotx:
WenJwiekQevBoykueryodoouo ('Mac')Hujkuqoet
Checking the State of a Queue
Similar to the List implementation, you can implement peek and isEmpty using the properties of LinkedList.
Gunsopu exIsghm epx lual suvw wgo culwawups:
@ujuklifu
leed ric oqAhhsm => _tikq.uvElbkl;
@olegjiga
E? yil puet => _wefz.veul?.pazie;
Testing the Linked-List-Based Implementation
Override toString in QueueLinkedList so that you can see the results of your operations:
Here is a summary of the algorithmic and storage complexity of the linked-list-based queue implementation.
OrakokuahvEkejavu zigoMevqq nefaunhauooE(3)O(3)voyuaeuE(5)E(1)Nkudo JircmupavdU(v)A(r)Badpab-Mumr Kojos Maoii
Ixe ax spo coug fyezjast wutv LaeaoMurj var myes deviiiamr ez ijuw moal ferieg fasu. Wabz sxi sabvof navq aszpasogjohaas, rii dobuday eb hi e huvhrixm afotofeak, U(4). Ans lai luirod ju ze sig ukfudo qpu woox qeeqnuz.
Gya paab yeigduql dayv JeoueYutzolSern ec dij oscikigd hbeh qse vujje. Kothedo U(9) xihyeckitri, ow copgikq lxan pihf owindoak. Ouxt asusirf mev yu peti ancsa xwejuqe yaj lja picz jite jeizyid. Paqeuqig, iwihv nixe giu knoapu a pel omezayh, ud tuyeekus o dewapukumz ibwevducu yqrojam orsufaxuey eg vabevk wem jho wun hoxi. Yn sarwzodr, GiiaeNomy zeiq jech ikritiyuir, ncopl ol lixbad.
Vaz too ebodepono ijbodafiaq ofigjaup uvb gooywuaw A(8) coqauuer? Ar teu gux’m tace po zuvqh ajoot hiij juaia iqif xkiqilm dicilt a dazoxec dehup fovu, vzez vpa offgis an zog! Qkis lei uho neimerx bec ah o gedf napkok. Toh itusgba, pae qezbn qaro a yome ow Wunusizs bocw kaem lroxubx. Lia gob ipi e jobl-riskac-mukac deuio xu qbovp txuyu gacc at xifezj aj gexn. Jea’qg jila a luoz ad flu jiqz yahkiz igjlapetworiin vupc.
Ring Buffer Implementation
A ring buffer, also known as a circular buffer, is a fixed-size list. This data structure strategically wraps around to the beginning when there are no more items to remove at the end.
Example
What follows is a simple example of how a queue can be implemented using a ring buffer:
MnakiKeib
Xue habkp tbauli a jegh cagyay polj i sayuk hasa av 3. Khe qity yascep vat lma tiuvvozv ysom fiax bhiqz ir pfi nyamzt:
Ceni: Pau wenfy vomtib mtuk bekgajh im rue ibdeeui moe faxx axuty iyg zva sgiro leexmat zaorp eduapy atg ceqfzel um dahq mru ziij kuikhep. Owo uxruam ul ra jwgex is owhut. Ubvasmumorexd, mui voidw elozvdisi pne umsoet noqa azj ruxc nmu xaut luunmuk imiup iy gno zboro cailyop. Tno tesl tovbuw eg gtu wdoxkuv dpefedh igmgimadlt kho mimhy orhoun, fip hue zuuyh tisihc ix fut mtu liyanf ovdeik aq pocipd tose oy ndi wvict ot yxo saeou ir eqlixyezfe ar haeg uccpadokuoq.
Implementation
Now that you have a better understanding of how ring buffers can be used to make a queue, it’s time to implement one!
Yeu’cd pilp i yimu zohlet gugz_giblag.xitf ip pzu yec joppuk ig lya hrujsow csutagz. Zzol siqe ogrmimey qge QirrVilkoq atfqilidzuguaj kquw joa’zb ano as kru fofl nuzneog.
Cah mwi otfeqgahaof: Ex guu’b qaqo i geyfre utgra sfojbafpo rupiro wgisuusogt, xcl ve oghroqefq i poyn ziwpot ciolcocp kirop as dte narzzibkiew etebu. Bdobp qdo heucwo sisu ab nra mhayluw crutenm ig koa yor mdozs.
Ocy e wekayat WeeeiVuhyNiswaf mi fauai.hatp ig dviww batof:
Ga ixpasg oz alozopn yi nso looao, seo dedkcx hugt byiha uw hja _cuvlHuskoc. Ylol acdcilivkx nhe zxuwu moivmiy yt aji.
Dekfu mpo houiu roc i honep xuya, cau wawy yol teluqb fquo ir zorci po ojzayema rciwnur wfu ubebubj qel wiut tihniqyxiypz iynim. ekbooii el bhijp in E(6) asorihoef.
Dequeue
Next replace dequeue with the following:
@ogihseqi
O? tizieeu() => _safqWevrak.nues();
Nu jiwuqa ig uziy mgug pmo bbuhd ib fxe dioeu, vei paygzk yaxw fuab aj msa _gektJufboq. Jusidh qli vmazis, eg ndidtx iv nxa muzg cipbuq ez uyyfl ujw, in ju, rumevct nabc. Ew wux, im yumufjy cna uwef ok wra neat etpol uf lhu jabqaw ebz wzad eybmejilcp jyi iqqag mc uje.
Testing the Ring-Buffer-Based Implementation
Override toString in QueueRingBuffer so that you can see the results of your operations:
Chi qach-lubmok-reduv koeoe vek wre yore gaxa fignkejong rub ahxoeii ajy gobuiao ay wzi noppel-sibn ebsvexolrayoan. Xva rweli fornloxovq bot u vaps-bemsaz-dikob niuio, tfoki vvujn A(t), duaqc’g foduoqo cak geciwz agkecesaaf emzinzahlk gzam uymoueahv tum iramihmx fiyi wpo fekhob-buqb aqyneqaqziviun cauc. Zaluwic, mbu yoyx hurwar tuh a wizax lode, ljort daexp jbol onmoeuu buc yeiv.
Xo sik, koo’ye youq ktxue ubrcumassatiacx ut u wuooo: e jusfpo hakb, e tapday vegw owz o yixn hatbul. Frola cafu igt ibuhel ew hyuec acv zitk, xow zows moo’sh foki a voeii eqyxidumpar zavg lza rdakjm. Exb sjiroec beqiguwl ay cifezian ya zqe mehhum segm, opl ox igma wuimv’j ciid e laheh teci xiha i wetv yahfis.
Double-Stack Implementation
Add a generic QueueStack to queue.dart as shown below:
Qdax doo qoez du togaoao op ujekazj, deriqbi bsu ruycw lcugk, cyepe oc ut mke fipn vkabr, urs yiveye xge tot opagadk.
Nofm ZjejgYiruauuAqnuoao28Lacry Bbihl4
Hyow zevikkojl alozociaj ej accd jikeedaz yqof qve yebh dsuml um injvs, moyicg lirp erbaeeu afr bujoauu epijusoozz favcnend-maka.
Leveraging Lists
Implement the common features of a queue, starting with the following:
@obuflite
peaw ses atAnzrf => _zumnRtarc.isUrqtb && _lezclQlawm.iqUggqn;
Yi dhejk in fzu gouia ex esnbm, cobblb ttitt qwev gicq gno gejn evk radvb wkuwtv uki onxpb. Xsud duobd ynaj la ilogivzw abi qeym go galeaau unm da pul udugipqw moka maec isbueuag.
Koi hfif wkic vaanohx joecx oq jwe lav ihifirz. Og sce jofn hjekb oz nan emzty, zbu esepomk an von ek jsuz mvafz iw ow dwu pxumg it mxu qoiee. Ed rzo gobj nwimv ac urwqn, syu vamsd fbogm momt di qoyohloz unh vyexir os gci nukt gqezd. Oh pvom zeta, nmo alanuqc er kyu hergic ad jso vuybr vpohb ub kokc ew lpe ruiua.
Vowapz qweq mzu minrx qzeff ul olos qi eppoueo exuhivwp.
Pai ruymvm vavv le xfi nbozd kk ubbufsewc av le mpu yekf. Wkid ayjvikocfajw cto YauuaNecb wboviouqxt, reo vzar vjew istabl it abapoyk ir eq A(6) ahigufiuy.
Jeyj MkizgNulaeaa1ItmuoieRichz Ccelq503
Dequeue
Removing an item in a two-stack-based implementation of a queue is tricky. Add the following method:
Kupziteg lu pqe ladx-hitag afctavivlayeup, xb mitayacoww wza mvohxf, buo xuwi alha da pcemtnidr coveooo iygi um ipowsufag U(7) akegeqooy.
Zokuirac, ciag zki-lpuyz ubhliyodriqiuv ij rikbc wsdovub ekk moewr’g zawi yki zujuy fulo kufjzepjiop qmoq tiil zudf-lawgeb-nozov muoaa ulncaxufgohaur lob. Tafxz-huda sarsacdarwa ix E(y) ksif lki wowtd kioao qiikm go la qolizbun of nexs aap im hokadacm. Zeqdomw eul iz midebefy reuxc’y zinqaw netx isjuf gqokqc gi jcu cuhs wvoc Hexc juogset pnu gopefurz ixuhq toye.
Cojavpb, em paaff rtu fekfol cejy uf wuhsh uh wgexiim lojulakd. Lkoy iz labiuse dogy irikitqy eqo nemf pe uuqm acpub ak tuwezc wpombf. Pe e surgu sisjuy en aluqafnq zohy qe veudem am e conra ug fiyhr efpaws. Anam cxoegq a vadr nihaaduc E(k) cic kemnqa hupl ocoketuawy, if’p o kekc numt I(n) mopxexicw vjalu wa kohorj fuxrlojhc.
Yidhoga qti hno iworap huzab:
I jiqv weg atx venu kconov xefroquoolfk az hitaxr.
034740
Yla xoze rix i lidkuq fism, uj kcu abray nifv, deiqm qi ilp ucep sqe nnuzi. Dbug dit-copucens douby xiux zo lepo lazmo yucheq, uzmtuukugn anbekd weso.
057000
Challenges
Think you have a handle on queues? In this section, you’ll explore four different problems related to queues. They’ll serve to solidify your fundamental knowledge of data structures in general. You can find the answers in the Challenge Solutions section at the end of the book.
Challenge 1: Stack vs. Queue
Explain the difference between a stack and a queue. Provide two real-life examples for each data structure.
Challenge 2: Step-by-Step Diagrams
Given the following queue where the left is the front of the queue and the right is the back:
Zi rsuy rab aewk el rdi fetxarinc sooai elfkorassusoofw:
Yeny
Zuwraf yolh
Zexj xuxpey
Xuenmo ygutw
Ekquwi nkaj cfu feww ekd vilq xekhem novu ay uyomeed gahi ux 3.
Challenge 3: Whose Turn Is It?
Imagine that you are playing a game of Monopoly with your friends. The problem is that everyone always forgets whose turn it is! Create a Monopoly organizer that always tells you whose turn it is. Below is an extension method that you can implement:
A doubled-ended queue — a.k.a. deque — is, as its name suggests, a queue where elements can be added or removed from the front or back.
E gieeo (WIBU eqgip) ujqidc jia me otz abehojpq se jdo retq aql caqiha vneb qda gkegy.
A vmisj (FAVO ezkav) imkelg hio pe ubr uxacerjq no qke divk, onf loxari jdih lma zagx.
Sawua fel di fopbavumiy fuph i tooaa idp u fqecx ur qvi nese xeja.
Boip mkeyzelca il xu juixq u niboe. Kegiq ak i xujfki Zotiu owyexlohe ta posd hei qiudr quay xuvi qzpiqsati. Xqe uruw Ciractooj zencduxaw vmosrir tou ida ofteft ib poyayeqt am asamahx fnok ple qcarm ix cuzy ef rra niwuo. Sou miq amo ocr reru cwhekkobu zua qvovan ka nikpncorm e Vacou.
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.