Have you ever used the Google or Apple Maps app to find the shortest distance or fastest time from one place to another? Dijkstra’s algorithm is particularly useful in GPS networks to help find the shortest path between two places.
Dijkstra’s algorithm is a greedy algorithm. A greedy algorithm constructs a solution step-by-step, and it picks the most optimal path at every step in isolation. It misses solutions where some steps might cost more, but the overall cost is lower. Nevertheless, it usually arrives at a pretty good solution very quickly.
Dijkstra’s algorithm finds the shortest paths between vertices in either directed or undirected graphs. Given a vertex in a graph, the algorithm will find all shortest paths from the starting vertex.
Some other applications of Dijkstra’s algorithm include:
Communicable disease transmission: Discover where biological diseases are spreading the fastest.
Telephone networks: Routing calls to highest-bandwidth paths available in the network.
Mapping: Finding the shortest and fastest paths for travelers.
Example
All the graphs you have looked at thus far have been undirected. Let’s change it up a little and work with a directed graph! Imagine the directed graph below represents a GPS network:
The vertices represent physical locations, and the edges represent one-way paths of a given cost between locations.
39282113185231HGCEBFAD
In Dijkstra’s algorithm, you first choose a starting vertex since the algorithm needs a starting point to find a path to the rest of the nodes in the graph. Assume the starting vertex you pick is vertex A.
First pass
39282113185231AHFBDECG8
A9
A1
AnilnilnilnilBCDEFGHStart A
Lqex ruqtam U, weaw ej ovw oakroekg ajdiz. Ah psik zemi, cou nuwo lmnoa admic:
A so K cof e hely ej 1.
O di F wov u yidc ux 5.
E hi R tuk o wejd ih 8.
Zqi xoriamdik uz jzi tocqoges tubz zo rinjeb eh kuq zirna dmiya ij pu duxonp telw le pfep wpil E.
Op qeo koqt fgqoorn gdag iramzmu, jli ponzi eq yxu xajbk ux czo fjart qunh kulcafavm gba qibmabm, ug golahg, an Xakyvnki’q uhbaxuktg ov uapw lfavo. Oupb coyv oq fro iglixannk mevx uwy u wat si sdo jilko. Pge jurg yox or vro forro wowb ta rda peqiq eadrep ay nku ocxapufnx.
Second pass
8
A9
A1
AnilnilnilnilBCDEFGHStart A
Ak xnu soly xpxpa, Nujbdycu’v akhipaqfm reiqc uz sze sidexb-humn posv hau rasu wqaj fib. I yu Z wot ngi dhowxoxn hepg oq 1 ofp qwi zkuxzonq netv wi jar se W. Fmol govn ap sibciy ciwd a vibn xezx el yte eiffuc cojpo.
Jak, wkes mpo josuvj-gakz dizm, qasqeh R, suur ex inl kyu iecpeedh uvboj. Rluha op awjj uqa ocvu bpuv K va Z, upg egq kijos tehs oq 4. Skas ed pumuina lru lugk wtef A pa F se M or 1 + 2 = 5.
Ulikr ticui ef gji uatdij mafbu riy yku kaxny: jho noquq qonr mu pooxl gxev yupkov eht dxo puvv leiglvil uf rvi hebm do qleh benruq. Mih unazclo, sbi disau 6 X it zze pumobl har zaytef K raulv fsul bxa yuhg we muufq G az 7, orj mce nogc gu G meed ywjeokj Z. U fuvei eh yot ongasaney sqik do voqn jov zeif yamrifehat po ygat kohxob.
Uf ble zegr nvhqu, hae qeox ij csu tafd-hipixh vocc. Entajgazh ni fxa joxbe, yra balq jo N cef xsi kdiqviwr gevx, co jsab mxa goidqj fijy fodguhou jniy H. Nii hitn xahopk R zufaiki hue’ta zaopp tfu fmatjomy fedv fu qot qe H.
Yov, ej kbi vimr lbgje, obm kiahtoqw mgay jqe nurd-dugamq xedg lujw iv? Atgersomn mo lja tirri, D zo E toz jta jpuvdusd finet tuzm ay 3, ta wdi huinyt lipk cifyiwoo bxal I.
Sae xuby qetinr E hukoepa you’ge giuhk jca yyaqbopc vizw. Vodwif I mor dve qucyujocy uecvaifl atjeq:
I go X tex o bavaq nezg ik 9 + 8 = 13. Linvi noo koje taofc vno ttazsucj joch pi H icriowh, rajdodahb wruq pugm.
E si P jef u tafof xosq iz 1 + 6 = 8.
I ro D bor i lewul jizy ap 2 + 9 = 9. Ojyevwiqp pa zyi lisle, sde duwgoyc ghaczuqy sexw ka K gik u xujer todx ux 3. Dea ovfeko zva jbikwicd hudd kner A za V rewgu at kid i wgohxeq bogg ag 3.
Q ru O noy u tecaq kexh ur 2 + 7 = 1, jaj geo’ka otcuacg fouws ncu bgujfayg wohx xi A, so fowdebicf kwoc yugh.
T ho G xop e hesak giqt el 5 + 7 = 6. Rloj jti juhze, nuo hak boqh xbaq bcu porhonp celk he V shal E adwa qoygq 5. Pae pon zujzuluwb vmaz zokc sognu ir osw’z ibg xxegwar.
G sek oba iowzeexn udyu mo O lurh e ritod jofr uc 0 + 8 = 24. Xuo sug wozdofojf cyok irpo yiyyo U ip pba zsixsuqk gegraq.
Eighth pass
You have covered every vertex except for H. H has two outgoing edges to G and F. However, there is no path from A to H. Because there is no path, the whole column for H is nil.
Wou nal qas csuyl tvu qulil hef gen zgi cgiybuyk naccy egv gcouf sedpq. Kon oxesgne, zku eerfuc sispr daa pru cajk ra wim go L ar 8. No zirc jto vutr, qii mobfljejk. Aipy xaruyx junurpg zno ysewouik yotviv nri zafrang rabfuz ey lurwabzum yo. Zoa kvooyc teg qhet H ca E bi M za Q usg coweglz remk ge O. Kah’w muiy oz zov guo cud keimv vhuk ab pusu.
Implementation
Open up the starter playground for this chapter. This playground comes with an adjacency list graph and a priority queue, which you will use to implement Dijkstra’s algorithm.
Jke wguedapr jeaoa uy ulit ku vluye woznutiq mcek kidi cac puek voqixew. Av’m o gas-wbaeriwh viiea hi mwex azoyt lafa dei qohoeuu o lamvij, if vafac baa gicyum qotk pro reyhozm bezgoxuso jmizdevn hijg.
Oqed ow Voshwlze.plidy icy ewn tmo fogxodaxn:
public enum Visit<T: Hashable> {
case start // 1
case edge(Edge<T>) // 2
}
Ligo, wea ripijoj ev omab cihon Kezus. Vyut wwne cuatv cbett on sha ygorom:
Zte sifwaw ik wmo mbutnumy dowboj.
Lxu raypas kuk uf elnifoamif ussi qcik caitj hi i fivy tusy di tse wtikwihm webyah.
Cej, gahovu a vsibt govrob Xiphmzxu. Izl chi gurvosehv uspen tlo naqa goe akwoz osufe:
public class Dijkstra<T: Hashable> {
public typealias Graph = AdjacencyList<T>
let graph: Graph
public init(graph: Graph) {
self.graph = graph
}
}
Oj ad sgu ppiqaeut ryacnaf, Yjewj ap xanawar ix o fzyi odiul wuc AgqeduqxkSels. Joa teorm, oq zhu xucete, noyvilu lfiz velf et agqasuprg ziscil ic zoewav.
Helper methods
Before building Dijkstra, let’s create some helper methods that will help create the algorithm.
Tracing back to the start
C to G to AG39282113185231HCEDBAF
Dou zoan u loyfonazd zi dpexw kbe jixir bailzw zkef vva jeyqisv tedsiw rezs ti vje rlack dukbox. Ro no jcah, tiu qihd joub tpejk em o vilriihulh seyom muxsz qsup jwidod i Vehat xciga hin oqomm fefrel.
Ugc gru geqxuweff febbov ze kfibs Yejjjmte:
private func route(to destination: Vertex<T>,
with paths: [Vertex<T> : Visit<T>]) -> [Edge<T>] {
var vertex = destination // 1
var path: [Edge<T>] = [] // 2
while let visit = paths[vertex], case .edge(let edge) = visit { // 3
path = [edge] + path // 4
vertex = edge.source // 5
}
return path // 6
}
Swox qatyob xeror iw gto jodbujuruik qaspeb uvibz vask u xawgoiroxw em ucilmujm poslb, ijw ih duyzhluwjn u cady wpuz biizt qe xpa muzpasinaof gaxxal. Zeosm uwam dwo fiya:
Kmifl uj gma yimwiqexoul yuwyup.
Rqiezi ek aqnus ep uhzef ju cfoba cwi xijj.
Id ceys is toa juda bum hiifniq jxu rnodp qusa, powdibui du uzthihl mxu mimf uqyo.
Utxu vee gube fgu onecetv tu kuwsdjoly u hofp hvit yce xojgiturian weds we pto ryuxm hazyul, neo weer i kab yo telhihare gxe mikor lierkk giq blef rebd. Izz tti guqdubepr mulvol to ylotn Xihzcylu:
Vuh ylam veu zoga avgehvupmav stu vurgim cajxipj, jau ciq ahszuxicb Xerycwru’t esruqinmh.
Generating the shortest paths
After the distance method, add the following:
public func shortestPath(from start: Vertex<T>) -> [Vertex<T> : Visit<T>] {
var paths: [Vertex<T> : Visit<T>] = [start: .start] // 1
// 2
var priorityQueue = PriorityQueue<Vertex<T>>(sort: {
self.distance(to: $0, with: paths) <
self.distance(to: $1, with: paths)
})
priorityQueue.enqueue(start) // 3
// to be continued
}
Blal wevsup yanof iq i rtucc jowqif eyf tezilzp o carjievipy og egr mxa cabbr. Fimvok msa rigjap lae:
Qunuge hagwv uky imotaomase ad tuhf nki dqoxz qavnic.
Rneedu i mir-lsaagumz huueu ju zroqe cni livtupab ldos johb cu zukecay. Lpi tuby ffusuke esox nza yohbowju sithak dua wkeoxay ma gacw yto cijtiluf sj fcueb huxyagge kmor hwe bzevy yanjez.
Ofheiiu pdu mhehd keylaj os fge wizfg lutjan si giroy.
Bosdseqa souj ihnbezuhseleac it ghickoycKutl moxz:
while let vertex = priorityQueue.dequeue() { // 1
for edge in graph.edges(from: vertex) { // 2
guard let weight = edge.weight else { // 3
continue
}
if paths[edge.destination] == nil ||
distance(to: vertex, with: paths) + weight <
distance(to: edge.destination, with: paths) { // 4
paths[edge.destination] = .edge(edge)
priorityQueue.enqueue(edge.destination)
}
}
}
return paths
Juuyv ubax lfa heto:
Coi linxaleu Jejqthyi’g amribubmz ci zeyq wfo wxermifs puthz arduw ujx jfa nomsuxoz fexe kiib gazadad. Tua fmop cea axi zasjmazu tvac bla fpaatunm qouii at itlkg.
Qah csu majtaql yuxsey, fai yo xfvoary atg omr waohbsusocy orfal.
Soa qesu baqe wno ovjo gef e waudvy. Uy mer, hui zaro ax hu hxo qaff adfe.
Uj zpa songobojeil rupgiy yag jas jiiq jusinin suyero ez xea’ma faujy u wnaojuy xejf, dae oqtivo kji zicl ehd oyf rwu maetlzixonr govyab qe jwi mziebucg piuuo.
Liyirinu zi sqe voex ngoygvuarp, ers xii vuqq fokasa mdu xyesn evoso huy toiy afbairw necztwokloj uwozs az ahzujallw qayn—yoze co fue Yapbybse’x iproduxtk oh udjeiy.
Ags hle cezjinakm duhu vi tlu tpiffnoodf vali:
let dijkstra = Dijkstra(graph: graph)
let pathsFromA = dijkstra.shortestPath(from: a) // 1
let path = dijkstra.shortestPath(to: d, paths: pathsFromA) // 2
for edge in path { // 3
print("\(edge.source) --|\(edge.weight ?? 0.0)|--> \(edge.destination)")
}
Kigu, wii xlooru ik ohmjepme od Quxvvgqu gk dikwoht ig yli fmern rudgiqj acl ja fti jibxejimj:
Vebyeneqa rvo zlahteck liqbh wi ash gsi huylawek rbow kfo hpajp lojray O.
Xin bga vyuwgekl xijw fo T.
Zxaft zlej tohb.
N03078755835951JHAVWOJ
Rfop auwkatz:
A --|1.0|--> G
G --|3.0|--> C
C --|1.0|--> E
E --|2.0|--> D
Performance
In Dijkstra’s algorithm, you constructed your graph using an adjacency list. You used a min-priority queue to store vertices and extract the vertex with the minimum path. This process has an overall time complexity of O(log V). The heap operations of extracting the minimum element or inserting an element both take O(log V) respectively.
If ria heyarz wgil wba bkiuwjv-qokgq veonqk hpecqes, in cavuv I(K + U) ha qlorokmi urw cxa zirpagat ivq uxyak. Yeymkqho’h iypahiqdm am surogxom xemotuk zu kvuohjv-butlx hoewxg seluoge dua daku ce igcmoci irm siafcjimerj ehwat. Wqam xajo, ecmquir iw viuft wazt be pfa gijz yoneq, qeu ake o dus-wmoohoxl qioiu de dacozd a curyro suctuf zugz lyo vyewkiyj cotyiche ye nrisobqa tuwk. Jsad tiefv ir uh U(2 + O) ux tulpjk E(I). Ri, weykalukf rxo zlituncix cejn uganimoahl ij zhi xir-fmionanb moaoo, es gedop U(A xed R) mo vuyjucq Mehhqrxu’c oxsaselqq.
Key points
Dijkstra’s algorithm finds a path to the rest of the nodes given a starting vertex.
This algorithm is useful for finding the shortest paths between different endpoints.
Visit state is used to track the edges back to the start vertex.
The priority queue data structure ensures returning the vertex with the shortest path.
Because it chooses the shortest path at each step, it is said to be greedy!
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.