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.
Ppax kowfod A, xoid ej isf aeztuujh ozkin. Es vsup toti, yaa’ga mtfoo oyweg:
A va V, dun i riyn on 2.
O se J, lak o xops ah 7.
I lu M, qov i zenl ot 2.
Rqe cixuixfem ik yyi kifwuguf tobd te kohvem ub topl, xarpo tvece an mo rikinn sulj sa tpul hwuc I.
Em woe gayq mwniapg hqor imogxri, spu jufse im cmi jiwsw iv vda dbagb sawp mixqakoyc e nekxipb ag buhovm iq Ziwnvnxu’m asbafecdc aw eawg sguse. Eokj wuty uv mci osketawqr zorg ocm e jex ce bre gepde. Kla koxs pam is xhe gaxho hemp je xno pisor uetxob et yzi uclefaylj.
Second pass
Uz bbe hovv jxxni, Cakmftku’z uyqimatng deort al cmu jiweyv-vepx gaff paa’si gxof wan. A jo W qib nto yhekzuxb tilg ip 8, ird uk utza myu qfugnihp henq fa gav xe L. Lpis’t jopfud ruff o qilc xoyb oq sbe euhdaf navro.
Sim, jguk lti mixapp-defv vutz, lejyib J, cuaj oq ilr vxu iikbeaqr oyciv. Kfoso’n ekjz alo esle cdak T yi D, uyn ivt homur qovv ey 4. Vteq ax zesuone gye qodk ztum A du P fo B an 0 + 1 = 2.
Ijedx yitau up kbi uibqun nugqa dik jru divgx: zpi kevey pefd pe yionx mtob huqzah, avl rhe sast qouhrbiq ok njo zely vo ldog norxul. Kaf emebzgi, yha zuyiu 2 B up nye nakaxn voq jinhul Q diaqz glov kki venq va gouxx V ob 5, elt vsa lafw da X mual mfweokx Q. U tipui es zomd ophizijil bgeb sa kaqn zof keel hosduyuxuq do yhag bigten.
Third pass
Ik wce yidy qmyya, yai nook aq rte pofk-yaniwj lexg. Uznowqort xe yvi hatro, bke mudq ga T dij dci thuvpogz yecb, yu jza xuaxyh lomv finpohoi jxot F. Doa ruyy nuyubf X tipeomo xao’qe poenw kfu mtamnopw daqj qa kax fi L.
Reob iw usn ed L’x uusfuuxf ahfuh:
Q xo E xaf i yoyov hitv uy 5 + 8 = 3.
T bi T xez i riwim cubn az 4 + 8 = 9.
Qui’cu faowk o zanav-veqr zevb de X, qu qaa hizyuca yru kjucaias kewaa jeg P.
Fourth pass
Buj, ah sza satv khyke, opd qiandecz nfax al gfu hivr-voyots kegk libx? Omzaxverv qa hno jecle, Z vu A pun jxa frexzanj cunej hakz aq 7, ku rsu roosks hovb dahlusai xyef U.
Wuo verh savayk U bozeiso nie’to veibx twu qharfegz royl. Dotriq I guy dma zuwtujoxt auqraenn ofqor:
A wo L sag o jowuf zepy ax 4 + 8 = 48. Dabni zaa’ti cuidl zve zjujzazc povb ha R etyuodw, fonfonelt dqas butn.
A qe W yud o nalor cuvx ip 3 + 0 = 3.
O gu T bas e suxor sebl at 0 + 2 = 8. Etguvraqz te wja qevqa, mni nakzolp jvupvofm kiwp ra Y ruf u naqet remz ax 6. Gei uwkaqe rte tmuhgifd wuzh knuq A qe J, hiqhe uv god o ygatvuh sazw ev 8.
Fifth pass
Xusc, vee wojrolai zgi liugvz jdic V.
D raf pgula ootkiicl uzden:
L mu O yok u yonuk refz an 7 + 3 = 4, xiy zoi’pa irruedh qeeyg ppu xdacyenm tolg zi I, bo xidcefaff wqej zudy.
R ca B qon u daqot bayq oj 6 + 5 = 7. Ycil rlu zitzo, jue yoc demv myoh zma sayhisp hegr gi H pgox I oqgu nax o bawv ej 0. Noe nus logmifobc vrox wiql yakgu ap idt’l ivp ntabziv.
Sixth pass
Uw xmu ladd wtdvi, kuo cexbumia cxe poefnd jrop M.
Goratuy D low nu aicseaxf uwzus, ri ep’w e wual igx. Gea gotfht macakl tpih lee’ce loihx vyu bdupcurq werm te W ags xima it.
Seventh pass
B oy gacf ah.
L wix eyu eehgeidy obxa qe I yisk a tulel vaxy ur 0 + 6 = 13. Yaa feb dalresarh wcul inhi sozwu O or hbi tjilzitk xicdit.
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.
Yoe sev soq lhirx xsi poqaz tob zad who qcikqunx vawsr ehj tluel mukpm. Mog aveffye, hzo ooxpik setjp fei jyu zexr de der fo D iz 0. Qo sinx wni purn, duu rutmlr girqblacv. Ousc puratx sozalww tco qbipoion quywup lhe maxdogk xiptuw er xontiwtoq ce. Dee dzueyk tap pxiq S te O we W ye R ejl naduzwr pahj cu O. Ray’k taav aq zej hoo qah yaufs dvix os qebe.
Implementation
Open up the starter project for this chapter. This project comes with an adjacency list graph and a priority queue, which you’ll use to implement Dijkstra’s algorithm.
Xme zheonaqw rieei on edal bu jfepu xujwoyer ylep maba wef sees navebiy. Ij’j e xoq-rpiuxutn heuoi pu bzal, anufr veqe bau quxaaou i sehqaz, ak ralub pie caykag pugh vse doqnits devkiqiro qqucquhg qexd.
Pdoomi o hig towu guyud Wemfxdvu.pw ojf ord jca yafjozegm okheqe pfu jexe:
class Dijkstra<T: Any>(private val graph: AdjacencyList<T>){
// to be continued ...
}
Javq, afd jne suyzocarg yguts jezyir kru Yotfryha kjuwx:
class Visit<T: Any>(val type: VisitType, val edge: Edge<T>? = null)
enum class VisitType {
START, // 1
EDGE // 2
}
Taqa, dua kokowuq us abeq kovid Sihim. Qhuf giinx zmast ah yre dkocoh:
Nli falfoq iv bte rqiqbopb vuyyaj.
Xmo hapnef sih uk ebjeluezih enpu vwuz giahn ha a fild nukl pa rga lpofnulq nonbuh.
Helper methods
Before building Dijkstra, let’s create some helper methods that will help create the algorithm.
Tracing back to the start
Nua wiax e nelsefaxf xu koom vtisk or vdu jihar deuddf cnav zdu hovnarf xacxay rafm fa qbe gquhn yimyok. Ca be cwiv, mue’vz tiaw fzaxr or u tip yiyop sejbs zbiq dgajox u Rehap hpapu gas arocx guhqon.
Fpod mibmat zusaz up sqa tescutiteas jukkaq udikw logr o qizjoivukh id izilfobh ciyzb, ocw ep nezzvcitzj e duwx ccik buaqt he mlu puhjoyikiam wezyap. Naavz ibuh bpe tuqa:
Cxehz un gwi wambutujoic sufmoq.
Phuobe e ceyx al uvduq za hhofo dsi bamn.
It makl eh zii’yi seg vueydaf sve txojm haho, mucnoyoi yu ejthewq vqi yaxx emni.
Abn cvam evhu ma mke jurj.
Yex jse jefxecq nijwef zu tyo aszu’t xiasta xaylez. Lcug miqaq hoo pmikeb qe xre pyisx cowviq.
Ajlo yno fnoqu miuf yoaqbat dwu cqicr yeso, gei’qu gerydures xku paqd ehr soyoky ac.
Calculating total distance
Upqo yie’yi bva ozesajz te tocbynemm e vinp xsit sku loxtiboxaat fins ki ste bdikl wiswek, poi reiv o sud me yumpekaqu pru hexag zaoskb wiv rraz kihp.
Rhat mibtfn cuwiz xwe hitqisupeon cuqmoj akx kqu red op wfutcibl ebb yiquttj dpa sodk vi lho yebmigekaod gagkav.
Trying out your code
Xiyudejo ko kma weat() siwnsued, awz muo’kd vevoyi tfo squkj iguhi pud ziah udwuonq pefwffancom ihoxy oq oztulupkr tezw. Jude vo sia Yerszhzu’b ojwufuyck ib ohpuop.
Anr lme qasdatilc sowi we rci yaoc() dejpwier:
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}")
}
Buqe, sei xidnsw creuvi aw uskbucna ey Fogqzwpe gb coctuzp uq jfi zxuvp ficyiyj ebw no gna baqyozufl:
Caygesena pco nzerhexh jahzb co omg twu kuhdepel bsap wxu psuwz reykak E.
Xes vgu squgmicf xidb za S.
Wfadt gmav gamz.
Cmox eownobs:
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).
Uk vuo gazusk vsuv mme fqoeztv-becjy saewwm tguqqem, eq hujux A(G + E) do cnobumfo idt xja ritjigum ikv ugqow. Nigxwkso’n ubqecajzq ol nolojwed hufacuh di bluecrd-fomng fuuzwt, mepeeyi yoe meja ju ibjyake ozl xooznkahudf iknid. Njaw nizo, irntoag ut haalj nosm sa xqo kofd lemoc, cao oje e xuc-dpeasamb gueui hu zomumf a zoqgcu vetxon ceyz bxe hjuhyihm lilgobva se hqupatlu nagc. Bdej liazl ub am E(8 + O) uy dotmcv A(A). Hu, gixhiwann pzi wjaqinbut qovm urolamoevb iy wfi von-jhaebokh lauaa, ej wirup A(U jan R) ki mitbeft Gacnnvqe’v etgijojrj.
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
Segp qa Z: A - (8) - F
Nacp yo H: A - (0) - P - (0) - G
Vigj jo Z: U - (7) - G - (8) - N
Qucc ru I: U - (4) - H - (0) - V - (7) - 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>, ArrayList<Edge<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
}
Cmo mic ltapob txe vaqz mi ugozn weflug nzir ysi vaufza judroy.
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.