Struktura przechowująca grafy w komputerze różni się złożonością pamięciową. Należy również pamiętać, że stosowany sposób przechowywania może różnić się w zależności od przechowywanego typu grafu. Przedstawiony poniżej kod pozwala na przechowywanie grafu nieskierowanego bez wag krawędziowych.
Jednym z sposobów na przechowanie grafu w komputerze jest macierz sąsiedztwa. Jednak ta technika jest mało wydajna pamięciowo jeśli jest bardzo mało krawędzi, a ponadto każda krawędź jest przechowywana podwójnie. To powoduje kolejne komplikacje, że należy pamiętać o podwójnej aktualizacji danych (jeśli krawędź nie jest skierowana). Na podstawie tych powodów warto zastanowić się nad jak najprostszym i najszybszym sposobem.
Dobrym pomysłem jest, aby każdy wierzchołek posiadał listę wierzchołków z którymi jest połączony. Ponadto przyjmując, że graf nie jest skierowany to można ograniczyć liczbę przechowywanych informacji o połączeniach. Jeśli krawędź (x, y) istnieje to (y, x) też. Przypuśćmy, że x < y wtedy istnienie krawędzi (y, x) sprawdzimy szukając krawędzi (x, y). W ten sposób liczba przechowywanych danych spada o połowę.
Dany jest następujący graf:
Można go zapisać w następującej postaci:
Wierzchołek | Połączenia |
---|---|
0 | 1, 2, 3 |
1 | 2 |
2 | - |
3 | - |
W celu sprawdzenia czy istnieje krawędź (1, 2) należy sprawdzić w liście połączeń wierzchołka 1 czy istnieje wartość 2. W przypadku szukania krawędzi (3, 2) należy zamienić wartościami miejscami tj. (2, 3) i dopiero sprawdzić czy wierzchołek 2 ma połącznie z wierzchołkiem 3.
Wierzchołek to elementarna część grafu. Będzie on przechowywał listę wierzchołków z którymi jest połączony na liście. Dodatkowo będzie pozwalał na wykonanie dwóch podstawowych operacji: dodania nowej krawędzi oraz sprawdzenia czy dane połączenie już istnieje.
W klasie Wierzchołek informacja o połączonych wierzchołkach są przechowywane w zmiennej prywatnej połączenia. W celu sprawdzenia czy istnieje połączenia tego wierzchałka z jakimś należy wywołać sprawdzenie funkcją sprawdźPołączenie(), a jako argument podać wierzchołek docelowy. Wynikiem działania funkcji będzie wartość logiczna. Z kolei funkcja dodajKrawędź() pozwala dodać połączenie do innego wierzchołka. Funkcja zwraca informację logiczną czy została dodana. Połączenie może nie zostać dodane ze względu na oszczędzanie pamięci jeśli dane połączenie już istnieje.
Z kolei graf będzie przechowywał listę wszystkich wierzchołków. Ilość wierzchołków jest do ustalenia podczas inicjalizacji nowego wystąpienia klasy. (Zabezpiecza to klasę przed wystąpieniem błędu dodania nowego połączenia, ponieważ dany wierzchołek mógł nie zostać jeszcze dodany.)
W klasie Graf informacja o połączonych wierzchołkach są przechowywane w zmiennej prywatnej wierzchołki. W celu dodania połączeń można skorzystać z funkcji dodajPołączenia(). Jako pierwszy przyjmowane jest id wierzchołka, a jako drugi listę wierzchołków do których ma zostać utworzone połączenie. Po dodaniu krawędzi można sprawdzić je funkcją sprawdźKrawędź(), która sprawdzi czy połączenie (start, koniec) ostnieje. Wynikiem jest wartość logiczna.
Napisaną klasę Graf można przetestować przy pomocy poniższego kodu, który wprowadza graf podany wcześniej w przykładzie. Po utworzeniu grafu zostają wypisane wszystkie krawędzi pomiędzy różnymi wierzchołkami, które nie istnieją.
Uruchomienie programu dla przykładowo wprowadzonego grafu zwraca następujący wynik:
Wynik ten zgadza się z wprowadzonym grafem.