Rc3eHnGputwzz
Fotografia przedstawia falującą wodę.

PY_I_R_W13B_M05 Dynamiczne struktury danych. Implementacja

Źródło: Michael Benz, dostępny w internecie: unsplash.com, domena publiczna.

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.

Ważne!

W programie korzystamy z biblioteki sys.

Biorąc powyższe warunki pod uwagę, do implementacji stosu wystarczy nam 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 konstruktor inicjalizujący dwa pola klasy:

Linia 1. class Wezel dwukropek. Linia 2. def podkreślnik podkreślnik init podkreślnik podkreślnik otwórz nawias okrągły self przecinek liczba zamknij nawias okrągły dwukropek. Linia 3. self kropka liczba znak równości liczba. Linia 4. self kropka nastepny znak równości None.

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

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

Stos zaimplementujemy również jako klasę, której atrybutem inicjalizowanym w konstruktorze referencją pustą będzie referencja na wierzchołek stosu o nazwie wierzcholek.

Linia 1. class Stos dwukropek. Linia 2. def podkreślnik podkreślnik init podkreślnik podkreślnik otwórz nawias okrągły self zamknij nawias okrągły dwukropek. Linia 3. self kropka wierzcholek znak równości None. Linia 5. kratka Poniżej dodamy kolejne metody.

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. def czy podkreślnik pusty otwórz nawias okrągły self zamknij nawias okrągły dwukropek. Linia 2. if self kropka wierzcholek is None dwukropek. Linia 3. print otwórz nawias okrągły cudzysłów Stos pusty wykrzyknik cudzysłów zamknij nawias okrągły. Linia 4. return True. Linia 5. return False.

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

Zacznijmy od metody odloz():

Linia 1. def odloz otwórz nawias okrągły self przecinek liczba zamknij nawias okrągły dwukropek. Linia 2. print otwórz nawias okrągły cudzysłów Odkladam cudzysłów przecinek liczba zamknij nawias okrągły. Linia 3. nowy znak równości Wezel otwórz nawias okrągły liczba zamknij nawias okrągły. Linia 4. nowy kropka nastepny znak równości self kropka wierzcholek. Linia 5. self kropka wierzcholek znak równości nowy.

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. def zdejmij otwórz nawias okrągły self zamknij nawias okrągły dwukropek. Linia 2. if self kropka czy podkreślnik pusty otwórz nawias okrągły zamknij nawias okrągły dwukropek. Linia 3. return minus sys kropka maxsize minus 1. Linia 5. pomocniczy znak równości self kropka wierzcholek. Linia 6. liczba znak równości pomocniczy kropka liczba. Linia 7. self kropka wierzcholek znak równości self kropka wierzcholek kropka nastepny. Linia 9. print otwórz nawias okrągły cudzysłów Zdejmuje cudzysłów przecinek liczba zamknij nawias okrągły. Linia 10. return liczba.

Jeżeli stos jest pusty, tzn. zachodzi błąd niedopełnienia stosu, zwracamy minimalną wartość dla typu całkowitego, którą w języku wylicza się jako ujemną wartość maksymalną (-sys.maxsize) pomniejszoną o 1.

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 pobierz_wierzcholek() ma tylko jedno zadanie: jeżeli stos nie jest pusty, zwraca wartość zapisaną w pierwszym, czyli ostatnim dodanym, elemencie listy:

Linia 1. def pobierz podkreślnik wierzcholek otwórz nawias okrągły self zamknij nawias okrągły dwukropek. Linia 2. if self kropka czy podkreślnik pusty otwórz nawias okrągły zamknij nawias okrągły dwukropek. Linia 3. return minus sys kropka maxsize minus 1. Linia 4. return self kropka wierzcholek kropka liczba.

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

Linia 1. def wypisz otwórz nawias okrągły self zamknij nawias okrągły dwukropek. Linia 2. if self kropka czy podkreślnik pusty otwórz nawias okrągły zamknij nawias okrągły dwukropek. Linia 3. return. Linia 5. print otwórz nawias okrągły cudzysłów Stos zawiera dwukropek cudzysłów przecinek end znak równości cudzysłów cudzysłów zamknij nawias okrągły. Linia 6. pomocniczy znak równości self kropka wierzcholek. Linia 7. while pomocniczy dwukropek. Linia 8. print otwórz nawias okrągły pomocniczy kropka liczba przecinek cudzysłów cudzysłów przecinek end znak równości cudzysłów cudzysłów zamknij nawias okrągły. Linia 9. pomocniczy znak równości pomocniczy kropka nastepny średnik. Linia 10. print otwórz nawias okrągły zamknij nawias okrągły.

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. stos znak równości Stos otwórz nawias okrągły zamknij nawias okrągły. Linia 2. stos kropka odloz otwórz nawias okrągły 1 zamknij nawias okrągły. Linia 3. stos kropka odloz otwórz nawias okrągły 2 zamknij nawias okrągły. Linia 4. stos kropka odloz otwórz nawias okrągły 3 zamknij nawias okrągły. Linia 5. stos kropka wypisz otwórz nawias okrągły zamknij nawias okrągły. Linia 6. stos kropka zdejmij otwórz nawias okrągły zamknij nawias okrągły. Linia 7. stos kropka zdejmij otwórz nawias okrągły zamknij nawias okrągły. Linia 8. stos kropka zdejmij otwórz nawias okrągły zamknij nawias okrągły. Linia 9. stos kropka zdejmij otwórz nawias okrągły zamknij nawias okrągły.
Ćwiczenie 1

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

RM4BEI8u73tF1