Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

خوارزمية Dijkstra

آخر تحديث

تجد خوارزمية Dijkstra أقصر مسار من عقدة المصدر إلى كل عقدة أخرى في رسم بياني ذي أوزان حواف غير سالبة. تحتفظ بمسافة مؤقتة لكل عقدة، وتثبّت مرارًا العقدة غير المثبتة ذات أصغر مسافة مؤقتة، وتسترخي حوافها، محدّثةً مسافة الجار كلما وُجد مسار أقصر عبر العقدة الحالية. اضغط تشغيل بالأعلى لمشاهدة المسافات تنخفض مع تثبيت كل عقدة.

الفكرة الأساسية جشعة: بمجرد اختيار أقرب عقدة غير مثبتة تصبح مسافتها نهائية، لأن أي مسار آخر إليها يجب أن يمر عبر عقدة أبعد بالفعل. باستخدام طابور أولوية قائم على كومة ثنائية، تعمل Dijkstra في زمن O((V + E) log V). تتطلب أوزانًا غير سالبة - استخدم Bellman-Ford إذا كانت الحواف قد تكون سالبة.

التعقيد الزمني والمكاني

التنفيذالتعقيدملاحظات
كومة ثنائيةO((V + E) log V)الخيار الشائع والعملي
مسح المصفوفةO(V²)أبسط؛ مناسب للرسوم البيانية الكثيفة
المساحةO(V)المسافات + طابور الأولوية
يتطلبأوزان غير سالبةالحواف السالبة تكسر الاختيار الجشع

خطوة بخطوة

الخطوةماذا يحدث
1اضبط مسافة المصدر إلى 0 وكل الباقي إلى ما لا نهاية.
2اختر العقدة غير المثبتة ذات أصغر مسافة مؤقتة.
3علّمها كمثبتة - أصبحت أقصر مسافة لها نهائية الآن.
4لكل جار، احسب المسافة-عبر-الحالية + وزن الحافة.
5إذا كانت أصغر من مسافة الجار الحالية، فاسترخِها.
6كرّر حتى تُثبَّت كل العقد القابلة للوصول.

مثال محلول

أقصر المسارات من المصدر A في الرسم البياني ذي الحواف A-B=4 وA-C=1 وC-B=2 وC-D=5 وB-D=1:

الخطوةتثبيتالمسافاتالإجراء
0-A=0, B=∞, C=∞, D=∞التهيئة: المصدر A=0، وكل الباقي ما لا نهاية.
1A (0)B=4, C=1, D=∞استرخِ حواف A: اضبط B=4 وC=1.
2C (1)B=3, D=6عبر C: B=1+2=3 يتفوق على 4؛ D=1+5=6.
3B (3)D=4عبر B: D=3+1=4 يتفوق على 6.
4D (4)A=0, C=1, B=3, D=4ثبّت D؛ لا شيء متبقٍّ للاسترخاء. انتهى.

متى تستخدم خوارزمية Dijkstra

استخدمها عندماتجنّبها عندما
تكون كل أوزان الحواف غير سالبةقد تكون أي حافة سالبة - استخدم Bellman-Ford
تحتاج أقصر المسارات من مصدر واحد إلى كل العقدتحتاج أقصر المسارات بين كل الأزواج - Floyd-Warshall أبسط
يكون الرسم البياني موزونًا وتريد مسافات دقيقةيكون الرسم البياني غير موزون - BFS البسيط أسرع وأبسط
يتوفر لديك كومة أو طابور أولوية جيدتريد الوصول بسرعة إلى هدف واحد بمساعدة إرشادية - استخدم A*

كود Dijkstra's Algorithm

تنفيذ نظيف وقابل للتشغيل لخوارزمية Dijkstra's Algorithm بلغات Python, JavaScript, Java, C++, C. اختر لغة، وانسخ الكود، أو افتحه محمّلًا مسبقًا في ساحة تجربة Coddy.

كود Dijkstra's Algorithm بلغة Python

Python
1import heapq2
3
4def dijkstra(graph, start):5    dist = {node: float("inf") for node in graph}6    dist[start] = 07    pq = [(0, start)]8    while pq:9        d, node = heapq.heappop(pq)10        if d > dist[node]:11            continue  # stale entry, a shorter path was already found12        for neighbor, weight in graph[node]:13            new_dist = d + weight14            if new_dist < dist[neighbor]:15                dist[neighbor] = new_dist16                heapq.heappush(pq, (new_dist, neighbor))17    return dist18
19
20graph = {21    "A": [("B", 4), ("C", 1)],22    "B": [("D", 1)],23    "C": [("B", 2), ("D", 5)],24    "D": [("E", 3)],25    "E": [],26}27
28for node, d in dijkstra(graph, "A").items():29    print(f"A -> {node}: {d}")
شغّل هذا الكود في ساحة تجربة Python

أسئلة شائعة حول خوارزمية Dijkstra

ما هو التعقيد الزمني لخوارزمية Dijkstra؟
باستخدام طابور أولوية قائم على كومة ثنائية تعمل في O((V + E) log V). النسخة البسيطة التي تمسح مصفوفة بحثًا عن الأصغر في كل خطوة هي O(V²)، والتي قد تكون في الواقع أسرع على الرسوم البيانية الكثيفة. كلتاهما تستخدم مساحة O(V).
لماذا لا تعمل Dijkstra مع أوزان الحواف السالبة؟
تفترض Dijkstra أنه بمجرد تثبيت أقرب عقدة غير مثبتة تصبح تلك المسافة نهائية. قد تُنشئ حافة سالبة لاحقًا مسارًا أقصر إلى عقدة مثبتة بالفعل، مما يكسر هذا الافتراض. للرسوم البيانية ذات الأوزان السالبة، استخدم خوارزمية Bellman-Ford.
ما الفرق بين Dijkstra وBFS؟
يجد BFS أقصر المسارات بعدّ الحواف (وزن كل حافة يساوي فعليًا 1)، مستخدمًا طابورًا عاديًا. تعمّم Dijkstra ذلك على الرسوم البيانية الموزونة بتوسيع العقدة ذات أصغر مسافة إجمالية دائمًا، مستخدمةً طابور أولوية. في رسم بياني غير موزون تُنتج الاثنتان المسارات نفسها.
ما الفرق بين Dijkstra وبحث A*؟
A* هي Dijkstra مضافًا إليها دالة إرشادية تُقدّر المسافة المتبقية إلى هدف، فتوجّه البحث نحو ذلك الهدف بدلًا من التوسع بانتظام في كل الاتجاهات. عندما تكون الدالة الإرشادية صفرًا، تتحول A* إلى Dijkstra تمامًا. استخدم A* عند وجود وجهة واحدة ودالة إرشادية مقبولة جيدة؛ واستخدم Dijkstra عندما تحتاج المسافات إلى كل العقد.
متى ينبغي أن أستخدم Dijkstra بدلًا من Bellman-Ford؟
استخدم Dijkstra كلما كانت كل أوزان الحواف غير سالبة - فهي أسرع بزمن O((V + E) log V) مقابل O(V·E) لـ Bellman-Ford. اختر Bellman-Ford فقط عندما قد تكون الحواف سالبة أو تحتاج إلى اكتشاف الدورات السالبة. في الرسوم البيانية غير السالبة تكون Dijkstra الخيار الأفضل دائمًا تقريبًا.
هل يمكن لـ Dijkstra إعادة زيارة عقدة بعد تثبيتها؟
لا - بمجرد تثبيت عقدة تصبح مسافتها نهائية ولا يُعاد استرخاؤها أبدًا. من المزالق الشائعة في تنفيذات الكومة ترك إدخالات قديمة في طابور الأولوية بعد تحسّن مسافة عقدة؛ يجب تخطي العقدة المُخرَجة إن كانت مثبتة بالفعل (إذا تجاوزت مسافتها المُخرَجة المسافة المسجلة). نسيان هذا الفحص لا يزال يعطي إجابات صحيحة لكنه يهدر جهدًا.
Coddy programming languages illustration

أتقن الخوارزميات مع Coddy

ابدأ الآن