الگوریتم دایجسترا (Dijkstra) – از صفر تا صد


«الگوریتم دایجسترا» (Dijkstra's Algorithm) یا «اولین الگوریتم کوتاهترین مسیر دایجسترا» (Dijkstra's Shortest Path First Algorithm | SPF) (البته تلفظ صحیح این نام، الگوریتم دیکسترا است که به صورت متداول به آن دایجسترا گفته میشود)، الگوریتمی است که برای پیدا کردن کوتاهترین مسیر بین دو «گره» (Node | راس) در گراف به کار میرود. این گراف، ممکن است نشانگر شبکه جادهها یا موارد دیگری باشد. الگوریتم دایجسترا در سال ۱۹۵۶، توسط دانشمند کامپیوتری با نام «ادسخر ویبه دیکسترا» (Edsger Wybe Dijkstra) مطرح و سه سال بعد، منتشر شد. الگوریتم دایجسترا دارای انواع گوناگونی است. الگوریتم اصلی، کوتاهترین مسیر بین دو گره را پیدا میکند؛ اما نوع متداولتر این الگوریتم، یک گره یکتا را به عنوان گره مبدا (آغازین) در نظر میگیرد و کوتاهترین مسیر از مبدا به دیگر گرهها در گراف را با ساختن درخت کوتاهترین مسیر پیدا میکند.
برای یک گره مبدا داده شده، الگوریتم، کوتاهترین مسیر بین آن گره و دیگر گرهها را پیدا میکند. همچنین، الگوریتم دایجسترا برای پیدا کردن کوتاهترین مسیر از یک گره یکتا به گره مقصد یکتای دیگری به کار میرود؛ برای انجام این کار، الگوریتم هنگامی که کوتاهترین مسیر از مبدا به مقصد را پیدا کند، متوقف میشود. برای مثال، اگر گرههای گراف نشانگر شهرها و یالها هزینه سفر بین شهرهایی باشند که با جادههای مستقیم به هم متصل شدهاند، از الگوریتم دایجسترا میتوان برای پیدا کردن کوتاهترین راه بین یک شهر و همه شهرهای دیگر استفاده کرد. یکی از کاربردهای اصلی الگوریتم دایجسترا، پروتکلهای مسیریابی شبکه است که از جمله آنها میتوان به IS-IS (سیستم میانی به سیستم میانی | Intermediate System to Intermediate System) و «ابتدا کوتاهترین مسیر باز» (Open Shortest Path First | OSPF) اشاره کرد.
از الگوریتم دایجسترا، به عنوان یک زیر روال نیز در برخی از دیگر الگوریتمها مانند «الگوریتم جانسون» (Johnson's Algorithm) استفاده میشود. الگوریتم دایجسترا از برچسبهایی استفاده میکند که اعداد صحیح یا حقیقی مثبت هستند. جالب توجه است که الگوریتم دایجسترا میتواند برای استفاده از برچسبهای تعریف شده به هر شکلی، تعمیم پیدا کند. چنین تعمیمی، «تعمیم الگوریتم کوتاهترین مسیر دایجسترا» نامیده میشود.
الگوریتم دایجسترا (Dijkstra) برای یافتن کوتاهترین مسیر
فرض میشود که یک گراف به همراه یک راس مبدا داده شده و هدف پیدا کردن کوتاهترین مسیر به همه راسهای موجود در گراف مذکور است. الگوریتم دایجسترا شباهت زیادی به «الگوریتم پریم» (Prim’s Algorithm) برای «درخت پوشای کمینه» (Minimum Spanning Tree) دارد. در الگوریتم دایجسترا نیز درخت کوتاهترین مسیر با استفاده از مبدا داده شده به عنوان ریشه، ساخته میشود.
در هر مرحله از الگوریتم، راسی پیدا میشود که در مجموعه دیگر (مجموعه راسهای در نظر گرفته نشده) قرار دارد و دارای کمترین فاصله از ریشه است. در ادامه، گامهای مورد استفاده در الگوریتم دایجسترا به منظور یافتن کوتاهترین مسیر از یک راس مبدا مجرد به دیگر راسها در گراف داده شده به صورت مشروح بیان شدهاند.
- ساخت مجموعه sptSet (مجموعه درخت کوتاهترین مسیر | Shortest Path Tree Set) که به دنبال راسهای قرار گرفته در درخت کوتاهترین مسیر میگردد؛ یعنی، راسی که حداقل فاصله آن از مبدا محاسبه و نهایی شده است. به طور مقدماتی، این مجموعه خالی است.
- تخصیص یک مقدار فاصله به همه راسها در گراف ورودی. مقداردهی اولیه همه مقادیر فاصلهها به عنوان INFINITE. تخصیص مقدار فاصله صفر به راس مبدا که موجب میشود این راس در ابتدا انتخاب شود.
- تا هنگامی که sptSet شامل همه راسها نشده است، اقدامات زیر انجام میشود:
- راس u انتخاب میشود که در sptSet نیست و دارای حداقل مقدار فاصله است.
- u در sptSet قرار میگیرد.
- مقدار فاصله از همه راسهای مجاور u به روز رسانی میشود. برای به روز رسانی مقادیر فاصله، در همه راسهای مجاور تکرار انجام میشود. برای هر راس مجاور v، اگر مجموع فاصله u (از کد منبع) و وزن یال u-v کمتر از مقدار فاصله v باشد، مقدار فاصله از v به روز رسانی میشود.
برای درک بهتر موضوع، مثال زیر مورد بررسی قرار خواهد گرفت.
مجموعه sptSet در ابتدا خالی است و فاصله تخصیص پیدا کرده به راسها برابر با { INF, INF, INF, INF, INF, INF, INF ,صفر} هستند که در آن INF نشانگر بینهایت (Infinite) است. اکنون، باید راسی که دارای کمترین مقدار فاصله است انتخاب شود. راس ۰ انتخاب میشود و در sptSet قرار میگیرد. بنابراین، sptSet به صورت {0} میشود. پس از قرار دادن ۰ در sptSet، مقدار فاصلهها از راسهای مجاور آن به روز رسانی میشوند. راسهای مجاور ۰، راسهای ۱ و ۷ هستند. مقدار فاصله برای ۱ و ۷، برابر با ۴ و ۸ است. زیرگراف زیر، راسها و مقدار فاصله آنها را نشان میدهد. در این گراف، تنها راسهایی با مقدار فاصله متناهی نشان داده شدهاند. راسهای موجود در SPT به رنگ سبز نمایش داده شدهاند.
راسی که حداقل فاصله را از مبدا دارد و تاکنون انتخاب نشده است، یعنی در sptSET قرار ندارد، انتخاب میشود. راس ۱ انتخاب و به sptSet اضافه میشود. بنابراین، اکنون sptSet به صورت {۱ ,۰} خواهد بود. مقدار فاصله راسهای مجاور ۱ به روز رسانی میشود. مقدار فاصله از راس ۲ برابر با ۱۲ خواهد بود.
راسی با کمترین مقدار فاصله که در حال حاضر در SPT قرار ندارد باید انتخاب شود. راس ۷ انتخاب میشود. بنابراین، sptSet اکنون به صورت {۷ , 1 , ۰} خواهد بود. مقدار فاصله از راسهای مجاور ۷ محاسبه میشود. مقدار فاصله از راس ۶ و ۸ متناهی است (به ترتیب، ۱۵ و ۹).
راسی با حداقل مقدار فاصله که در SPT نیز قرار ندارد باید انتخاب شود. راس ۶ انتخاب میشود. بنابراین، sptSet اکنون برابر با {۶ ,۷ ,۱ ,۰} است. مقدار فاصلهها از راسهای مجاور ۶ باید به روز رسانی شود. مقدار فاصله برای راسهای ۵ و ۸ به روز رسانی میشود.
مراحل بیان شده تا جایی تکرار میشوند که sptSet شامل همه راسهای گراف داده شده نباشد. در نهایت، درخت کوتاهترین مسیر (SPT) زیر حاصل میشود.
برای پیادهسازی الگوریتم بالا، از آرایه بولین []sptSet برای ارائه مجموعهای از راسهای قرار گرفته در SPT استفاده میشود. اگر مقدار [sptSet[v «درست» (True) باشد، راس v در SPT قرار میگیرد، در غیر این صورت، یعنی اگر [sptSet[v «غلط» (False) باشد، راس v در SPT قرار نمیگیرد. آرایه []dist برای ذخیرهسازی کوتاهترین مقدار فاصله از همه راسها مورد استفاده قرار میگیرد.
کد الگوریتم دایجسترا در ++C
1// A C++ program for Dijkstra's single source shortest path algorithm.
2// The program is for adjacency matrix representation of the graph
3
4#include <stdio.h>
5#include <limits.h>
6
7// Number of vertices in the graph
8#define V 9
9
10// A utility function to find the vertex with minimum distance value, from
11// the set of vertices not yet included in shortest path tree
12int minDistance(int dist[], bool sptSet[])
13{
14 // Initialize min value
15 int min = INT_MAX, min_index;
16
17 for (int v = 0; v < V; v++)
18 if (sptSet[v] == false && dist[v] <= min)
19 min = dist[v], min_index = v;
20
21 return min_index;
22}
23
24// A utility function to print the constructed distance array
25int printSolution(int dist[], int n)
26{
27 printf("Vertex Distance from Source\n");
28 for (int i = 0; i < V; i++)
29 printf("%d tt %d\n", i, dist[i]);
30}
31
32// Function that implements Dijkstra's single source shortest path algorithm
33// for a graph represented using adjacency matrix representation
34void dijkstra(int graph[V][V], int src)
35{
36 int dist[V]; // The output array. dist[i] will hold the shortest
37 // distance from src to i
38
39 bool sptSet[V]; // sptSet[i] will be true if vertex i is included in shortest
40 // path tree or shortest distance from src to i is finalized
41
42 // Initialize all distances as INFINITE and stpSet[] as false
43 for (int i = 0; i < V; i++)
44 dist[i] = INT_MAX, sptSet[i] = false;
45
46 // Distance of source vertex from itself is always 0
47 dist[src] = 0;
48
49 // Find shortest path for all vertices
50 for (int count = 0; count < V-1; count++)
51 {
52 // Pick the minimum distance vertex from the set of vertices not
53 // yet processed. u is always equal to src in the first iteration.
54 int u = minDistance(dist, sptSet);
55
56 // Mark the picked vertex as processed
57 sptSet[u] = true;
58
59 // Update dist value of the adjacent vertices of the picked vertex.
60 for (int v = 0; v < V; v++)
61
62 // Update dist[v] only if is not in sptSet, there is an edge from
63 // u to v, and total weight of path from src to v through u is
64 // smaller than current value of dist[v]
65 if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX
66 && dist[u]+graph[u][v] < dist[v])
67 dist[v] = dist[u] + graph[u][v];
68 }
69
70 // print the constructed distance array
71 printSolution(dist, V);
72}
73
74// driver program to test above function
75int main()
76{
77 /* Let us create the example graph discussed above */
78 int graph[V][V] = {{0, 4, 0, 0, 0, 0, 0, 8, 0},
79 {4, 0, 8, 0, 0, 0, 0, 11, 0},
80 {0, 8, 0, 7, 0, 4, 0, 0, 2},
81 {0, 0, 7, 0, 9, 14, 0, 0, 0},
82 {0, 0, 0, 9, 0, 10, 0, 0, 0},
83 {0, 0, 4, 14, 10, 0, 2, 0, 0},
84 {0, 0, 0, 0, 0, 2, 0, 1, 6},
85 {8, 11, 0, 0, 0, 0, 1, 0, 7},
86 {0, 0, 2, 0, 0, 0, 6, 7, 0}
87 };
88
89 dijkstra(graph, 0);
90
91 return 0;
92}
کد الگوریتم دایجسترا در جاوا
1// A Java program for Dijkstra's single source shortest path algorithm.
2// The program is for adjacency matrix representation of the graph
3import java.util.*;
4import java.lang.*;
5import java.io.*;
6
7class ShortestPath
8{
9 // A utility function to find the vertex with minimum distance value,
10 // from the set of vertices not yet included in shortest path tree
11 static final int V=9;
12 int minDistance(int dist[], Boolean sptSet[])
13 {
14 // Initialize min value
15 int min = Integer.MAX_VALUE, min_index=-1;
16
17 for (int v = 0; v < V; v++)
18 if (sptSet[v] == false && dist[v] <= min)
19 {
20 min = dist[v];
21 min_index = v;
22 }
23
24 return min_index;
25 }
26
27 // A utility function to print the constructed distance array
28 void printSolution(int dist[], int n)
29 {
30 System.out.println("Vertex Distance from Source");
31 for (int i = 0; i < V; i++)
32 System.out.println(i+" tt "+dist[i]);
33 }
34
35 // Funtion that implements Dijkstra's single source shortest path
36 // algorithm for a graph represented using adjacency matrix
37 // representation
38 void dijkstra(int graph[][], int src)
39 {
40 int dist[] = new int[V]; // The output array. dist[i] will hold
41 // the shortest distance from src to i
42
43 // sptSet[i] will true if vertex i is included in shortest
44 // path tree or shortest distance from src to i is finalized
45 Boolean sptSet[] = new Boolean[V];
46
47 // Initialize all distances as INFINITE and stpSet[] as false
48 for (int i = 0; i < V; i++)
49 {
50 dist[i] = Integer.MAX_VALUE;
51 sptSet[i] = false;
52 }
53
54 // Distance of source vertex from itself is always 0
55 dist[src] = 0;
56
57 // Find shortest path for all vertices
58 for (int count = 0; count < V-1; count++)
59 {
60 // Pick the minimum distance vertex from the set of vertices
61 // not yet processed. u is always equal to src in first
62 // iteration.
63 int u = minDistance(dist, sptSet);
64
65 // Mark the picked vertex as processed
66 sptSet[u] = true;
67
68 // Update dist value of the adjacent vertices of the
69 // picked vertex.
70 for (int v = 0; v < V; v++)
71
72 // Update dist[v] only if is not in sptSet, there is an
73 // edge from u to v, and total weight of path from src to
74 // v through u is smaller than current value of dist[v]
75 if (!sptSet[v] && graph[u][v]!=0 &&
76 dist[u] != Integer.MAX_VALUE &&
77 dist[u]+graph[u][v] < dist[v])
78 dist[v] = dist[u] + graph[u][v];
79 }
80
81 // print the constructed distance array
82 printSolution(dist, V);
83 }
84
85 // Driver method
86 public static void main (String[] args)
87 {
88 /* Let us create the example graph discussed above */
89 int graph[][] = new int[][]{{0, 4, 0, 0, 0, 0, 0, 8, 0},
90 {4, 0, 8, 0, 0, 0, 0, 11, 0},
91 {0, 8, 0, 7, 0, 4, 0, 0, 2},
92 {0, 0, 7, 0, 9, 14, 0, 0, 0},
93 {0, 0, 0, 9, 0, 10, 0, 0, 0},
94 {0, 0, 4, 14, 10, 0, 2, 0, 0},
95 {0, 0, 0, 0, 0, 2, 0, 1, 6},
96 {8, 11, 0, 0, 0, 0, 1, 0, 7},
97 {0, 0, 2, 0, 0, 0, 6, 7, 0}
98 };
99 ShortestPath t = new ShortestPath();
100 t.dijkstra(graph, 0);
101 }
102}
103//This code is contributed by Aakash Hasija
کد الگوریتم دایجسترا در #C
1// A C# program for Dijkstra's single
2// source shortest path algorithm.
3// The program is for adjacency matrix
4// representation of the graph
5using System;
6
7class GFG
8{
9// A utility function to find the
10// vertex with minimum distance
11// value, from the set of vertices
12// not yet included in shortest
13// path tree
14static int V = 9;
15int minDistance(int[] dist,
16 bool[] sptSet)
17{
18 // Initialize min value
19 int min = int.MaxValue, min_index = -1;
20
21 for (int v = 0; v < V; v++)
22 if (sptSet[v] == false &&
23 dist[v] <= min)
24 {
25 min = dist[v];
26 min_index = v;
27 }
28
29 return min_index;
30}
31
32// A utility function to print
33// the constructed distance array
34void printSolution(int[] dist, int n)
35{
36 Console.Write("Vertex Distance " +
37 "from Source\n");
38 for (int i = 0; i < V; i++)
39 Console.Write(i + " \t\t " +
40 dist[i] + "\n");
41}
42
43// Funtion that implements Dijkstra's
44// single source shortest path algorithm
45// for a graph represented using adjacency
46// matrix representation
47void dijkstra(int[,] graph, int src)
48{
49 int[] dist = new int[V]; // The output array. dist[i]
50 // will hold the shortest
51 // distance from src to i
52
53 // sptSet[i] will true if vertex
54 // i is included in shortest path
55 // tree or shortest distance from
56 // src to i is finalized
57 bool[] sptSet = new bool[V];
58
59 // Initialize all distances as
60 // INFINITE and stpSet[] as false
61 for (int i = 0; i < V; i++)
62 {
63 dist[i] = int.MaxValue;
64 sptSet[i] = false;
65 }
66
67 // Distance of source vertex
68 // from itself is always 0
69 dist[src] = 0;
70
71 // Find shortest path for all vertices
72 for (int count = 0; count < V - 1; count++)
73 {
74 // Pick the minimum distance vertex
75 // from the set of vertices not yet
76 // processed. u is always equal to
77 // src in first iteration.
78 int u = minDistance(dist, sptSet);
79
80 // Mark the picked vertex as processed
81 sptSet[u] = true;
82
83 // Update dist value of the adjacent
84 // vertices of the picked vertex.
85 for (int v = 0; v < V; v++)
86
87 // Update dist[v] only if is not in
88 // sptSet, there is an edge from u
89 // to v, and total weight of path
90 // from src to v through u is smaller
91 // than current value of dist[v]
92 if (!sptSet[v] && graph[u, v] != 0 &&
93 dist[u] != int.MaxValue &&
94 dist[u] + graph[u, v] < dist[v])
95 dist[v] = dist[u] + graph[u, v];
96 }
97
98 // print the constructed distance array
99 printSolution(dist, V);
100}
101
102// Driver Code
103public static void Main ()
104{
105/* Let us create the example
106graph discussed above */
107int[,] graph = new int[,]{{0, 4, 0, 0, 0, 0, 0, 8, 0},
108 {4, 0, 8, 0, 0, 0, 0, 11, 0},
109 {0, 8, 0, 7, 0, 4, 0, 0, 2},
110 {0, 0, 7, 0, 9, 14, 0, 0, 0},
111 {0, 0, 0, 9, 0, 10, 0, 0, 0},
112 {0, 0, 4, 14, 10, 0, 2, 0, 0},
113 {0, 0, 0, 0, 0, 2, 0, 1, 6},
114 {8, 11, 0, 0, 0, 0, 1, 0, 7},
115 {0, 0, 2, 0, 0, 0, 6, 7, 0}};
116 GFG t = new GFG();
117 t.dijkstra(graph, 0);
118}
119}
120
121// This code is contributed by ChitraNayal
کد الگوریتم دایجسترا در پایتون
1# Python program for Dijkstra's single
2# source shortest path algorithm. The program is
3# for adjacency matrix representation of the graph
4
5# Library for INT_MAX
6import sys
7
8class Graph():
9
10 def __init__(self, vertices):
11 self.V = vertices
12 self.graph = [[0 for column in range(vertices)]
13 for row in range(vertices)]
14
15 def printSolution(self, dist):
16 print "Vertex tDistance from Source"
17 for node in range(self.V):
18 print node,"t",dist[node]
19
20 # A utility function to find the vertex with
21 # minimum distance value, from the set of vertices
22 # not yet included in shortest path tree
23 def minDistance(self, dist, sptSet):
24
25 # Initilaize minimum distance for next node
26 min = sys.maxint
27
28 # Search not nearest vertex not in the
29 # shortest path tree
30 for v in range(self.V):
31 if dist[v] < min and sptSet[v] == False:
32 min = dist[v]
33 min_index = v
34
35 return min_index
36
37 # Funtion that implements Dijkstra's single source
38 # shortest path algorithm for a graph represented
39 # using adjacency matrix representation
40 def dijkstra(self, src):
41
42 dist = [sys.maxint] * self.V
43 dist[src] = 0
44 sptSet = [False] * self.V
45
46 for cout in range(self.V):
47
48 # Pick the minimum distance vertex from
49 # the set of vertices not yet processed.
50 # u is always equal to src in first iteration
51 u = self.minDistance(dist, sptSet)
52
53 # Put the minimum distance vertex in the
54 # shotest path tree
55 sptSet[u] = True
56
57 # Update dist value of the adjacent vertices
58 # of the picked vertex only if the current
59 # distance is greater than new distance and
60 # the vertex in not in the shotest path tree
61 for v in range(self.V):
62 if self.graph[u][v] > 0 and sptSet[v] == False and
63 dist[v] > dist[u] + self.graph[u][v]:
64 dist[v] = dist[u] + self.graph[u][v]
65
66 self.printSolution(dist)
67
68# Driver program
69g = Graph(9)
70g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0],
71 [4, 0, 8, 0, 0, 0, 0, 11, 0],
72 [0, 8, 0, 7, 0, 4, 0, 0, 2],
73 [0, 0, 7, 0, 9, 14, 0, 0, 0],
74 [0, 0, 0, 9, 0, 10, 0, 0, 0],
75 [0, 0, 4, 14, 10, 0, 2, 0, 0],
76 [0, 0, 0, 0, 0, 2, 0, 1, 6],
77 [8, 11, 0, 0, 0, 0, 1, 0, 7],
78 [0, 0, 2, 0, 0, 0, 6, 7, 0]
79 ];
80
81g.dijkstra(0);
82
83# This code is contributed by Divyanshu Mehta
اگر نوشته بالا برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی
- آموزش ساختمان دادهها
- مجموعه آموزشهای ساختمان داده و طراحی الگوریتم
- معرفی منابع آموزش ویدئویی هوش مصنوعی به زبان فارسی و انگلیسی
- زبان برنامهنویسی پایتون (Python) — از صفر تا صد
- آموزش ساختمان داده — مجموعه مقالات جامع وبلاگ فرادرس
^^
اگه بخوایم برنامه ها رو بنویسیم باید خط های نارنجی. و. قرمز و سبز هم بنویسیم؟
با سلام؛
از همراهی شما با مجله فرادرس سپاسگزاریم. آنچه در این کد به رنگهایی به جز مشکی نمایش داده شده است، بخشهای مختلف کد است که ویرایشگر کد متناسب با نوع آن بخش از کد، آن را به یکی از رنگهای بیان شده توسط شما درآورده است. برای مثال، توضیحات (کامنتها)، توابع، شرطها و دیگر موارد هر یک به رنگی درآمدهاند. این کار توسط ویرایشگر کد به صورت خودکار و با این دلیل انجام می شود که خوانایی و عیبیابی کد افزایش پیدا کند. بنابراین، همه این موراد جزئی از یک کد کامل هستند. البته، توضحیات بخش غیر اجرایی و قابل حذف یک کد هستند که البته وجود آنها برای افزایش خوانایی و به دلایل مهم دیگر، به نوعی الزامی است. برای مطالعه بیشتر پیرامون توضیحات، مطالعه مطلب زیر پیشنهاد میشود.
توضیحات در پایتون — به زبان ساده
پیروز، شاد و تندرست باشید.
سپاس
عالی