January 6, 2024

Dijkstra's Algorithm

Rasmda berilgan graph Vaznli graph (weighted graph) deyiladi. Bunday graphlarning bir nuqtasidan boshqa nustasigacha bo'lgan vazni bo'ladi (rasmda bir nuqtalar orasidagi masofa keltirilgan). Bunday graphlarda ikki nuqta orasidagi eng kichik masofani topishlik uchun "Dijkstra algoritmi" ishlatiladi. BFS (breadth first search) algoritmi bilan bir nuqtadan ikkinchi nuqtaga olib boruvchi eng kichik yo'lni topgan bo'lsak (unda masofalar yo'q edi, segmentlar bor edi), Dijkstra algoritmi bilan eng kichik masofani topib olamiz.

Quyida weigthed graph va Dijkstra algoritmining codedagi implementatsiyasini ko'rob chiqamiz:

type WeightedGraphType = Record<string, Record<string, number>>

class WeightedGraph {

  private graph: WeightedGraphType
  constructor () {    
    this.graph = {}  
  }

  print () {    
    return this.graph  
  }
  // graphga uzel (edge) lar qo'shish uchun
  addEdge (key: string, value: Record<string, number>) {    
     this.graph[key] = value  
  }
  // start nuqtadan qolgan barcha nuqtalargacha bo'lgan
  // masofani qaytaradi
  dijkstra(start: string): Record<string, number> {
     // start nuqtadan qolgan barcha nuqtalargacha bo'lgan eng    
     // kichik masofani saqlash uchun     
     const distances: Record<string, number> = {};
     
     // tashrif buyurilgan nuqtalarni saqlash uchun    
     const visited = new Set<string>();

     // graph keylarini massivga olamiz // ['a', 'b' ..., 'g']    
     let nodes = Object.keys(this.graph);

     // har bir nuqta uchun boshlang'ich masofani Inifinity     
     // qilib belgilab olamiz
     for (let node of nodes) {        
         distances[node] = Infinity;    
     }

     // boshlang'ich nuqtadan o'zigacha bo'lgan masofa    
     // 0 bo'lgani uchun uni 0 ga tenglaymiz
     distances[start] = 0;

     // barcha nodelar bo'ylab siklda aylanib chiqamiz    
     while (nodes.length) {
       // nodelarni kamayish tartibida tartiblab olamiz va        
       // undan eng yaqin bo'lgan nodeni olamiz
       nodes.sort((a, b) => distances[b] - distances[a]);        
       let closestNode = nodes.pop()!;
       
       // agar eng yaqin nodegacha bo'lgan masoda hali ham Infinity bo'lsa,        
       // u holda u siklni to'xtatamiz
       if (distances[closestNode] === Infinity) {          
           break        
       }
       
       // eng yaqin node'ni tashrif buyurilganlarga qo'shamiz        
       visited.add(closestNode);
       
       // node'ning har bir qo'shnilari bo'ylab yurib chiqamiz        
       for (let neighbor in this.graph[closestNode]) {
          // agar qo'shni node'ga hali tashrif buyurilmagan bo'lsa            
          if (!visited.has(neighbor)) {                
            // node'dan uning qo'shinisigacha bo'lgan masofani hisoblaymiz                
            let newDistance = distances[closestNode] + this.graph[closestNode][neighbor];                                
            // agar hisoblangan masofa ayni paytdagi masofadan kichik bo'lsa                
            // u holda ayni masofani o'zgartiramiz (eng kichik masofa)                
            if (newDistance < distances[neighbor]) {                    
               // eng kichik masofani update qilamiz                    
               distances[neighbor] = newDistance;                
            }            
          }        
       }
     }
    // start nuqtadan qolgan nuqtalargacha (nodelar) bo'lgan eng     
    // kichik masofalarni qaytaramiz    
    return distances;
  } 

  // bir nuqtadan ikkinchi nuqtagacha bo'lgan eng kichik masofa
  shortDistance (start: string, end: string): number | undefined {
     return this.dijkstra(start)[end]
  }   
}

// Weighted graph instance
const weightedGraph = new WeightedGraph()

// uzel (edge) larni qo'shib chiqamiz
weightedGraph.addEdge('a', {b: 2, c: 1})
weightedGraph.addEdge('b', {f: 7})
weightedGraph.addEdge('c', {d: 5, e: 2})
weightedGraph.addEdge('d', {f: 2})
weightedGraph.addEdge('e', {f: 1})
weightedGraph.addEdge('f', {g: 1})
weightedGraph.addEdge('g', {})

console.log(weightedGraph.print())
// {
//   a: { b: 2, c: 1 },
//   b: { f: 7 },
//   c: { d: 5, e: 2 },
//   d: { f: 2 },
//   e: { f: 1 },
//   f: { g: 1 },
//   g: {}
// }

console.log(weightedGraph.dijkstra('a')) // { a: 0, b: 2, c: 1, d: 6, e: 3, f: 4, g: 5 }
// a nuqtadan g nuqtagacha bo'lgan masofani topish
console.log(weightedGraph.shortDistance('a', 'g')) // 5

Telegram kanalim: https://t.me/elyor_dev