Wpisany przez Michał Knasiecki,
09 sierpnia 2005 21:49
Zrozumienie algorytmu wymaga znajomości pojęć grafu oraz
minimalnego drzewa rozpinającego
Algorytm ten jest oparty o metodę zachłanną.
Budowę minimalnego drzewa rozpinającego zaczynamy od dowolnego wierzchołka, np. od pierwszego. Dodajemy wierzchołek do drzewa a wszystkie krawędzie incydentne umieszczamy na posortowanej wg. wag liście. Następnie zdejmujemy z listy pierwszą krawędź (o najmniejszej wadze). Sprawdzamy, czy drugi wierzchołek tej krawędzi należy do tworzonego drzewa. Jeżeli tak, to nie ma sensu dodawać takiej krawędzi (bo oba jej wierzchołki znajdują sięw drzewie), porzucamy krawędź i pobieramy z listy następną. Jeżeli jednak wierzchołka nie ma w drzewie, to należy dodać krawędź do drzewa, by wierzchołek ten znalazł się w drzewie rozpinającym. Następnie dodajemy do posortowanej listy wszystkie krawędzie incydentne z dodanym wierzchołkiem i pobieramy z niej kolejny element.
Jednym zdaniem: zawsze dodajemy do drzewa krawędź o najmniejszej wadze, osiągalną (w przeciwieństwie do Kruskala) z jakiegoś wierzchołka tego drzewa.
Można zauważyć, że kluczową, z punktu widzenia wydajności algorytmu, czynnością jest zaimplementowanie listy posortowanej, gdyż po każdym dodaniu krawędzi, lista musi być nadal posortowana.
Przyjmijmy następującą notację: [ui, uj, w] oznacza krawędź łączącą wierzchołki (ui, uj) o wadze w.
Dany jest spójny graf nieskierowany:
Przebieg algorytmu:
Suma wag krawędzi wchodzących w skład drzewa wynosi 10.
Zobacz też: Algorytm Kruskala.
Algorytm ten jest oparty o metodę zachłanną.
Budowę minimalnego drzewa rozpinającego zaczynamy od dowolnego wierzchołka, np. od pierwszego. Dodajemy wierzchołek do drzewa a wszystkie krawędzie incydentne umieszczamy na posortowanej wg. wag liście. Następnie zdejmujemy z listy pierwszą krawędź (o najmniejszej wadze). Sprawdzamy, czy drugi wierzchołek tej krawędzi należy do tworzonego drzewa. Jeżeli tak, to nie ma sensu dodawać takiej krawędzi (bo oba jej wierzchołki znajdują sięw drzewie), porzucamy krawędź i pobieramy z listy następną. Jeżeli jednak wierzchołka nie ma w drzewie, to należy dodać krawędź do drzewa, by wierzchołek ten znalazł się w drzewie rozpinającym. Następnie dodajemy do posortowanej listy wszystkie krawędzie incydentne z dodanym wierzchołkiem i pobieramy z niej kolejny element.
Jednym zdaniem: zawsze dodajemy do drzewa krawędź o najmniejszej wadze, osiągalną (w przeciwieństwie do Kruskala) z jakiegoś wierzchołka tego drzewa.
Można zauważyć, że kluczową, z punktu widzenia wydajności algorytmu, czynnością jest zaimplementowanie listy posortowanej, gdyż po każdym dodaniu krawędzi, lista musi być nadal posortowana.
Przykład:
Przyjmijmy następującą notację: [ui, uj, w] oznacza krawędź łączącą wierzchołki (ui, uj) o wadze w.
Dany jest spójny graf nieskierowany:
Przebieg algorytmu:
Wybieramy wierzchołek a. Tworzymy posortowaną listę L={[a,e,1],[a,f,2],[a,b,4]} Wybieramy krawędź (a,e). |
Dodajemy nowe krawędzie: L={[a,f,2],[e,b,2],[e,d,3],[a,b,4],[e,f,7]} Wybieramy krawędź (a,f). |
Krawędź [f,e,7] jest już na liście: L={[e,b,2],[e,d,3],[a,b,4],[f,d,6],[e,f,7]} Wybieramy krawędź (e,b). |
Dodajemy krawędź (b,c): L={[b,c,2],[e,d,3],[a,b,4],[f,d,6],[e,f,7]} Wybieramy krawędź (b,c). |
Dodajemy krawędź (c,d): L={[e,d,3],[a,b,4],[f,d,6],[e,f,7],[c,d,8]} Wybieramy krawędź (e,d). |
Drzewo utworzone. |
Suma wag krawędzi wchodzących w skład drzewa wynosi 10.
Zobacz też: Algorytm Kruskala.
Implementacje
Autor | Język programowania | Komentarz | Otwórz | Pobierz | Ocena |
Marcin Walewski | C/C++ | .cpp | .cpp | ***** / 28 | |
Michał Knasiecki | Delphi/Pascal | Borland Delphi 5 | .pas | .pas | ***** / 10 |
mephisto | Java | Wersja leniwa algorytmu | .java | .java | ***** / 4 |
Poprawiony: 16 sierpnia 2012 20:25
Pozdrawiam,
Kamil
Może zgłoś to do jakiejś organizacji, bo właśnie chcesz wykazać, że stosowany od lat algorytm, którego poprawne działanie UDOWODNIONO, nie działa. Może Ci pomnik postawią.
prim(0); // start at vertex 0
cout