Struktury Danych i Złożoność Obliczeniowa Zajęcia 1 Podstawowe struktury danych Tablica ● ● Najprostsza metoda przechowywania serii danych, zalety: ● ● prostota, wady: ● ● musimy wiedzieć, ile elementów chcemy przechowywać (bądź w trakcie kompilacji, bądź w czasie tworzenia tablicy), konieczność znalezienia ciągłego miejsca w pamięci. Tablica ● ● ● ● ● Przykład tworzenia tablicy w sposób statyczny, przykład tworzenia tablicy w sposób dynamiczny, przykład tworzenia dynamicznej tablicy dwuwymiarowej, konieczność pamiętania o zwalnianiu zaalokowanej pamięci, jakie mamy wartości domyślne? * Wektor (std::vector<T>) ● ● ● Jeden z elementów biblioteki standardowej (STL), w bibliotece STL (w przestrzeni nazw std) występuje jako szablon (ang. template), w porównaniu do klasycznych tablic: ● prostsze stosowanie, ● umożliwia płynną „regulację” pojemności, ● ● dostęp do elementów w ten sam sposób (przeciążony operator indeksowania), również potrzebuje ciągłej przestrzeni w pamięci. Wektor (std::vector<T>) ● ● Najprostszy przykład, przykład utworzenia i wykorzystania tablicy dwuwymiarowej na wektorach, ● ● ● uwaga: każdy z wierszy może mieć inną długość, brak konieczności zwalniania pamięci (pamięć zwalnia destruktor a to jest wykonywane automatycznie), jakie mamy wartości domyślne? * Lista ● Jak jest skonstruowana lista? Lista ● Początek listy to wskaźnik Lista ● Przykładowa lista Lista Lista cykliczna Lista dwukierunkowa Lista (std::list<T>) ● Konstrukcja listy dwukierunkowej, ● cechy: ● ● brak możliwości użycia operatora indeksowania, ● nie wymaga ciągłości pamięci, na której operuje, ● ● szybsze działanie przy operacjach dodawania i usuwania w dowolnym miejscu niż tablica/wektor, wygodne operowanie przy przeszukiwaniu przy pomocy iteratorów (występują również w wektorze). występuje również w prostszej wersji: std::slist<T>, gdzie mamy do czynienia z listą jednokierunkową. Lista (std::list<T>) ● ● Prosty przykład wykorzystania listy, (1) przykład wyświetlenia elementów parzystych z listy intów z wykorzystaniem iteratorów (2) * Kolejka (std::queue<T>) ● Kontener o nieco węższych zastosowaniach niż poprzednio przedstawione, ● dzięki temu – intuicyjne zastosowania, ● implementacja kolejki typu FIFO, ● W porównaniu do listy nie umożliwia iterowania ani innego dostępu do elementów wewnątrz kolejki; mamy dostęp tylko do elementu pierwszego i ostatniego poprzez metody front() i back(), Kolejka (std::queue<T>) ● Przykłady wykorzystania kolejki: ● ● ● elementy do przetworzenia w ramach jakiegoś algorytmu, kolejka może być wykorzystana jako bufor między dwoma interfejsami (jeden interfejs „nadaje”, drugi „przetwarza”, ale zdarzenia mogą mieć miejsce asynchronicznie), najprostsze algorytmy np. w routerach wykorzystują kolejki – pakiety przychodzą, są kolejkowane i kolejno przesyłane do odpowiednich odbiorców. Deque (std::deque<T>) ● ● ● Deque to Double-Ended Queue (czyli kolejka o dwóch końcach), jest to swoiste „skrzyżowanie” listy i wektora, kosztem nieco mniejszej wydajności zyskujemy na uniwersalności: ● ● ● możliwość iterowania po wszystkich elementach, możliwość wykorzystania operatora indeksu, aby dostać się natychmiastowo do konkretnego elementu, brak konieczności wykorzystania ciągłego fragmentu pamięci. Deque (std::deque<T>) ● Przykład wykorzystania deque'a, * ● dodajemy elementy z przodu, z tyłu, ● używamy operatora indeksowania, ● usuwamy elementy z dowolnej strony. Stos (std::stack<T>) ● ● ● Stos to struktura typu LIFO, bardzo prosta struktura, która umożliwia de facto trzy operacje: ● dodanie elementu na szczyt stosu, ● usunięcie elementu ze szczytu stosu, ● sprawdzenie, co znajduje się na szczycie stosu, jest to adapter („wrapper”) na kontener typu deque, ale można wykorzystać również inny kontener (np. vector lub list), Stos (std::stack<T>) Uwaga: nie należy mylić std::stack<T> ze stosem ani stertą jako element programu bądź systemu operacyjnego. Kopiec binarny ● ● Struktura drzewiasta (choć nie implementowana jako drzewo) w której każdy węzeł ma dwoje dzieci (za wyjątkiem najniższego poziomu drzewa) i mają one wartości większe niż rodzic, na najniższym poziomie drzewa elementy układane są od lewej do prawej strony. Kopiec binarny ● Przykład kopca binarnego: Kopiec binarny ● Cechy: ● ● ● ● zawsze element o najmniejszej wartości będzie na górze kopca, po dodaniu lub usunięciu elementu, drzewu trzeba przywrócić własność kopca (można użyć funkcji STL: std::make_heap), można sobie wyobrazić kopiec w wersji min i max, najwygodniej zaimplementować kopiec w postaci tablicy: Informacje Szczegóły związane z każdą z zaprezentowanych reprezentacji danych można znaleźć tutaj: http://www.sgi.com/tech/stl/ Pytania? Zadania?