Dijkstra'nın ve Prim'in algoritmaları arasındaki tam fark nedir? Prim'in bir MST vereceğini biliyorum ama Dijkstra tarafından oluşturulan ağaç da bir MST olacak. O zaman tam fark nedir?
graph[u][v] < key[v]
dist[u]+graph[u][v] < dist[v]
Dijkstra'nın ve Prim'in algoritmaları arasındaki tam fark nedir? Prim'in bir MST vereceğini biliyorum ama Dijkstra tarafından oluşturulan ağaç da bir MST olacak. O zaman tam fark nedir?
graph[u][v] < key[v]
dist[u]+graph[u][v] < dist[v]
Yanıtlar:
Prim'in algoritması , grafik için, grafikteki tüm düğümleri birbirine bağlayan ve tüm düğümleri birbirine bağlayan tüm ağaçlar arasında en az toplam maliyeti olan bir ağaç olan minimum bir kapsayan ağaç oluşturur. Bununla birlikte, MST'deki herhangi iki düğüm arasındaki bir yolun uzunluğu, orijinal grafikteki bu iki düğüm arasındaki en kısa yol olmayabilir. MST'ler, örneğin, en az toplam maliyetle elektrik sağlamak için grafikteki düğümleri fiziksel olarak bağlamak istiyorsanız kullanışlıdır. İki düğüm arasındaki yol uzunluğunun optimal olmayabileceği önemli değil, çünkü tek umursadığın şey onların bağlantılı olmaları.
Dijkstra'nın algoritması , bazı kaynak düğümlerinden başlayarak en kısa yol ağacını oluşturur . En kısa yol ağacı, grafikteki tüm düğümleri tekrar kaynak düğüme bağlayan ve grafikteki kaynak düğümden herhangi bir başka düğüme giden yolun uzunluğunun en aza indirilmesi özelliğine sahip bir ağaçtır. Bu, örneğin herkesin önemli bir dönüm noktasına ulaşmasını mümkün olduğunca verimli kılan bir yol ağı oluşturmak istiyorsanız yararlıdır. Bununla birlikte, en kısa yol ağacının minimum kapsayan bir ağaç olacağı garanti edilmez ve en kısa yol ağacının kenarlarındaki maliyetlerin toplamı, bir MST'nin maliyetinden çok daha büyük olabilir.
Bir diğer önemli fark, algoritmaların hangi grafik türleri üzerinde çalıştığı ile ilgilidir. Bir MST kavramı grafiklerin doğası gereği yönlenmemiş olduğunu varsaydığından, Prim'in algoritması yalnızca yönsüz grafiklerde çalışır. (Yönlendirilmiş grafikler için "minimum yayılan arboresan" denen bir şey vardır, ancak onları bulmaya yönelik algoritmalar çok daha karmaşıktır). Dijkstra'nın algoritması, en kısa yol ağaçları gerçekten yönlendirilebildiği için yönlendirilmiş grafiklerde iyi çalışacaktır. Ek olarak, Dijkstra'nın algoritması , negatif kenar ağırlıkları içeren grafiklerde mutlaka doğru çözümü sağlamazken , Prim'in algoritması bunu halledebilir.
Bu yardımcı olur umarım!
the length of a path between **any** two nodes
, sadece src düğümü ile Prim'deki diğer düğümler arasındaki mesafenin en kısa değilse neden en kısa olmadığına odaklanmalısınız. Prim'deki src düğümünü başka herhangi bir düğüme soruyor olmalı . Prim'de neden herhangi iki düğüm hakkında konuştunuz ? Tabii ki bu en kısa değil.
Dijkstra'nın algoritması bir MST oluşturmaz, en kısa yolu bulur.
Bu grafiği düşünün
5 5
s *-----*-----* t
\ /
-------
9
En kısa yol 9 iken, MST 10'da farklı bir 'yol'dur.
The shortest path is 9
... s'den t'ye. Dijkstra algoritması tarafından oluşturulan s ile başlayan grafiğin ağırlığı 14'tür (5 + 9).
Prim ve Dijkstra algoritmaları, "gevşeme işlevi" dışında neredeyse aynıdır.
İlk:
MST-PRIM (G, w, r) {
for each key ∈ G.V
u.key = ∞
u.parent = NIL
r.key = 0
Q = G.V
while (Q ≠ ø)
u = Extract-Min(Q)
for each v ∈ G.Adj[u]
if (v ∈ Q)
alt = w(u,v) <== relax function, Pay attention here
if alt < v.key
v.parent = u
v.key = alt
}
Dijkstra:
Dijkstra (G, w, r) {
for each key ∈ G.V
u.key = ∞
u.parent = NIL
r.key = 0
Q = G.V
while (Q ≠ ø)
u = Extract-Min(Q)
for each v ∈ G.Adj[u]
if (v ∈ Q)
alt = w(u,v) + u.key <== relax function, Pay attention here
if alt < v.key
v.parent = u
v.key = alt
}
Tek fark, rahatlama işlevi olan okla belirtilir.
alt = w(u,v)
alt = w(u,v) + u.key
edges()
Dijkstra sahipken, MST kenarları dönüş distanceTo(v)
, pathTo(v)
s tepe ile initialize Dijkstra olduğu sırasıyla kaynaktan tepe v kaynaktan tepe v mesafe ve yolu döndürür.
edges()
, ancak Dijkstra başlatma farklı s için farklı çıkış döndürür distanceTo(v)
, pathTo(v)
.
Dijsktra'nın algoritması , düğüm i ile tüm düğümler arasındaki minimum mesafeyi bulur (i belirtirsiniz). Böylece, i düğümünden minimum uzaklık ağacını elde edersiniz.
Prims algoritması, belirli bir grafik için size minimum yayılma ağacını verir . Tüm maliyetlerin toplamı mümkün olan minimum iken tüm düğümleri birbirine bağlayan bir ağaç.
Yani Dijkstra ile seçilen düğümden diğerine minimum maliyetle gidebilirsiniz , bunu Prim'in
Gördüğüm tek fark, Prim'in algoritmasının minimum maliyet sınırını saklaması, Dijkstra'nın algoritmasının ise bir kaynak tepe noktasından geçerli tepe noktasına kadar olan toplam maliyeti depolamasıdır.
Dijkstra, maliyet minimum olacak şekilde kaynak düğümden hedef düğüme bir yol sağlar. Bununla birlikte, Prim'in algoritması, tüm düğümlerin bağlanacağı ve toplam maliyetin minimum olacağı şekilde size minimum bir yayılma ağacı verir.
Basit bir deyişle:
Bu nedenle, birkaç şehri birbirine bağlamak için bir tren yerleştirmek istiyorsanız, Prim'in algo'unu kullanırsınız. Ancak bir şehirden diğerine olabildiğince fazla zaman kazanmak istiyorsanız, Dijkstra'nın algoritmasını kullanırsınız.
Her ikisi de aşağıdaki gibi tam olarak aynı genel algoritma kullanılarak uygulanabilir:
Inputs:
G: Graph
s: Starting vertex (any for Prim, source for Dijkstra)
f: a function that takes vertices u and v, returns a number
Generic(G, s, f)
Q = Enqueue all V with key = infinity, parent = null
s.key = 0
While Q is not empty
u = dequeue Q
For each v in adj(u)
if v is in Q and v.key > f(u,v)
v.key = f(u,v)
v.parent = u
Prim f = w(u, v)
için geçiş ve Dijkstra geçişi için f = u.key + w(u, v)
.
Bir başka ilginç şey de, yukarıdaki Generic'in aynı zamanda Kapsamlı İlk Arama'yı (BFS) da uygulayabilmesidir, ancak bu aşırı olacaktır çünkü pahalı öncelik sırası gerçekten gerekli değildir. Genel algoritmayı BFS'ye dönüştürmek için, f = u.key + 1
tüm ağırlıkları 1'e zorlamakla aynı olan geçiş yapın (yani BFS, A noktasından B'ye geçmek için gereken minimum kenar sayısını verir).
Sezgi
İşte yukarıdaki genel algoritmayı düşünmenin iyi bir yolu: A ve B olmak üzere iki kova ile başlıyoruz. Başlangıçta, tüm köşelerinizi B'ye koyun, böylece A kovası boş olur. Sonra bir tepe noktasını B'den A'ya hareket ettiririz. Şimdi, A'daki köşelerden B'deki köşelere geçen tüm kenarlara bakın. Bu kesişen kenarlardan bazı kriterleri kullanarak bir kenarı seçtik ve karşılık gelen tepe noktasını B'den A'ya taşıdık. A. B boşalana kadar bu işlemi tekrarlayın.
Bu fikri hayata geçirmenin kaba kuvvet yolu, A'daki B'ye geçen köşeler için kenarların öncelik sırasını korumak olacaktır. Açıkçası, eğer grafik seyrek olmasaydı bu zahmetli olurdu. Öyleyse soru, bunun yerine öncelik sırasını koruyabilir miyiz? Aslında bu, nihayet kararımız olarak B'den hangi tepe noktasını seçeceğimizdir.
Tarihsel Bağlam
İlginçtir ki, her iki algoritmanın arkasındaki tekniğin jenerik versiyonu kavramsal olarak elektronik bilgisayarlar yokken bile 1930 kadar eskidir.
Hikaye, Moravya ülkesindeki (şimdi Çek Cumhuriyeti'nin bir parçası) şehirleri minimum maliyetli elektrik hatlarıyla nasıl bağlayacağını anlamaya çalışan bir aile dostu için bir algoritmaya ihtiyaç duyan Otakar Borůvka ile başlıyor. O zamanlar Bilgisayar Bilimleri olmadığı için algoritmasını matematikle ilgili bir dergide 1926'da yayınladı. Bu, Borůvka'nın algoritmasında bir gelişme düşünen ve bunu 1930'da yayınlayan Vojtěch Jarník'in dikkatini çekti. Aslında, 1957'de onu yeniden keşfeden Prim'in algoritması olarak bildiğimiz algoritmanın aynısını keşfetti.
Tüm bunlardan bağımsız olarak, 1956'da Dijkstra'nın enstitüsünün geliştirdiği yeni bir bilgisayarın yeteneklerini gösteren bir program yazması gerekiyordu. Hollanda'nın iki şehri arasında seyahat etmek için bilgisayarın bağlantı bulmasının harika olacağını düşündü. Algoritmayı 20 dakikada tasarladı. Bazı basitleştirmelerle (bilgisayarı 6 bit olduğu için) 64 şehirden oluşan bir grafik oluşturdu ve bu 1956 bilgisayarı için kod yazdı. Ancak algoritmasını öncelikle bilgisayar bilimi dergileri olmadığı için yayınlamadı ve bunun çok önemli olmayabileceğini düşündü. Ertesi yıl, yeni bilgisayarların terminallerini, kabloların uzunluğunu en aza indirecek şekilde bağlama sorununu öğrendi. Bu sorunu düşündü ve Jarník / Prim'i yeniden keşfetti Bir yıl önce keşfettiği en kısa yol algoritması ile aynı tekniği kullanan algoritma. Oher iki algoritmasının da kalem ve kağıt kullanılmadan tasarlandığından bahsetti . 1959'da her iki algoritmayı da sadece 2 buçuk sayfa uzunluğundaki bir makalede yayınladı .
Dijkstra, başlangıç düğümü ile diğer tüm düğümler arasındaki en kısa yolu bulur. Yani karşılığında, başlangıç düğümünden minimum mesafe ağacını elde edersiniz, yani diğer tüm düğümlere mümkün olduğunca verimli bir şekilde ulaşabilirsiniz.
Prims algoritması, size belirli bir grafik için MST'yi, yani tüm maliyetlerin toplamı mümkün olan minimum iken tüm düğümleri bağlayan bir ağaç verir.
Gerçekçi bir örnekle kısa bir hikaye yapmak için:
Doğrudan Dijkstra Algorithm'in wikipedia makalesinden:
Dijkstra'nın algoritmasının altında yatan süreç, Prim'in algoritmasında kullanılan açgözlü sürece benzer. Prim'in amacı, grafikteki tüm düğümleri birbirine bağlayan minimum bir kapsayan ağaç bulmaktır; Dijkstra yalnızca iki düğümle ilgileniyor. Prim, başlangıç düğümünden gelen yolun toplam ağırlığını değerlendirmez, yalnızca tek tek yolu değerlendirir.
Son zamanlarda aynı sorudan rahatsız oldum ve sanırım anlayışımı paylaşabilirim ...
Bence bu iki algoritma (Dijkstra ve Prim) arasındaki temel fark, çözmek için tasarlandıkları problemdeki kökler, yani iki düğüm arasındaki en kısa yol ve minimum yayılma ağacı (MST). Biçimsel olan, örneğin s ve t düğümleri arasındaki en kısa yolu bulmaktır ve rasyonel bir gereklilik, grafiğin her kenarını en fazla bir kez ziyaret etmektir. Ancak, tüm düğümü ziyaret etmemizi GEREKMEZ . İkincisi (MST), TÜM düğümü ziyaret etmemizi (en fazla bir kez) ve aynı rasyonel gereksinimle, her bir kenarı en fazla bir kez ziyaret etmemizi sağlamaktır .
Bu varlık Dijkstra kadar uzun alabilirsiniz "take kısayol" bizi tanır, söz konusu s için t sonucu endişelenmeden, - ben gidince t , işim bitti! Orada da bir yol olmasına rağmen s için t MST'deki, ancak bu s - t yolu her şey düğümlerinin hususlar ile oluşturulur, bu nedenle, bu yol daha uzun olabilir s - t yolu Dijstra algoritması tarafından bulundu. Aşağıda 3 düğümlü hızlı bir örnek verilmiştir:
2 2
(s) o ----- o ----- o (t)
| |
-----------------
3
Diyelim ki üst kenarların her birinin maliyeti 2 ve alt kenarın maliyeti 3, sonra Dijktra bize orta düğümü umursamadığımız için alt yolu seçmemizi söyleyecektir. Öte yandan, Prim bize alt kenarı atarak üst 2 kenarı olan bir MST döndürür.
Bu farklılık, uygulamalardaki ince farktan da yansıtılır: Dijkstra'nın algoritmasında, yeni bir düğümü absorbe ettikten sonra s'den en kısa yolu güncellemek için bir defter tutma adımına (her düğüm için) ihtiyaç duyulur , oysa Prim'in algoritmasında, böyle bir ihtiyaç yok.
Temel algoritmalar arasındaki temel fark, farklı kenar seçim kriterlerinde yatmaktadır. Genel olarak, her ikisi de sonraki düğümleri seçmek için bir öncelik kuyruğu kullanır, ancak mevcut işleme düğümlerinin bitişik düğümlerini seçmek için farklı kriterlere sahiptir: Prim'in Algoritması, sonraki bitişik düğümlerin de kuyrukta tutulmasını gerektirirken Dijkstra'nın Algoritması şunları yapmaz:
def dijkstra(g, s):
q <- make_priority_queue(VERTEX.distance)
for each vertex v in g.vertex:
v.distance <- infinite
v.predecessor ~> nil
q.add(v)
s.distance <- 0
while not q.is_empty:
u <- q.extract_min()
for each adjacent vertex v of u:
...
def prim(g, s):
q <- make_priority_queue(VERTEX.distance)
for each vertex v in g.vertex:
v.distance <- infinite
v.predecessor ~> nil
q.add(v)
s.distance <- 0
while not q.is_empty:
u <- q.extract_min()
for each adjacent vertex v of u:
if v in q and weight(u, v) < v.distance:// <-------selection--------
...
Köşe mesafesi hesaplamaları ikinci farklı noktadır.
Dijkstra'nın algoritması, i ve j düğümleri arasındaki tek kaynaklı en kısa yol problemidir, ancak Prim'in algoritması, asgari kapsamlı bir ağaç problemidir. Bu algoritma, 'açgözlü algoritma' adlı programlama konseptini kullanır
Bu fikri kontrol ederseniz, lütfen ziyaret edin
Dijkstras algoritması yalnızca en kısa yolu bulmak için kullanılır.
In minimum kapsayan ağacı (Prim veya Kruskal Algoritması) minimum kenar değeri ile asgari egdes olsun.
Örneğin: - Çok sayıda kablo gerektirecek büyük bir ağ oluşturmak istemeyeceğiniz bir durumu düşünün, böylece bu tel sayımı Minimum Genişleme Ağacı (Prim veya Kruskal algoritması) kullanılarak yapılabilir (yani, minimum maliyetle büyük kablolu ağ bağlantısı oluşturmak için size minimum sayıda kablo verir).
Oysa herhangi bir düğümü birbirine bağlarken iki düğüm arasındaki en kısa yolu elde etmek için "Dijkstras algoritması" kullanılacaktır.
En basit açıklama Prims'de Başlangıç Düğümünü belirtmezsiniz , ancak dijsktra'da (bir başlangıç düğümüne sahip olmanız gerekir) verilen düğümden diğer tüm düğümlere en kısa yolu bulmanız gerekir.
@templatetypedef, MST ve en kısa yol arasındaki farkı kapattı. Algoritma farkını başka bir So cevabında ele aldım , her ikisinin de girdi olarak bir parametre daha alan aynı genel algoritma kullanılarak uygulanabileceğini gösterdim: fonksiyon f(u,v)
. Prim ve Dijkstra'nın algoritması arasındaki fark basitçe f(u,v)
kullandığınız şeydir .
Kod düzeyinde, diğer fark API'dir.
Bir kaynak köşe noktasına sahip Prim başlatmak, s , yani Prim.new(s)
; s herhangi bir köşe olabilir ve s'den bağımsız olarak, minimum kapsayan ağacın (MST) kenarları olan nihai sonuç aynıdır. MST kenarlarını elde etmek için yöntemi çağırıyoruz edges()
.
Bir kaynak köşe noktasının ile Dijkstra başlatmak s , yani Dijkstra.new(s)
tüm diğer köşe için en kısa yol / mesafe almak istiyorum. En kısa yolu / mesafe olan uç sonuçlar, s diğer vertices; bağlı olarak farklıdır s . Dan en kısa yollar / mesafeleri almak için s herhangi köşe için v , biz yöntemleri çağırmak distanceTo(v)
ve pathTo(v)
sırasıyla.