R1KSK8bTfIKoK
Fotografia przedstawia kartki samoprzylepne, doklejane do ściany.

I_R_W13A_M03_JAVA Zaawansowane  struktury danych

Źródło: Kelly Sikkema, domena publiczna.

Najprostszymi dynamicznymi strukturami, które poznaliśmy, są stos i kolejka. Obydwie implementować można za pomocą różnych mechanizmów. Jedno z najprostszych rozwiązań, które służy zazwyczaj do wyjaśnienia działania tych struktur, to użycie statycznej lub dynamicznej tablicy. Jednak nie jest to rozwiązanie w pełni dynamiczne, ponieważ użycie tablic wymaga podania maksymalnej liczby przechowywanych w strukturze elementów. Aby uzyskać w pełni dynamiczne struktury stosu i kolejki, wykorzystuje się listy.

Stos

Przypomnijmy, że stos to liniowa struktura typu LIFO (ang. Last‑In, First‑Out – ostatni na wejściu, pierwszy na wyjściu), która obsługuje dwie podstawowe operacje, tj. odkładanie i zdejmowanie danych. Dodatkowe działania, które wykonuje się na stosie, to odczytywanie wierzchołka stosu, czyli ostatniego odłożonego elementu, bez usuwania go, oraz ewentualnie sprawdzanie rozmiaru stosu, czyli liczby odłożonych elementów.

Biorąc podane warunki pod uwagę, do implementacji stosu wystarczy jednokierunkowa lista niecykliczna. Elementami tej listy będą węzły zawierające dane, np. liczby, oraz – w przypadku listy jednokierunkowej – referencja na element następny. Do zdefiniowania węzła użyjemy klasy zawierającej dwa pola oraz konstruktor:

Linia 1. class Wezel otwórz nawias klamrowy. Linia 2. int liczba średnik. Linia 3. Wezel nastepny średnik. Linia 4. Wezel otwórz nawias okrągły int liczba zamknij nawias okrągły otwórz nawias klamrowy. Linia 5. this kropka liczba znak równości liczba średnik. Linia 6. this kropka nastepny znak równości null średnik. Linia 7. zamknij nawias klamrowy. Linia 8. zamknij nawias klamrowy.

Stworzenie nowego węzła i przypisanie wartości do jego składowych umożliwia instrukcja:

Linia 1. Wezel nowy znak równości new Wezel otwórz nawias okrągły liczba zamknij nawias okrągły średnik.

Stos zaimplementujemy również jako klasę, której atrybutem będzie referencja na wierzchołek stosu o nazwie wierzcholek. Klasa będzie zawierała również definicję konstruktora.

Linia 1. class Stos otwórz nawias klamrowy. Linia 2. Wezel wierzcholek średnik. Linia 3. otwórz nawias ostrokątny code style znak równości cudzysłów white minus space dwukropek pre średnik cudzysłów data minus inline zamknij nawias ostrokątny public Stos otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 4. wierzcholek znak równości null średnik. Linia 5. zamknij nawias klamrowy. Linia 7. prawy ukośnik prawy ukośnik Miejsce na dodanie metod otwórz nawias ostrokątny prawy ukośnik code zamknij nawias ostrokątny. Linia 9. zamknij nawias klamrowy.

W konstruktorze Stos() inicjalizujemy pole wierzcholek referencją pustą.

Do klasy Stos() dodamy teraz metody wykonujące charakterystyczne dla stosu operacje.

Zaczniemy od metody czyPusty(), która będzie zwracała wartość true (prawda), jeżeli stos będzie pusty, czyli w sytuacji, kiedy pole wierzcholek będzie referencją pustą. W przeciwnym razie metoda zwróci wartość false (fałsz).

Linia 1. public boolean czyPusty otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 2. if otwórz nawias okrągły wierzcholek znak równości znak równości null zamknij nawias okrągły otwórz nawias klamrowy. Linia 3. System kropka out kropka println otwórz nawias okrągły cudzysłów Stos pusty wykrzyknik cudzysłów zamknij nawias okrągły średnik. Linia 4. zamknij nawias klamrowy. Linia 5. return otwórz nawias okrągły wierzcholek znak równości znak równości null zamknij nawias okrągły średnik. Linia 6. zamknij nawias klamrowy.

W celu zachowania poprawności działania struktury LIFO, funkcja odloz() będzie dodawała elementy na początku listy i odpowiednio funkcja zdjemij() będzie usuwała elementy również z początku listy.

Zacznijmy od metody odloz():

Linia 1. public void odloz otwórz nawias okrągły int liczba zamknij nawias okrągły otwórz nawias klamrowy. Linia 2. System kropka out kropka println otwórz nawias okrągły cudzysłów Odkładam cudzysłów plus String kropka valueOf otwórz nawias okrągły liczba zamknij nawias okrągły zamknij nawias okrągły średnik. Linia 3. otwórz nawias ostrokątny code style znak równości cudzysłów white minus space dwukropek pre średnik cudzysłów data minus inline zamknij nawias ostrokątny Wezel nowy znak równości new Wezel otwórz nawias okrągły liczba zamknij nawias okrągły średnik. Linia 4. nowy kropka nastepny znak równości wierzcholek średnik. Linia 5. wierzcholek znak równości nowy średnik otwórz nawias ostrokątny prawy ukośnik code zamknij nawias ostrokątny. Linia 7. zamknij nawias klamrowy.

W funkcji odloz() tworzymy nowy węzeł i zapisujemy w nim wartość zmiennej liczba przekazaną jako argument. Następnie pole nastepny nowego elementu ustawiamy na dotychczasowy wierzcholek, w ten sposób dodajemy element na początku listy. Na koniec aktualizujemy pole wierzcholek, tak aby wskazywało na nowo dodany element.

W metodzie pomijamy sprawdzenie ewentualnego błędu przepełnienia stosu, który ze względu na użycie listy jest mało prawdopodobny.

Usuwanie pierwszego elementu jest możliwe dzięki referencji wierzcholek:

Linia 1. public int zdejmij otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 2. if otwórz nawias okrągły czyPusty otwórz nawias okrągły zamknij nawias okrągły zamknij nawias okrągły return Integer kropka MIN podkreślnik VALUE średnik. Linia 3. Wezel pomocniczy znak równości wierzcholek średnik. Linia 4. int liczba znak równości pomocniczy kropka liczba średnik. Linia 5. wierzcholek znak równości wierzcholek kropka nastepny średnik. Linia 6. otwórz nawias ostrokątny code style znak równości cudzysłów white minus space dwukropek pre średnik cudzysłów data minus inline zamknij nawias ostrokątny System kropka out kropka println otwórz nawias okrągły cudzysłów Zdejmuję cudzysłów plus Integer kropka toString otwórz nawias okrągły liczba zamknij nawias okrągły zamknij nawias okrągły średnik. Linia 8. return liczba średnik otwórz nawias ostrokątny prawy ukośnik code zamknij nawias ostrokątny. Linia 10. zamknij nawias klamrowy.

Jeżeli stos jest pusty, tzn. zachodzi błąd niedopełnienia stosu, zwracamy minimalną wartość zdefiniowaną dla typu całkowitego w stałej MIN_VALUE.

W przeciwnym razie dotychczasowy pierwszy element oraz zapisaną w nim wartość zapamiętujemy w zmiennych pomocniczych. Następnie ustawiamy wierzchołek na drugi element listy, dotychczasowy pierwszy usuwamy, a zapamiętaną wartość zwracamy.

Metoda pobierzWierzcholek() ma tylko jedno zadanie: jeżeli stos nie jest pusty, zwraca wartość zapisaną w pierwszym, czyli ostatnim dodanym, elemencie listy:

Linia 1. public int pobierzWierzcholek otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 2. if otwórz nawias okrągły czyPusty otwórz nawias okrągły zamknij nawias okrągły zamknij nawias okrągły return Integer kropka MIN podkreślnik VALUE średnik. Linia 3. return wierzcholek kropka liczba średnik. Linia 4. zamknij nawias klamrowy.

Metoda wypisz() posłuży do wypisania wartości odłożonych na stosie, czyli zapisanych w kolejnych węzłach listy:

Linia 1. public void wypisz otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 2. if otwórz nawias okrągły czyPusty otwórz nawias okrągły zamknij nawias okrągły zamknij nawias okrągły return średnik. Linia 3. otwórz nawias ostrokątny code style znak równości cudzysłów white minus space dwukropek pre średnik cudzysłów data minus inline zamknij nawias ostrokątny System kropka out kropka print otwórz nawias okrągły cudzysłów Stos zawiera dwukropek cudzysłów zamknij nawias okrągły średnik. Linia 4. Wezel pomocniczy znak równości wierzcholek średnik. Linia 5. while otwórz nawias okrągły pomocniczy wykrzyknik znak równości null zamknij nawias okrągły otwórz nawias klamrowy. Linia 6. System kropka out kropka print otwórz nawias okrągły pomocniczy kropka liczba plus cudzysłów cudzysłów zamknij nawias okrągły średnik. Linia 7. pomocniczy znak równości pomocniczy kropka nastepny średnik. Linia 8. zamknij nawias klamrowy. Linia 9. System kropka out kropka println otwórz nawias okrągły zamknij nawias okrągły średnik otwórz nawias ostrokątny prawy ukośnik code zamknij nawias ostrokątny. Linia 11. zamknij nawias klamrowy.

Do wypisania wartości używamy pętli przechodzącej po wszystkich elementach stosu zapisywanych w zmiennej pomocniczy, którą ustawiamy na wierzchołek, a następnie wewnątrz pętli przesuwamy na kolejne węzły wskazywane przez pole nastepny. Pętla będzie działać dopóki nie dojdziemy do ostatniego węzła, którego referencja nastepny będzie pusta.

Do sprawdzenia działania stosu możemy użyć poniższego kodu:

Linia 1. public class StosLista otwórz nawias klamrowy. Linia 2. public static void main otwórz nawias okrągły String otwórz nawias kwadratowy zamknij nawias kwadratowy args zamknij nawias okrągły otwórz nawias klamrowy. Linia 3. Stos stos znak równości new Stos otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 4. stos kropka odloz otwórz nawias okrągły 1 zamknij nawias okrągły średnik. Linia 5. stos kropka odloz otwórz nawias okrągły 2 zamknij nawias okrągły średnik. Linia 6. stos kropka odloz otwórz nawias okrągły 3 zamknij nawias okrągły średnik. Linia 7. stos kropka wypisz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 8. stos kropka zdejmij otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 9. stos kropka zdejmij otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 10. stos kropka zdejmij otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 11. stos kropka zdejmij otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 12. zamknij nawias klamrowy. Linia 13. zamknij nawias klamrowy.
Ćwiczenie 1

Na podstawie całego omówionego powyżej kodu przygotuj program ilustrujący działanie stosu. Przeanalizuj podaną wyżej funkcję główną i odpowiedz, jaki będzie ostatni wypisany przez program komunikat. Uruchom program i sprawdź poprawność swojej odpowiedzi.

Wykorzystaj omówiony kod i przygotuj program pozwalający sprawdzić działanie kolejki. Dodaj do kolejki trzy liczby, wypisz kolejkę, a następnie cztery raz wywołaj metodę usuwającą.

RJl1aILncO7Yk
sss