Menu
Coddy logo textTech

Dijkstra Algoritması

Son güncelleme

Dijkstra algoritması, negatif olmayan kenar ağırlıklarına sahip bir grafta bir kaynak düğümden diğer tüm düğümlere en kısa yolu bulur. Her düğüm için geçici bir mesafe tutar, en küçük geçici mesafeye sahip yerleşmemiş düğümü tekrar tekrar yerleştirir ve kenarlarını gevşetir; mevcut düğüm üzerinden daha kısa bir rota bulunduğunda bir komşunun mesafesini günceller. Her düğüm yerleştikçe mesafelerin düşüşünü izlemek için yukarıdan oynat düğmesine basın.

Temel fikir açgözlüdür: en yakın yerleşmemiş düğüm seçildiğinde mesafesi kesinleşir, çünkü ona giden diğer tüm rotalar zaten daha uzakta olan bir düğümden geçmek zorunda kalır. İkili yığın öncelik kuyruğuyla Dijkstra O((V + E) log V) sürede çalışır. Negatif olmayan ağırlıklar gerektirir; kenarlar negatif olabiliyorsa Bellman-Ford kullanın.

Zaman ve alan karmaşıklığı

UygulamaKarmaşıklıkNotlar
İkili yığınO((V + E) log V)Yaygın ve pratik seçim
Dizi taramasıO(V²)Daha basit; yoğun graflar için uygun
AlanO(V)Mesafeler + öncelik kuyruğu
GerektirirNegatif olmayan ağırlıklarNegatif kenarlar açgözlü seçimi bozar

Adım adım

AdımNe olur
1Kaynak mesafesini 0, diğerlerinin hepsini sonsuz olarak ayarlayın.
2En küçük geçici mesafeye sahip yerleşmemiş düğümü seçin.
3Onu yerleşmiş olarak işaretleyin: en kısa mesafesi artık kesindir.
4Her komşu için mevcut-üzerinden-mesafe + kenar ağırlığını hesaplayın.
5Bu, komşunun mevcut mesafesinden küçükse onu gevşetin.
6Ulaşılabilir tüm düğümler yerleşene kadar tekrarlayın.

Çözümlü örnek

A-B=4, A-C=1, C-B=2, C-D=5, B-D=1 kenarlarına sahip grafta kaynak A'dan en kısa yollar:

AdımYerleştirMesafelerEylem
0-A=0, B=∞, C=∞, D=∞Başlat: kaynak A=0, diğerlerinin hepsi sonsuz.
1A (0)B=4, C=1, D=∞A'dan kenarları gevşet: B=4, C=1 ayarla.
2C (1)B=3, D=6C üzerinden: B=1+2=3, 4'ü geçer; D=1+5=6.
3B (3)D=4B üzerinden: D=3+1=4, 6'yı geçer.
4D (4)A=0, C=1, B=3, D=4D'yi yerleştir; gevşetilecek bir şey kalmadı. Bitti.

Dijkstra algoritması ne zaman kullanılır

Şu durumda kullanınŞu durumda kaçının
Tüm kenar ağırlıkları negatif değilseHerhangi bir kenar negatif olabiliyorsa: Bellman-Ford kullanın
Bir kaynaktan tüm düğümlere en kısa yollara ihtiyacınız varsaTüm çiftler arası en kısa yollara ihtiyacınız varsa: Floyd-Warshall daha basittir
Graf ağırlıklıysa ve kesin mesafeler istiyorsanızGraf ağırlıksızsa: düz BFS daha hızlı ve basittir
İyi bir yığın veya öncelik kuyruğunuz varsaBir sezgiselle tek bir hedefe hızlıca ulaşmak istiyorsanız: A* kullanın

Dijkstra's Algorithm kodu

Python, JavaScript, Java, C++, C dillerinde temiz ve çalıştırılabilir bir Dijkstra's Algorithm uygulaması. Bir dil seçin, kodu kopyalayın veya Coddy Playground'da hazır yüklenmiş olarak açın.

Python ile Dijkstra's Algorithm kodu

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}")
Bu kodu Python Playground'da çalıştır

Dijkstra Algoritması SSS

Dijkstra algoritmasının zaman karmaşıklığı nedir?
İkili yığın öncelik kuyruğuyla O((V + E) log V) sürede çalışır. Her adımda minimumu bulmak için bir diziyi tarayan basit sürüm O(V²)'dir ve yoğun graflarda aslında daha hızlı olabilir. İkisi de O(V) alan kullanır.
Dijkstra neden negatif kenar ağırlıklarıyla çalışmaz?
Dijkstra, en yakın yerleşmemiş düğümü yerleştirdiğinde o mesafenin kesin olduğunu varsayar. Negatif bir kenar, daha sonra zaten yerleşmiş bir düğüme daha kısa bir yol oluşturarak bu varsayımı bozabilir. Negatif ağırlıklı graflar için Bellman-Ford algoritmasını kullanın.
Dijkstra ile BFS arasındaki fark nedir?
BFS, kenarları sayarak (her kenar ağırlığı etkin olarak 1) düz bir kuyruk kullanarak en kısa yolları bulur. Dijkstra bunu ağırlıklı graflara genelleştirir; her zaman en küçük toplam mesafeye sahip düğümü bir öncelik kuyruğu kullanarak genişletir. Ağırlıksız bir grafta ikisi de aynı yolları üretir.
Dijkstra ile A* araması arasındaki fark nedir?
A*, bir hedefe kalan mesafeyi tahmin eden bir sezgisel eklenmiş Dijkstra'dır; böylece her yöne eşit yayılmak yerine aramayı o hedefe yönlendirir. Sezgisel sıfır olduğunda A*, tam olarak Dijkstra'ya dönüşür. Tek bir hedefiniz ve iyi bir kabul edilebilir sezgiseliniz varsa A* kullanın; tüm düğümlere mesafelere ihtiyacınız varsa Dijkstra kullanın.
Bellman-Ford yerine ne zaman Dijkstra kullanmalıyım?
Tüm kenar ağırlıkları negatif olmadığında her zaman Dijkstra kullanın: Bellman-Ford'un O(V·E)'sine karşı O((V + E) log V) ile daha hızlıdır. Bellman-Ford'u yalnızca kenarlar negatif olabildiğinde veya negatif döngüleri tespit etmeniz gerektiğinde seçin. Negatif olmayan graflarda Dijkstra neredeyse her zaman daha iyi seçenektir.
Dijkstra bir düğümü yerleştirdikten sonra tekrar ziyaret edebilir mi?
Hayır: bir düğüm yerleştirildiğinde mesafesi kesinleşir ve bir daha asla gevşetilmez. Yığın uygulamalarında yaygın bir tuzak, bir düğümün mesafesi iyileştikten sonra öncelik kuyruğunda eski girişler bırakmaktır; çıkarılan bir düğüm zaten yerleşmişse (çıkarılan mesafesi kaydedilen mesafeyi aşarsa) onu atlamalısınız. Bu kontrolü unutmak yine de doğru yanıtlar verir ama boşa iş yaptırır.
Coddy programming languages illustration

Coddy ile algoritmalarda ustalaş

BAŞLA