Floyd-Warshall Algoritması

Floyd-Warshall algoritması, ağırlıklı bir grafta tüm düğüm çiftleri arasındaki en kısa yolları bulan dinamik programlama tabanlı bir algoritmadır. Roy Warshall ve Robert Floyd tarafından geliştirilmiş olup, pozitif ve negatif kenar ağırlıklarını destekler ancak negatif çevrimler olmamalıdır.

Avantajlar

  • Tüm düğüm çiftleri arasındaki en kısa yolları tek seferde bulur
  • Negatif kenar ağırlıklarını destekler
  • Negatif çevrimleri tespit edebilir
  • Uygulaması basit ve anlaşılırdır
  • Yol rekonstrüksiyonu için next matrisi sağlar
  • Dense (yoğun) graflarda verimli çalışır

Dezavantajlar

  • Zaman karmaşıklığı O(V³)'tür, büyük graflarda yavaş
  • Alan karmaşıklığı O(V²), büyük graflarda bellek problemi
  • Negatif çevrimler varsa sonuçlar geçersiz olur
  • Sparse (seyrek) graflarda diğer algoritmalardan daha yavaş
  • Tek kaynak en kısa yol problemleri için aşırı kapsamlı

İnteraktif Görselleştirme

Komşuluk Matrisi (Giriş)

0
1
2
3
4
0
1
2
3
4

• Komşuluk matrisinde kenar ağırlıklarını girin

• Boş hücreler sonsuz (∞) mesafe olarak kabul edilir

• Köşegen elemanlar (kendinden kendine mesafe) otomatik olarak 0'dır

Floyd-Warshall Algoritması

Zaman Karmaşıklığı: O(n³) - Üç iç içe döngü kullanır

Alan Karmaşıklığı: O(n²) - İki boyutlu mesafe matrisi

Çalışma Prensibi: Her iterasyonda, bir ara düğüm (k) üzerinden geçen yolları kontrol eder ve daha kısa yol bulursa günceller.

Kullanım Alanları: Ağ yönlendirme, şehir planlama, oyun geliştirme (NPC navigasyonu), graf analizi

Kod Örnekleri

Floyd-Warshall - TypeScript
1interface Graph {
2 nodes: Map;
3 edges: GraphEdge[];
4}
5
6interface GraphEdge {
7 from: string;
8 to: string;
9 weight: number;
10}
11
12// Floyd-Warshall algorithm for all-pairs shortest paths
13function floydWarshall(graph: Graph): {
14 distances: Map>;
15 next: Map>;
16} {
17 const nodeIds = Array.from(graph.nodes.keys());
18 const distances = new Map>();
19 const next = new Map>();
20
21 // Initialize distance and next matrices
22 nodeIds.forEach(i => {
23 distances.set(i, new Map());
24 next.set(i, new Map());
25
26 nodeIds.forEach(j => {
27 if (i === j) {
28 distances.get(i)!.set(j, 0);
29 } else {
30 distances.get(i)!.set(j, Infinity);
31 }
32 next.get(i)!.set(j, null);
33 });
34 });
35
36 // Set direct edge distances
37 graph.edges.forEach(edge => {
38 distances.get(edge.from)!.set(edge.to, edge.weight);
39 next.get(edge.from)!.set(edge.to, edge.to);
40 });
41
42 // Main Floyd-Warshall algorithm
43 nodeIds.forEach(k => {
44 nodeIds.forEach(i => {
45 nodeIds.forEach(j => {
46 const currentDistance = distances.get(i)!.get(j)!;
47 const newDistance = distances.get(i)!.get(k)! + distances.get(k)!.get(j)!;
48
49 if (newDistance < currentDistance) {
50 distances.get(i)!.set(j, newDistance);
51 next.get(i)!.set(j, next.get(i)!.get(k));
52 }
53 });
54 });
55 });
56
57 return { distances, next };
58}
59
60// Reconstruct shortest path between two nodes
61function reconstructPath(
62 next: Map>,
63 start: string,
64 end: string
65): string[] {
66 if (next.get(start)!.get(end) === null) {
67 return []; // No path exists
68 }
69
70 const path: string[] = [start];
71 let current = start;
72
73 while (current !== end) {
74 current = next.get(current)!.get(end)!;
75 path.push(current);
76 }
77
78 return path;
79}
80
81// Usage example
82const graph: Graph = createExampleGraph();
83const result = floydWarshall(graph);
84const path = reconstructPath(result.next, '0', '3');
85console.log('Shortest path from 0 to 3:', path);
86console.log('Distance:', result.distances.get('0')!.get('3'));

Algoritma Nasıl Çalışır?

Floyd-Warshall algoritması, dinamik programlama prensibini kullanarak tüm düğüm çiftleri arasındaki en kısa yolları hesaplar. Algoritmanın temel çalışma prensibi şu adımlardan oluşur:

1. Başlangıç Matrisi Oluşturma

İlk adımda, grafın komşuluk matrisinden yola çıkarak bir mesafe matrisi oluşturulur. Bu matrisin köşegen elemanları 0 (düğümden kendisine mesafe), doğrudan bağlantı olan düğümler arasındaki mesafeler kenar ağırlıkları, diğer tüm elemanlar ise sonsuz (∞) olarak ayarlanır.

2. Ara Düğüm İterasyonları

Algoritmanın ana döngüsünde, her düğüm k için, tüm düğüm çiftleri (i,j) kontrol edilir. Eğer i'den j'ye doğrudan gitmek yerine k üzerinden gitmek daha kısa bir yol sağlıyorsa, mesafe matrisi güncellenir:

if (distance[i][k] + distance[k][j] < distance[i][j]) {distance[i][j] = distance[i][k] + distance[k][j]; next[i][j] = next[i][k];}

3. Yol Rekonstrüksiyonu

Algoritma aynı zamanda bir "next" matrisi tutar. Bu matris, herhangi iki düğüm arasındaki en kısa yolda bir sonraki düğümün ne olduğunu saklar. Bu sayede algoritma tamamlandıktan sonra, sadece mesafeyi değil, gerçek yolu da elde edebiliriz.

4. Negatif Çevrim Tespiti

Floyd-Warshall algoritması çalıştıktan sonra, eğer mesafe matrisinin köşegen elemanlarından herhangi biri negatif ise, bu grafta negatif çevrim olduğunu gösterir. Negatif çevrimler varsa, en kısa yol kavramı anlamsız hale gelir çünkü çevrimde sürekli dolaşarak mesafeyi sonsuzca azaltabiliriz.

5. Algoritmanın Doğruluğu

Algoritmanın doğruluğu matematiksel tümevarım ile kanıtlanabilir. k'ıncı iterasyondan sonra, distance[i][j] değeri i'den j'ye giden ve sadece {1, 2, ..., k} düğümlerini ara düğüm olarak kullanan en kısa yolun uzunluğunu verir.

Karmaşıklık Analizi

Zaman Karmaşıklığı

O(V³): Üç iç içe döngü nedeniyle

  • Dış döngü: V iterasyon (her düğüm için)
  • İç döngüler: V × V = V² işlem her iterasyonda
  • Toplam: V × V² = V³ işlem

Not: Bu karmaşıklık tüm durumlar için sabittir, en iyi, ortalama ve en kötü durum aynıdır.

Alan Karmaşıklığı

O(V²): İki boyutlu matrisler için

  • Mesafe matrisi: V × V boyutunda
  • Next matrisi: V × V boyutunda (yol rekonstrüksiyonu için)
  • Toplam: 2 × V² alan

Optimizasyon: Eğer sadece mesafeler gerekiyorsa, next matrisi kullanılmayabilir.

Diğer Algoritmalarla Karşılaştırma

AlgoritmaProblem TürüZaman KarmaşıklığıAlan KarmaşıklığıAvantajlar
Floyd-WarshallAll-pairs shortest pathO(V³)O(V²)Negatif kenarlar, basit implementasyon
DijkstraSingle-source shortest pathO((V + E) log V)O(V)Hızlı, sparse graflarda verimli
Bellman-FordSingle-source shortest pathO(VE)O(V)Negatif kenarlar, negatif çevrim tespiti
Johnson'sAll-pairs shortest pathO(V²log V + VE)O(V²)Sparse graflarda Floyd-Warshall'dan hızlı

Gerçek Dünya Uygulamaları

Ağ Yönlendirme

İnternet protokollerinde, routerlar arasındaki en kısa yolları bulmak için kullanılır. OSPF (Open Shortest Path First) protokolü Floyd-Warshall'ın bir varyasyonunu kullanır.

Ulaşım Planlama

Şehir içi ulaşım sistemlerinde, herhangi iki nokta arasındaki en kısa yolu ve süreyi hesaplamak için kullanılır. GPS navigasyon sistemlerinin temelinde yer alır.

Oyun Geliştirme

Oyun haritalarında NPC'lerin (Non-Player Character) herhangi iki nokta arasındaki en kısa yolu bulması için kullanılır. Özellikle RTS (Real-Time Strategy) oyunlarında yaygındır.

Sosyal Ağ Analizi

Sosyal ağlarda, iki kişi arasındaki "altı derece ayrılık" teorisini test etmek ve sosyal bağlantıların gücünü ölçmek için kullanılır.

⚠️ Önemli Notlar

  • Floyd-Warshall algoritması negatif çevrimler içeren graflarda doğru sonuç vermez. Algoritma çalıştırılmadan önce negatif çevrim kontrolü yapılmalıdır.
  • Büyük graflarda (V > 1000) performans sorunu yaşanabilir. Bu durumda Johnson's algoritması veya tekrarlı Dijkstra tercih edilmelidir.
  • Algoritma dense (yoğun) graflar için optimize edilmiştir. Sparse (seyrek) graflarda diğer algoritmalar daha verimli olabilir.
  • Floating-point sayılarla çalışırken, sayısal hassasiyet sorunları yaşanabilir. Bu durumda epsilon değeri kullanarak karşılaştırma yapılmalıdır.