Temat: Listy jednokierunkowe i dwukierunkowe 1 Wstęp teoretyczny
Transkrypt
Temat: Listy jednokierunkowe i dwukierunkowe 1 Wstęp teoretyczny
Instrukcja Podstawy programowania 2 laboratoryjna Temat: Listy jednokierunkowe i dwukierunkowe 4 Przygotował: mgr inż. Tomasz Michno 1 Wstęp teoretyczny Listy są dynamicznymi strukturami służącymi do przechowywania danych (są kontenerami). W odróżnieniu od tablic mogą przechowywać dowolną liczbę elementów (ograniczoną jedynie przez dostępną pamięć) oraz umożliwiają wstawienie elementu w dowolnym miejscu. Posiadają jednak wadę w postaci wolniejszego dostępu do dowolnego elementu – aby się do niego dostać należy przejść przez wszystkie elementy znajdujące się przed nim. Istnieje kilka rodzajów list, jednak na zajęciach skupimy się jedynie na listach jednokierunkowych i dwukierunkowych. 1.1 Listy jednokierunkowe Listy jednokierunkowe posiadają bardzo prostą budowę: pojedynczy element składa się z przechowywanych danych i wskaźnika na następny element. dane wskaźnik (następny element) dane wskaźnik (następny element) ... dane wskaźnik (następny element) nil Na przykładzie 1 została przedstawiona struktura elementu listy przechowująca znaki (pełny kod znajduje się na Achillesie). Przykład 1. type WSKLista = ^TLista; TLista = record znak : char; nastepny : WSKLista; {wskaznik na element nastepny} end; Podstawowe operacje na listach: • wstawianie: na koniec, w dowolnym miejscu • wyszukiwanie • usuwanie Wstawianie Na koniec listy: 1. Sprawdź, czy lista jest pusta, jeśli tak utwórz nowy element i dodaj go na początku listy. Przejdź do 4. 2. Jeśli lista nie jest pusta, przejdź korzystając ze wskaźników na koniec listy. 3. Utwórz nowy element. Ustaw wskaźnik następny ostatniego elementu listy tak, aby wskazywał na nowy element. 4. Koniec. W dowolnym miejscu: Algorytm jest praktycznie identyczny z powyższym, z następującymi różnicami: • pętla po wszystkich elementach wyszukuje element przed którym/za którym ma być wstawiony nowy element • dla wstawiania przed wybranym elementem: w pętli należy zastosować dodatkowy wskaźnik na poprzedni element, ułatwiający wstawienie. Dzięki temu łatwo jest zaktualizować wskaźniki tak, aby zachować ciągłość listy. Wyszukiwanie Wyszukiwanie elementu najlepiej jest zrealizować za pomocą funkcji zwracającej wskaźnik na znaleziony element. Dzięki temu uzyskujemy do niego bezpośredni dostęp, który bardzo często jest potrzebny w praktycznych zastosowaniach. Algorytm wyszukiwania sprowadza się do przejścia po wszystkich elementach listy, sprawdzając kolejno, czy aktualny element jest szukanym. Jeżeli tak, następuje koniec wyszukiwania i zwrócenie jego wskaźnika. Usuwanie Podczas usuwania elementu z listy należy zachować dużą ostrożność, ponieważ bardzo łatwo jest zaburzyć ciągłość listy poprzez utracenie jednego wskaźnika. Schemat działania jest następujący: 1. Wyszukaj element który należy usunąć (usuwany), zachowując wskaźnik na jego poprzednika (poprzedni), np. w pętli zastosuj dodatkowy wskaźnik, który będzie pamiętał poprzedni element. 2. Podmień wskaźniki: poprzedni^.nastepny:=usuwany^.nastepny; 3. Usuń element. 1.2 Listy dwukierunkowe Listy dwukierunkowe, w porównaniu do list jednokierunkowych pozwalają na przechodzenie przez elementy w dowolnym kierunku. Dzięki temu np. w algorytmach wstawiania, czy usuwania nie trzeba stosować dodatkowych wskaźników na elementy poprzednie, ponieważ znajdują się one już w strukturze pojedynczego elementu. Możemy też listę wyświetlać w obu kierunkach. Minusem list dwukierunkowych jest konieczność aktualizacji dwóch wskaźników, przy operacjach wstawiania i wyszukiwania, ponieważ bez tego ciągłość listy zostanie zaburzona. dane wskaźnik wskaźnik (poprzedni (następny element) element) dane wskaźnik wskaźnik (poprzedni (następny element) element) ... dane wskaźnik wskaźnik (poprzedni (następny element) element) ... nil Na przykładzie 2 została przedstawiona struktura elementu listy dwukierunkowej przechowującej znaki. Przykład 2. type WSKLista = ^TLista; TLista = record znak : char; poprzedni : WSKLista; {wskaznik na element poprzedni} nastepny : WSKLista; {wskaznik na element nastepny} end; 2 Zadania 1. Napisz program, który za pomocą listy jednokierunkowej będzie przechowywał imiona, nil nazwiska i rok urodzenia osób. Zaimplementuj następujące operacje: wstawianie, usuwanie i wyświetlanie całej listy. Przy wstawianiu zachowuj kolejność alfabetyczną (po nazwiskach, a następnie imionach). 2. Do zadania 1 dodaj operację wyszukiwania i wyświetlania pojedynczego elementu. Wyszukaj jeden z elementów, a następnie go wyświetl. Po wyświetleniu usuń go i wyświetl całą listę. 3. Przerób zadania 1 i 2 tak, aby korzystały z listy dwukierunkowej. Następnie dodaj do programu wyświetlanie elementów na liście od końca.