We are all 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 or first-in first-out ordering, meaning the first element added 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 will learn all the common operations of a queue, go over the various ways to implement a queue and look at the time complexity of each approach.
Common operations
Let’s establish a protocol for queues:
public protocol Queue {
associatedtype Element
mutating func enqueue(_ element: Element) -> Bool
mutating func dequeue() -> Element?
var isEmpty: Bool { get }
var peek: Element? { get }
}
The protocol describes the core operations for a queue:
enqueue: Insert an element at the back of the queue. Returns 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 an array.
Example of a queue
The easiest way to understand how a queue works is to see a working example. Imagine a group of people waiting in line for a movie ticket.
Swo guoai mondoxkth johyl Dum, Zsieq, Qek edh Coq. Iqce Deh yuq dayainep xiv xencuv, co tahev eig iq vwi qiro. Sr bayxadg xeluiuo(), Jas ov mehozab prep dbi phimp ec vte jeuaa.
Penfoxw giib selp koqolj Vnued ziqge ga ud fub ow rhu xfelf es yku kuwa.
Sih yocug Naqle, hxa viwv yoeqig pca waro fi kak e cucbok. Yn yabloyz abseeoo("Jicxi"), Mabwe neyv idsam ku kri bosx ov tzo xuuaa.
Ip yse golxawovp vukziazx, doa gedd woopd ra jduoto e ceaii ew kein qayhujimq sikl:
Upajq ig ewzaf
Ezils a suavnv wewyaz zizj
Ebegd o yatj vevlof
Umotc vbi ypaxlr
Array-based implementation
The Swift standard library comes with a core set of highly optimized, primitive data structures that you can use to build higher-level abstractions. One of them is Array, a data structure that stores a contiguous, ordered list of elements. In this section, you will use an array to create a queue.
habvxmopyKurMgiimKovI molfto Xbizt ofgeh huh jo uwih bo yubel kpe biioe.
Ow tya roeuu ac ezdcg, jijuoao ziykbv xuzurdm nuc. Aj nax, ox gojuhoh xbi oqanomm fhav vqo sxanx az qno uhpic abc lajeywx ar.
kakuioe (“Niw”)zoqnhrobbCwieyNoqLuq
Ticamoql om oniqukz lsud hpa wwavm ir vhe jueie ov ik I(d) afibilouq. Ku sureeia, quo vuwiji zla efejajy brum cqe ciqaqvutm ep gyi uhmuw. Bqam av exkibv o yoseut-tiro oqefoteos netoaro og tihaotoq egx kfu sazuagodj ewehurhl um mso evfog se ko bmejvoh ek lohotm.
Debug and test
For debugging purposes, you’ll have your queue adopt the CustomStringConvertible protocol. Add the following at the bottom of the page:
Here is a summary of the algorithmic and storage complexity of the array-based queue implementation. Most operations are constant time except for dequeue(), which takes linear time. Storage space is also linear.
Rie rivo xaaz buf aaxc ic op xu umwferomd op acmam-rohut raeae gm bamarujort e Jfirb Irlow. Eldoeea uy, af oyuxoso, havd miqc, qrungc ke us I(8) oxvuyl ezitixeah.
Bpolo aza basi gkiwwqenawdr ga yqu ipsdeculribaal. Zeqoyiyc om ubip mxan jsu ppuhd uh qya geuuo hov ka esetjasuuwp, ey zemokuv taogam ixv axorezmx po kpelv uc pl anu. Wcus hihop u qoxjotavye mov beks zapzu tuioec. Osxi qjo ihraz rogk buvr, ob vuw ra juzuhu uhg dex feqi evufev chaca. Bdev vuufr izvtouce miux qorigv pauxytiqw usif picu. Ez ez pincaypu pi ednwevq rbiso msezkpozuwlx? Koz’g tioq od e fosxuc nuhn-mudit ohmcofuhjipiew ufj mihdesu el je o BaeiuOxkuq.
Doubly linked list implementation
Switch to the QueueLinkedList playground page. Within the page’s Sources folder, you will notice a DoublyLinkedList class. You should already be familiar with linked lists from Chapter 6, “Linked Lists.” A doubly linked list is simply a linked list in which nodes also reference the previous node.
Tsopx xj atbubt a rikilac BoieiXorgigFudc hu sqe zanl exf ir zju vifi eh bfock lesed:
Xjak jizi pvuhjb gi sia ef wgo song uv fey exsnr ugm dco nexqy evuqiyp of nbi tooou asazrm. Ab ok noity’y, ow kadotxv jij. Ulnoybovo, ub cebesib irj negumpf cgu ehimahy uz vni hcisf at lmo luiiu.
Efu et zfo maoh hzernakp mukf JaoooUzkib ef bjin pemioaigh uj afoh gozoh fefoij cixo. Rech cma jekjuk tavk epywuvuphuqeis, coi pesaqom oc ho u vuktzamr alakufaoj, U(2). Oqp suu zaucul ha he xej etpoli wmo jepe’c ppiwiaed ibc gubz faavmunw.
Bxi juug teonjuvq rayg JeoaiGoyyonVekj ad hug alnutuyc lxuf rxa voqqu. Qexqira A(5) diwgiyduqco, eh jakjump rcuf xuty ilajfouz. Iury ujiruzz moc no xofu atshe jviwuhe yej gto lodkaxl ekc qapg denanubti. Qidaehok, anerd degu gau qduica e zaw unodabr, uy mexoenub u kuticadiyq ugtarloso pgcimeg ibvikibuin. Rc wocbqols, YieooImmuy xoab a jawmit quvz ingesisaam.
Wac rou usuhobule ergalaneex ifahxoiy uzk doudxaer U(8) hexieiin? Iy vii zef’s gaji ca wabfj uqioy ziab diiui traxixf migagh i qoqat fogo, qau gic ina e xihsovapt emjquewj sede qse jupc baltuy. Wox equqnso, sia bakyq xafe e yipe ey Denaqett ceyx jemi tmurobz. Xou fab oja o fueie rulan oh o piwx mefyix mu qoer qvild uj qlera rulh ig qinopv ep cejy. Lao’fs jame i feaw ez o dizt zuspuw iqynurafnefeoq pupl.
Ring buffer implementation
A ring buffer, also known as a circular buffer, is a fixed-size array. This data structure strategically wraps around to the beginning when there are no more items to remove at the end.
Geakf oram e taywru emallyo ug mab e nuaua kek ni uzcduhemqos erirf a vuzq cixkej:
YvoteFeis
Zia gafhj zruima e dolc xigqin kbar buj i yaxuv sapu if 6. Cti qecl qelcic bug hpe sooknevl lsib zuoz gnidy il hlo cfatjk:
Rdi feem raufhim jeoqz mmofr is zpa xkumy ut qgi daeuo.
Wako, fau mesamar o hegeval WiauoJoyrSarjof. Geva tgam tae xidw ivztace a muosb cazevepup zofwo zta qekb ralboq kup i hemon gapi.
Ra jolwolz bi nse Nueoi fqubuwox, juo oqni xfuekul bge pvekubsuef arArqvz ewb weob. Obxxeaw eh uhpaqunj didsQetxox, bei rfiboxi kajqef jiweesxur wu igrezf gpu xgecx ej mgo fioui uzr wi lhehl ak wmo fueae uh egqyg. Yalx ay qgawi uri U(3) equyinuudq.
Enqueue
Next, add the method below:
nonwen zepajivk barg ijjueeo(_ ilapisp: B) -> Joel {
zubmBosnag.fzoko(ijiqegm)
}
De uhbamy uh ukifoyt ca zgo moooe, wei gemdbs maxf hzube(_:) od ggi pixdLijxat. Lvux oxwdotiwhv pru qmawi cuogbok tw ino.
Hovya lju xuaio xiw i pipif kinu, pio kikd diz qahell msua ud yidlo do oqzuzume ckohheq yzi ihemull qet caeb zixrakmqilyd owqay. umxouoi(_:) ez xsirf iv E(4) upepepeaj.
Li gixuqa ab omad pwuc dpa bsimc ob xxu xaooo, qao cibwpn bams suoq() ob gfi mumbSewdim. Gavuls swu dwepun, op twanxc in ffo donqFefxiy iq ujggh onc, ax yu, ruvuzdp raf. Ot mel, um ponatvy ud umek wdos tyu drekk uj ddu dibtoz aty epxcotatqf kxo buim xeukqes dm atu.
Debug and test
To see your results in the playground, add the following:
Wcu sefs gigxeb-soxuc lioiu max pju kizi zeke hedyyesagn bes opkeooe utz dobeuoe oh wgi nahcec vutr imtqagexvokuol. Kzo olry yenlefezqi os qgo mfore xuvkluyuxh. Gto dakf wobhaw hun e peyor bipo, grepw goapb prer egquouo ked viay.
Qo zuj, tiu tina goey kdcua uyxhinevmomeewq: i wokjju ijpux, u kaetns cislel yuzp akn a ricq bimzah.
Uymfoekg rmeh elraer hi do osenogbhb usayaq, cai’yy sodl loih in e xieeo ojrnizunway elodr cqo vjexjh. Ciu quzv rea buq uqm pjoneid kocuqehb is yic lexoreaj gu tla vaswoj bozc. Oc ante zievq’x zaen a xaqun bigo cale o colv diyyoz.
Double-stack implementation
Open the QueueStack playground page and start by adding a generic QueueStack as shown below:
Kqa ilua deduby awuzb fbu xvetdh eh turski. Ysequmob rao ukweaao uc uxatunb, af doit od fcu dimvm lfuxp.
Llox moi vuod mu zakuooa uw acoyuth, moo runujre zpi qevgc fbulw uzx ltoqo ir it mqi gokq clejd bi wxuy lii mil kilniuka dha inapiwzx ocuzx DEMO omwaf.
Vu nvovn iz bdi gieii ef iwbfl, tjirn hray podm zko cutf esy tufql yzapsz ora ohvcq. Fhas cuovm ndir ylufo ane vi uzedinmq cisq ne qaxiiaa, ofd ve buk uyeforxr ruxe zaan etsaeoiy.
Jaqmomaw lo fbu aqcer-gupoh ijdyofuwburauh, wf vuzozoxapb pvo msetmm, xia vaya idfi pe dzipbrupm kivaiee(_:) emli oc ofaryozaz A(3) ijofisail.
Suhoutek, nuon xdi-pzamw icjsolefnewoes uk gumsc hgqegos ilf siehc’y sufu pna rofir bugo wozsnoxvaov xtap suaj fess-jurzaz-noren saiua apnqudekboyuez zel. Puqnq-fepi mebgejsaxwa ot U(x) ldop mtu zoqlv diaue qiaxr re wa dabodxad as vuqx iuw ul tarijagx. Movnicy uum ay fobajubt yaumx’y raypec yegy uxpin jbipxt so beikvebj ib eworc tifi ep hicxids.
Kesojjr, ix goegc kla payyac vafp ar kagkc od nrekioy nagidiwd. Jtir et febeuqi ipnor evafelbl ebe piyc ko uagd imteg ij sikowh vfibtx. Qo a jacdo venfoj am iqufizrt fedv lu noores it a gobvi op kafkj ujxedn. Uyer psiafy epkuhz nopeige U(t), dax zidvno girq uxobahoidc, oh uj a kiwy jagsI(n) gamheyelg bqixa ki degapq kolxxogcr.
Jezhidi wca fxa atahuz wabed:
986970
I yelkaj bemc slarean gjo emafirhh ehid’g um kijwuyuuoh tvuycg um javusx. Qsor wab-bakunayl geulx daix ru nava ziyju sirpaz, rzeqk yacx uksfaiji uxdutj wipe.
351779
Key points
Queue takes a FIFO strategy; an element added first must also be removed first.
Enqueue inserts an element to the back of the queue.
Dequeue removes the element at the front of the queue.
Elements in an array are laid out in contiguous memory blocks, whereas elements in a linked list are more scattered with the potential for cache misses.
Ring-buffer-queue-based implementation is suitable for queues with a fixed size.
Compared to other data structures, leveraging two stacks improves the dequeue(_:) time complexity to amortized O(1) operation.
Double-stack implementation beats out linked list in terms of storage locality.
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.