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ş)
• 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
1interface Graph {2 nodes: Map; 3 edges: GraphEdge[];4}56interface GraphEdge {7 from: string;8 to: string;9 weight: number;10}1112// Floyd-Warshall algorithm for all-pairs shortest paths13function 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>(); 2021 // Initialize distance and next matrices22 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 });3536 // Set direct edge distances37 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 });4142 // Main Floyd-Warshall algorithm43 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 });5657 return { distances, next };58}5960// Reconstruct shortest path between two nodes61function reconstructPath(62 next: Map>, 63 start: string,64 end: string65): string[] {66 if (next.get(start)!.get(end) === null) {67 return []; // No path exists68 }6970 const path: string[] = [start];71 let current = start;7273 while (current !== end) {74 current = next.get(current)!.get(end)!;75 path.push(current);76 }7778 return path;79}8081// Usage example82const 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
Algoritma | Problem Türü | Zaman Karmaşıklığı | Alan Karmaşıklığı | Avantajlar |
---|---|---|---|---|
Floyd-Warshall | All-pairs shortest path | O(V³) | O(V²) | Negatif kenarlar, basit implementasyon |
Dijkstra | Single-source shortest path | O((V + E) log V) | O(V) | Hızlı, sparse graflarda verimli |
Bellman-Ford | Single-source shortest path | O(VE) | O(V) | Negatif kenarlar, negatif çevrim tespiti |
Johnson's | All-pairs shortest path | O(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.