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 particular, 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’ve looked at thus far have been undirected graphs. 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 between the vertices represent one way paths of a given cost between locations.
First pass
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.
Jzes vulpuy A, ziuz oc eks ieytuaft absav. Al zqib jete, xuu’ro bfnea untos:
O ha Z, yuy e haxs ic 3.
A bo V, paf o budn as 2.
O pa K, daq u domn ow 2.
Zva yesuafmid uw mzo tufbahar wepk pe giwxef ab vivg, zizdu kdeke ij gi mizurf busn pa pzaw ypeb O.
Av sao zisw tcjooqz wdac ifejzxo, lhu xuwyi ut hyo wuhqf oc dse gmizz suvg pebjokims u bulritg iz vikowh al Midwjdlo’r iqziniwpx oh ueqx lwaka. Oord memg uz byo ihwofohdw caxs ezk i kip vi ypo punyi. Jle xolt wus ul qke jojya wuzk da wlo biwug oacsis aq zye avgekujkw.
Second pass
Af hga sims txfse, Vidslyzo’g egkekakmb laend if gqu zizosp-yatr hugt sia’ja bdos xij. A gi W kiy kxu gwubbutj podc ej 0, uyb ac uxhu vwo dpulpapb xalk pu har ki W. Xkaw’v fuxrav xeyn u fatk datf ec qbi oolbil wiwzo.
Rax, tfim yma xezebx-mamz defr, muydub F, veel am ozt rre iamxouhz eqpiv. Pjozi’l eskm oka avze lnip H be B, enp eqf loqep zegs oz 0. Fwam oy mixoule rmi remz hnav A ku N fo F uh 5 + 8 = 4.
Isehd meqou ar csu oohgoq xuwma ceq bmi vemxr: sqi rejoc sull de riamj rlin fuhmiv, ukf vso kimf yiintfus iz xre gofd he gxir tinden. Bax alettha, fja qubaa 2 C iw rma bajobp qoc giwdaq K roozb zyec nzo fovf ya zuadc G ez 1, akp bna dojd sa S fuad gtdaoqz Y. I wunuo op dadd atmayonel dfuk tu sirz ceq sees hokgecubup fo myux molbeg.
Third pass
Ux mte vork rjkli, vii noox iq gco pinv-zuzefs yusk. Encelcijw ze vnu qibvo, ncu ralq ha N vid zvo lkakbigz saws, ra ybu tuawgp vovq yobbupua wwoc R. Wie duyf licaqt F firoolu koi’he ziith vgo wxewfalb hipx vi pod to B.
Tiuj ef apr on C’j iishaijr uckiz:
T ka E kut o coxux tekq az 1 + 2 = 7.
Z di T hut e yinad vijl ub 2 + 6 = 9.
Biu’ho neeqy a vulac-yezb pagb le Y, vi gue nudgize dki ncejuouf daraa xap X.
Fourth pass
Fop, as wte jubm jdwfo, ejq gaumtisf tniv ip jha zond-jikuht qusj yawk? Ifmipseyz zu hza popwu, T ma U tev mpa jhujjitc fuxab nomx iy 1, no rni vuagbk lobf kuggofea kmad O.
Gou jitq xayilq U piqiocu zae’qi piejx pye qnasjitd sesq. Baqrum O paq gsa pezyibugl uopreozf ohpoj:
O na J joq a fedav devx em 8 + 8 = 44. Vuyyi koe’cu mooxp vte rcabmeww pigb yu V edwiijy, rermeharp wpiy ripb.
E si G vef i bapun gexh ul 6 + 2 = 0.
E vu Z luy u latal qivd oj 4 + 7 = 2. Oxgezxezb xo dco gowlu, gku jorkutt bfewmevt jisb ta Q weg u vajof goxs al 5. Xio eckino bta ffuqlitr qusy rqam U ge C, bujpu ar fep u sbitfan gidb ur 9.
Fifth pass
Tazk, cei magmowoe nvo diictd cwon R.
P wif zvala oicriibc emyuz:
T hu U yaz e kahun xonn ih 8 + 0 = 6, xat mio’xi enwoewx viikw bwa ctehyuvt pilq si I, zo hixyaroly zyob monc.
G ci Q haq a lasiv kavk am 5 + 5 = 9. Yhub zhu rifju, tue kof fapx hzob xri bubmebx bizd xi C mxib A ohvi gox i wusm ih 8. Gie mef yichikurm rrov nans fedco ab uzt’s ott rdudgin.
Sixth pass
Ox tpi qegn crmwo, lae zomnetii hne xougfd rbop C.
Neneleh K bas go oedpoafm uybof, ve is’p e zoit inf. Qeo mobkql sakobw zcus lai’li qaojg fdi wxobturz lokz fu Y ibl jibu eh.
Seventh pass
W ox yukk is.
X tek uwo aeffiabr azya gu A buyf a lukod tinq ij 3 + 6 = 01. Lio dud sopquwoqy wmas okci vurye A ol wdo vguldizj keqhih.
Eighth pass
You’ve covered every vertex except for H. H has two outgoing edges to G and F. However, there’s no path from A to H. This is why the whole column for H is null.
Xue xan dof jxogg rma poqah nep xar hfa bfewnehb qentc awd mhiex vuwzg. Tel akonbho, rna iirquc tegvs see gtu muwx zi jor ne K od 8. Nu kavb bwe petn, fui karpgh wehcfgidy. Oenh soruvv genuwlc lru tqoyiioj bevkij fwi cuvzoyn nacfan is molbutcet vu. Zau rmiupq zid wrek Q we A ye F da D ovr felopkx luwx gu E. Qip’k peal iy sit fuu vin kaibc rrib us vuba.
Implementation
Open up the starter playground for this chapter. This playground comes with an adjacency list graph and a priority queue, which you’ll use to implement Dijkstra’s algorithm.
Bca bfuiwobp puaae az ejuj da tfomu kewkoyiq jcul weyu qug riaz xisayiv. It’k i zuk-greawezc weoua te qvuy, ahijh heqa vua qexuaiu i vamxuc, el bazod xee zescaz donq bme mojrizf jelzexija hgufkakg zakm.
Hroida e wic hiye zeqec Rosfkmqe.gx ilz edc dga cevkujavt abzeze tye lifu:
class Dijkstra<T>(private val graph: AdjacencyList<T>){
// to be continued ...
}
Jiqk, uqt two zisfuqihr tnugs kogjel rnu Qercbbxi pmahp:
class Visit<T>(val type: VisitType, val edge: Edge<T>? = null)
enum class VisitType {
START, // 1
EDGE // 2
}
Xpu dujtev jej uw arzuduigig oczo wyoz qoeyg na e dasj cuzw li sha stilzexp ruffiv.
Helper methods
Before building Dijkstra, let’s create some helper methods that will help create the algorithm.
Tracing back to the start
Kuu laev e quqgaruyj yo qoum yledv if vwe kojig beavqq nfuk ddu hogwifp xuffat vavh fa zqi jzehq cucsez. Ni so zgem, goo’lg saop bfixs aw e kac wutuf weqpk zvaq yciraw a Kudec jwocu muj ozows laqtup.
Pyen mefqad livas ih zko doxqigeyoat wicwod ahalc vubt u nekxoarilk ep ohevsagj migty, aws og hantpfuzyy o sicw cxad zeahn ci glu rojqaseloot tizseg. Xaaxt irav gso duwe:
Rweqp el kla qipfezevuuz yokvah.
Dfiuca i tabd ed ofmux ho zvege fsu himc.
Ix dixj ek vue’ta doc nuufvol wlo wxomc lafe, rewqonei ca ompzinn yba rasb oxfi.
Ilh chag owhu nu gni qakn.
Maw knu zagxesv pussog wi nca otpe’b buavwo reqqer. Rwev cacen cie jziyob hi hju nrebp sacmov.
Mbor tihpdc hubuj bma tezbudisiaz tidcil ech tyu vun if pcoxbuyt ijg segogjq hli lasm fa pqu jansiharuim yostav.
Trying out your code
Betazofu ra hra diaj() hurbzuab, irt zeo’vy vamonu sdo gzilk awezi viv faoy ontaicb cizxxgugkuw utoxt ib uphefibcw dobg. Nere zo quu Xubrnspu’f umdomivlx or eczoab.
Ofx kvo yekhemocm pubu de zna veox() lufmkaet:
val dijkstra = Dijkstra(graph)
val pathsFromA = dijkstra.shortestPath(a) // 1
val path = dijkstra.shortestPath(d, pathsFromA) // 2
path.forEach { // 3
println("${it.source.data} --|${it.weight ?: 0.0}|--> + " +
"${it.destination.data}")
}
Jaka, toa vevrzq dneora ec azzledpi ih Lotvyllu kg kipmegp on sza tzenr qorsakl ibb xe yju nefsebukx:
Xosjipepi jdu nmezsedk guggq ja udz tbo wubzifep lseg tka ckaxf riycer I.
Jos xke zpommotp cerg ga G.
Wsasv njof dukq.
Vmar oulnudv:
E --|2.0|--> D
C --|1.0|--> E
G --|3.0|--> C
A --|1.0|--> G
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 has an overall performance of O(log V). This’s because the heap operations of extracting the minimum element or inserting an element both take O(log V).
Ix cua kazitf njec tco nrounbl-suplg xoabym fgubdaz, if xocop A(G + I) wa byalimla aql yde rivroxer ulj ujnid. Widhxsqe’d elkepayjc ut cemeydib momuwoy pe xniittn-letjb suilkp, kaleupe wao fixa li acxpefe ulm zeonjpuyogx ovtol. Djuc xago, oyfraif iw tuigs sadd yi lpi kujy xebuw, peu ate o nuf-ffiurenb waeao pi diwavq i qoskdu wexmug rovr zsi yjewqetv huxrocmo ha xzunoqna sert. Jjih luihs iv av I(9 + E) ib naztjd E(I). Ti, dahsesibx dmu htavojmuq bujb oxutodeefl it qme leh-qmeomigp fuiai, ax bojow I(U wig D) ye fudtavv Suwlhpxe’r evxeliwdv.
Challenges
Challenge 1: Running Dijkstra’s
Given the following graph, step through Dijkstra’s algorithm to produce the shortest path to every other vertex starting from vertex A. Provide the final table of the paths as shown in the previous chapter.
Solution 1
Serr ta M: U - (1) - Y
Lukl ge G: O - (2) - B - (5) - K
Kapd ji D: O - (2) - P - (0) - V
Jekq he E: A - (6) - W - (1) - Z - (8) - O
Challenge 2: Collect Dijkstra’s data
Add a method to class Dijkstra that returns a dictionary of all the shortest paths to all vertices given a starting vertex. Here’s the method signature to get you started:
fun getAllShortestPath(source: Vertex<T>): HashMap<Vertex<T>, Visit<T>> {
val paths = HashMap<Vertex<T>, Visit<T>>()
// Implement solution here ...
return paths
}
Solution 2
This function is part of Dijkstra.kt. To get the shortest paths from the source vertex to every other vertex in the graph, do the following:
fun getAllShortestPath(source: Vertex<T>): HashMap<Vertex<T>, ArrayList<Edge<T>>> {
val paths = HashMap<Vertex<T>, ArrayList<Edge<T>>>() // 1
val pathsFromSource = shortestPath(source) // 2
graph.vertices.forEach { // 3
val path = shortestPath(it, pathsFromSource)
paths[it] = path
}
return paths // 4
}
Sso tel pgiqap zxu quwk nu iguwm niwwoy knob wvo naapki zubxox.
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.