Implementacja listy jednokierunkowej w Javie

Implementacja listy jednokierunkowej w Javie

Nasza lista jest zbudowana z dwóch klas.

  • Wezel – klasa wewnętrzna – reprezentuje pojedynczy węzeł na liście.
  • Lista – klasa zewnętrzna – zawiera algorytmy dodawania, usuwania oraz wyświetlania elementów oraz przechowuje pierwszy element listy.

Aby pokazać różnice pomiędzy listami dwukierunkowymi a jednokierunkowymi postanowiliśmy opracować własną implementację. Ponownie naszym celem jest pokazanie działania tej struktury danych, a nie możliwości interfejsów, takich jak Comparable lub Iterable. Aby maksymalnie uprościć kod przechowywanym typem danych będzie int.

Naszym celem było napisanie jak najprostszego algorytmu, aby pokazać jak operować na listach jednokierunkowych. Tak, aby w praktyczny sposób przekazać wiedzę z naszego teoretycznego wstępu odnośnie list jednokierunkowych. Na pierwszy rzut oka implementacja jest bardzo podobna do listy dwukierunkowej, jednakże w przypadku usuwania węzła jesteśmy zmuszeni utworzyć tymczasową zmienną, która będzie go przechowywać. W przeciwnym wypadku stracimy możliwość np. zmiany referencji w poprzednim ogniwie listy, gdyż aktualnie usuwany element „nie zna” położenie swojego poprzednika.

Aby uruchomić poniższy kod należy skopiować kod, a następnie skompilować.

Wewnętrzna klasa Wezel

Powyższy program można podzielić na dwie części. Pierwszą jest obiekt, który przechowuje dane i jest nią klasa Wezel. Ze względu na to, że ta struktura danych jest mało elastyczna umieściliśmy ją wewnątrz klasy Lista, gdyż i tak nie wykorzystamy jej nigdzie indziej. Takie podejście jest wygodnie, ponieważ mamy ułatwiony dostęp do pól obu klas.

Pola

Obiekt klasy Wezel zawiera jedną referencję do kolejnego obiektu oraz zmienną przechowującą dane. Jeśli dany węzeł jest ostatni (ogon), to jego referencją na następny obiekt jest wartość null.

Konstruktor

Inicjuje dane – referencję do następnego obiektu na null, a pole z danymi uzupełnia wartością przekazaną w argumencie.

Zewnętrzna klasa Lista

Obiekt klasy Lista przechowuje referencję do pierwszego elementu listy, czyli głowę (ang. head). Zawiera również niezbędne algorytmy, takie jak:

  • dodawanie elementów do listy,
  • usuwanie elementów z listy,
  • szukanie elementu o konkretnym indeksie,
  • wypisanie wszystkich elementów listy.

W metodzie main znajduje się przykładowy przebieg programu. Wykonanie metody main spowoduje wyświetlenie następujących komunikatów w konsoli.

Zachęcamy do eksperymentów z kodem.

Metody

Podstawową różnicą między implementacją listy dwukierunkowej jest algorytm usuwania elementu. Żaden węzeł nie zna położenia swojego poprzednika zatem przy przechodzeniu listy musimy utworzyć zmienną pomocniczą, którą będzie przechowywała jego referencję.

Czemu jednak nie postąpić jak w  przypadku list dwukierunkowych i do zmiennej pomocniczej nie użyć po prostu argumentu n-1? Przecież byłoby to dużo wygodniejsze i kod zajmowałby mniej linii. Powodem jest wydajność. Zwróćmy uwagę, że metoda getWezel() byłaby wywołana dwa razy – raz z argumentem n, a za drugim razem n-1. Jednakże dwukrotnie przejście przez listę zaczynałoby się od głowy listy. Oznacza to podwojenie liczby wykonywanych operacji. W przypadku małej kolekcji oczywiście nie ma to znaczenia, ale kolekcja może składać się z bardzo wielu elementów.

Wyjątek IndexOutOfBoundException

Jeżeli spróbujemy wpisać do metody szukającej indeks ujemny lub spoza naszej listy zostanie wyrzucony wyjątek.

System zbierania nieużytków (ang. Garbage collector)

W Javie nie ma potrzeby ręcznego czyszczenia pamięci. Jeśli nie mamy już referencji do obiektu, to nie musimy z tym nic robić. System zbierania nieużytków oczyści pamięć ze zbędnych obiektów.