Prim ve Dijkstra algoritmaları arasındaki fark nedir?


99

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?


5
Dijkstra. "ij" Hollandaca'da bir diphthongdur (kayan sesli harf) ve "j" nin ünsüz olmadığı tek yerdir.

23
Soruyu almanın herhangi bir yolu.
anuj pradhan

5
Aralarındaki farkı ayırt etmenin en iyi yolu , Dijkstra ve Prim gibi bazı kaynak kodları okumaktır . Temel fark burada: Prim ve Dijkstra için . Bu iki sayfadaki grafiklerden de görebileceğiniz gibi , temelde bu iki satır kod yüzünden farklılar . graph[u][v] < key[v]dist[u]+graph[u][v] < dist[v]
JW.ZG

Yanıtlar:


151

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!


İlk paragraf anlamsız adamım. Soru, Dijkstra ve Prim arasındaki farkın ne olduğudur, burada Dijkstra söylediklerinizle ilgili değildir 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.
JW.ZG

2
En kısa yol ağacının, kaynak düğümden kaynaklanan en kısa yollar için yalnızca bir küçültücü olduğunu açıklığa kavuşturmak için, Dijkstra algoritmasıyla ilgili paragraftaki ifadeleri temizledim. Cevabımı bu şekilde yapılandırmamın nedeni , algoritmaların neden farklı sonuçlar ürettiklerini ve neden aynı olmasını beklemeyeceğinizi daha yüksek bir seviyede göstermek için nasıl çalıştıklarından ziyade bulduklarını göstermenin bir yoluydu .
templatetypedef

1
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. Bkz stackoverflow.com/a/51605961/6668734
Deepak Yadav

1
@templatetypedef - Dediğinizde: "ve [Dijkstra ile] böyle bir ağaç inşa etmenin maliyeti bir MST'nin maliyetinden çok daha fazla olabilir ." detaylandırır mısın lütfen?
Amelio Vazquez-Reina

1
@ AmelioVazquez-Reina Üzgünüm, bu biraz belirsiz. Demek istediğim, en kısa yollar ağacının kenarlarındaki ağırlıkların toplamı, bir MST'de kenarlardaki ağırlıkların toplamından çok daha büyük olabilir.
templatetypedef

85

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.


2
Tamam teşekkürler ... iyi bir noktayı fark ettin. Şimdiye kadar dijkstra tarafından üretilen çıktının bir MST olacağını düşünüyordum ama şüpheyi iyi bir örnekle ortadan kaldırdınız. . Çok teşekkürler
anuj pradhan

8
Daha doğrusu - 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).
Bernhard Barker

1
@Dukeling - Huh? Dijkstra'daki ağacın / grafiğin ağırlığı anlamsız, mesele bu ....
dfb

4
Çok kısa ve öz bir şekilde gösterilmiştir!
Ram Narasimhan

1
@dfb: Normalde, belirli bir köşe çifti arasındaki en kısa yolu elde etmek için yalnızca Dijkstra algoritmasını çalıştırırız, ancak aslında tüm köşeler ziyaret edilene kadar devam edebilirsiniz ve bu size templatetypedef'in cevabı olarak "en kısa yol ağacı" verecektir açıklıyor.
j_random_hacker

65

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.

  • Minimum yayılma ağacını arayan Prim, yalnızca tüm köşeleri kapsayan toplam kenarların minimumuyla ilgilenir. Rahatlama işlevialt = w(u,v)
  • Minimum yol uzunluğunu arayan Dijkstra, bu nedenle kenar birikimini önemsiyor. Rahatlama işlevialt = w(u,v) + u.key

Kod düzeyinde, diğer fark API'dir. Prim yöntemi vardır 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.
nethsix

1
Doğal sonucu Prim ile herhangi bir herhangi bir kaynak tepe başlatılırken, döner için aynı çıkış s edges(), ancak Dijkstra başlatma farklı s için farklı çıkış döndürür distanceTo(v), pathTo(v).
nethsix

Primler negatif ağırlığa izin veriyor mu? eğer evetse bu başka bir farktır. Büyük pozitif no ekleyerek primlerin üzerinde negatif ağırlıklara izin verebileceğinizi okudum. her bir değere, her şeyi olumlu kılar.
Akhil Dad

1
Kafa karışıklığımı çözdüm! Mükemmel cevap!!
Dhananjay Sarsonia

burada işlenen tepe yönsüz grafik için göz ardı edilmelidir
Bay AJ,

53

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


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. Bkz stackoverflow.com/a/51605961/6668734
Deepak Yadav

32

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.


24

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 + 1tü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ı .


Teşekkürler! Çıkış belirsiz, hiçbir şey olmasa bile neden döngüden çıkıyor?
amirouche

15

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:

  1. Dijkstra, yolculuk süresinden ve yakıttan tasarruf ederek her bir varış noktasına en kısa yolu bilmek istiyor.
  2. Prim, bir tren ray sisteminin verimli bir şekilde nasıl konuşlandırılacağını, yani malzeme maliyetlerinden nasıl tasarruf edileceğini bilmek istiyor.

10

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.


5
"Dijkstra sadece iki düğümle ilgileniyor" ranzadır.
tmyklebu

5

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.


3

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.


3

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

  1. Açgözlü algoritma ders notu: http://jeffe.cs.illinois.edu/teaching/algorithms/notes/07-greedy.pdf
  2. Minimum kapsayan ağaç: http://jeffe.cs.illinois.edu/teaching/algorithms/notes/20-mst.pdf
  3. Tek kaynaklı en kısa yol: http://jeffe.cs.illinois.edu/teaching/algorithms/notes/21-sssp.pdf

2

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.


2

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.


0

@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 .


0

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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.