Lista - struktura danych służąca do reprezentacji zbiorów dynamicznych, w której elementy ułożone są w liniowym porządku. Rozróżniane są dwa podstawowe rodzaje list: lista jednokierunkowa w której z każdego elementu możliwe jest przejście do jego następnika oraz lista dwukierunkowa w której z każdego elementu możliwe jest przejście do jego poprzednika i następnika[1].
Spis treści |
Istnieją dwie popularne implementacje struktury listy: tablicowa i wskaźnikowa.
W przypadku tej implementacji każdy element listy składa się z co najmniej dwóch pól: klucza oraz pola wskazującego na następny element listy. W przypadku list dwukierunkowych każdy element listy zawiera także pole wskazujące na poprzedni element listy. Pole wskazujące poprzedni i następny element listy są najczęściej wskaźnikami[1].
Dopisanie elementu (dla prostej listy jednostronnej):
Usunięcie elementu jest odwrotne do wstawiania: w pewnym miejscu zapisuje się wskaźnik do usuwanego elementu (aby nie "zgubić" jego adresu), następnie wskaźnik wiążący poprzednika przestawia się na następnik. Dopiero w tym momencie zwalnia się pamięć po obiekcie usuwanym (do tego potrzebny jest ten wskaźnik tymczasowy).
Zalety i wady tej implementacji są komplementarne w stosunku do implementacji tablicowej.
Wgłębiając się w szczegóły implementacji listy za pomocą wskaźników można wyróżnić następujące rodzaje list:
Powyższe cechy można prawie dowolnie łączyć, co daje możliwość stworzenia wielu różnych implementacji listy, zależnie od potrzeb.
Jednokierunkowe listy oparte na wskaźnikach są bardzo popularną podstawową strukturą danych w funkcyjnych językach programowania.
Istnieje możliwość realizacji takiej listy, wtedy gdy:
Wówczas pojedynczy wskaźnik zawiera różnicę symetryczną (xor) wartości liczbowej wskaźników na poprzedni i następny element listy. Podczas przechodzenia listy pamiętany jest rzeczywisty wskaźnik uprzednio odwiedzonego elementu i dzięki własności
można z zakodowanej liczby odtworzyć albo poprzedni albo następny element, w zależności od kierunku przeglądania listy. Warunek 2. gwarantuje, że wskaźniki na pierwszej i ostatniej pozycji można odkodować natychmiast.
Zaletą takiej reprezentacji jest oszczędność pamięci (jeden wskaźnik, zamiast dwóch), wadą natomiast utrudnione przeglądanie - jeśli nie rozpoczyna się od pierwszego lub ostatniego elementu, potrzeba znać co najmniej dwa wskaźniki w celu odkodowania rzeczywistych wartości.
Jak wskazuje nazwa, lista zaimplementowana w ten sposób opiera się na tablicy obiektów (lub rekordów) danego typu.
Dopisanie elementu do listy to wstawienie elementu do tablicy:
Usunięcie elementu znajdującego się pod danym indeksem tablicy to przesunięcie o jedno pole w lewo wszystkich elementów o indeksie wyższym.
Zalety tej implementacji: prosta nawigacja wewnątrz listy, korzystanie z gotowej struktury tablicy, szybki dostęp do elementu o konkretnym numerze, większa odporność na błędy.
Wady: niska elastyczność, szczególnie dotycząca rozmiaru tablicy, liniowa złożoność operacji wstawiania i usuwania.
Implementację tablicową stosuje się tam, gdzie elastyczność nie odgrywa istotnej roli, a wymagana jest szybka i prosta nawigacja.