Algorytma Prima pozwala znaleźć w grafie nieskierowanym minimalne drzewo rozpinające. Każda z krawędzi musi mieć określoną wagę. To na podstawie tych wartości algorytm będzie dopasowywał je do drzewa. Punktem początkowym może być dowolny wierzchołek grafu. Innymi słowy minimalne drzewo rozpinające uzyskane na końcu zawsze będzie takie samo dla tego samego grafu.
Dla każdego wierzchołka określamy, że jego koszt wynosi nieskończoność, a poprzednik jest nieokreślony. Wybranemu wierzchołkowi przypisujemy wartość 0, a następnie tworzymy kolejkę wierzchołków do rozpatrzenia. W kolejce dane są posortowane po koszcie elementu. Następnie, dopóki kolejka nie jest pusta, wybieramy wierzchołek o najniższym koszcie i aktualizujemy jego sąsiadów, którzy występują w kolejce. Jeśli krawędź z wybranego wierzchołka z kolejki do sąsiada ma niższą wartość niż sąsiad ma koszt to aktualizujemy informacje.
Rozpatrzmy następujący graf:
Zgodnie z algorytmem najpierw utwórzmy dla każdego wierzchołka parę danych: koszt i poprzednika. Szukamy drzewa rozpoczynając od wierzchołka 0.
Kolejka | 0 | 1 | 2 | 3 | 4 | 5 | Wybrany | Komentarz |
---|---|---|---|---|---|---|---|---|
0, 1, 2, 3, 4, 5 | 0 | -1 | ∞ | -1 | ∞ | -1 | ∞ | -1 | ∞ | -1 | ∞ | -1 | 0 | Usuwamy 0 z kolejki i aktualizujemy sąsiadów |
1, 2, 3, 4, 5 | 0 | -1 | 4 | 0 | 5 | 0 | ∞ | -1 | ∞ | -1 | ∞ | -1 | 1 | Najmniejszy koszt wierzchołek 1 |
2, 3, 4, 5 | 0 | -1 | 4 | 0 | 3 | 1 | 4 | 1 | ∞ | -1 | ∞ | -1 | 2 | Najmniejszy koszt wierzchołek 2 |
3, 4, 5 | 0 | -1 | 4 | 0 | 3 | 1 | 2 | 2 | 6 | 2 | 1 | 2 | 5 | Najmniejszy koszt wierzchołek 5 |
3, 4 | 0 | -1 | 4 | 0 | 3 | 1 | 2 | 2 | 5 | 5 | 1 | 2 | 3 | Najmniejszy koszt wierzchołek 3 |
3 | 0 | -1 | 4 | 0 | 3 | 1 | 2 | 2 | 4 | 3 | 1 | 2 | 4 | Najmniejszy koszt wierzchołek 4 |
- | 0 | -1 | 4 | 0 | 3 | 1 | 2 | 2 | 4 | 3 | 1 | 2 | - | Kolejka pusta, koniec algorytmu |
Dla każdego wierzchołka zostały otrzymane dwie wartości. Pierwsza z nich określa koszt wierzchołka. Suma tej wartości dla wszystkich wierzchołków da łączną wartość minimalnego drzewa rozpinającego. W tym przypadku wynosi ona 14. Z kolei druga wartość poprzednik pozwala określić, które węzły są ze sobą połączone. W tym przypadku warto pamiętać, że graf nie jest skierowany. Na podstawie otrzymanych danych można narysować następujące minimalne drzewo rozpinające:
Złożoność algorytmu jest zależna od implementacji kolejki. Niemniej wewnątrz algorytmu przechodzimy po wszystkich n elementach kolejki i za każdym razem aktualizujemy n sąsiadów. Oznacza to, że sam algorytm ma złożoność O(n2). Jednak należy pamiętać, że dodatkowo w każdej pętli należy uaktualnić kolejkę priorytetową, albo przeszukiwać listę w celu znalezienia minimalnego elementu.
Algorytm otrzymuje jako argumeny macierz sąsiedztwa grafu, a w wyniku zwraca parę danych: koszt i poprzednik dla każdego wierzchołka. Program nie sprawdza poprawności danych wejściowych. W celu wczytania przykładowego grafu należy podać go w następujący sposób:
Funkcja AlgorytmPrima() spełnia opisane wyżej założenia. W celu wyszukiwania minimalnego elementu w kolejce wykorzystuje wyszukiwanie.
(3.) Utwórz miejsce do zapisu wyniku, (3. - 6.) wypełnij domyślnymi wartościami oraz (7.) przypisz pierwszemu wierzchołkowi zerowy koszt. Następnie (8. - 10.) utwórz kolejkę i (11.) operuj na niej, aż zostanie pusta. (12. - 16.) Znajdź element w kolejce o najniższym koszcie. Potem (17.) dla każdego jego sąsiada: (18. - 19.) sprawdź czy istnieje pomiędzy nimi krawędź i czy sąsiad jest w kolejce oraz (20.) czy koszt trzeba zaktualizować. Jeśli tak to (21. - 22.) należy to wykonać. Na koniec pętli (25. - 26.) należy pamiętać o usunięciu wybranego z kolejki elementu! Na koniec zwracana jest wyznaczona tablica wynik.
W celu przetestowania działania napisanej funkcji można skorzystać z poniższego fragmentu kodu: