Dynamiczne struktury danych

Slides:



Advertisements
Podobne prezentacje
ALGORYTMY I STRUKTURY DANYCH
Advertisements

Tablice 1. Deklaracja tablicy
PRAM.
STRUKTURY DANYCH.
Sortowanie przez scalanie
Standardowa biblioteka języka C++
Zaawansowane techniki algorytmiczne
ALGORYTMY GRAFOWE.
Dynamiczne struktury danych Listy, Kolejki, Stosy
Grażyna Mirkowska PJWSTK 15 listopad 2000
Wykład 10 Metody Analizy Programów Specyfikacja Struktur Danych
PROGRAMOWANIE STRUKTURALNE
PROGRAMOWANIE STRUKTURALNE
ALGORYTMY I STRUKTURY DANYCH
ALGORYTMY I STRUKTURY DANYCH
Elementarne struktury danych Piotr Prokopowicz
Współprogramy III Ten wykład ma na celu pokazanie kolejnej ciekawej możliwości, którą oferują współprogramy. Wspólprogramy reprezentujące wyrażenia regularne.
MS Access 2000 Normalizacja Paweł Górczyński 2005.
ZŁOŻONOŚĆ OBLICZENIOWA
ALGORYTMY GEOMETRYCZNE.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 7: Procedury i funkcje © Jan Kaczmarek.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 8: Wykorzystanie procedur i funkcji © Jan Kaczmarek.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 6: Tablice, rekordy, zbiory.
Kurs Pascala – spis treści
Model danych oparty na listach
Dynamiczne struktury danych 1
I T P W ZPT 1 Jak smakuje Espresso I T P W ZPT 2.
Algorytmy grafowe Reprezentacja w pamięci
Analiza kosztu zamortyzowanego
1 Języki i techniki programowania prowadzący dr Grzegorz Filipczyk.
Typy wskaźnikowe, dynamiczne struktury danych
Podprogramy.
Typy złożone, case, stałe. Typ zbiorowy type typ_zb = set of typ_podstawowy; Typem podstawowym może być tylko typ porządkowy. Typem podstawowym może być
O relacjach i algorytmach
Algorytmy i struktury danych
Algorytmy i struktury danych
Zbiór do posortowania mieści się w pamięci
Podstawy programowania II
Algorytmy i Struktury Danych Sortowanie
Pliki tekstowe. Operacje na plikach. mgr inż. Agata Pacek.
Operacje na strukturach listowych
TABLICE C++.
Procedury i funkcje.
Definicja pliku tekstowego Operacje wykonywane na plikach tekstowych
Pliki Pojęcie i rodzaje plików Definicja typu plikowego Operacje wykonywane na plikach elementowych.
Listy, stosy i kolejki..
Złożone typy danych Listy Tworzenie elastycznych baz danych
Rodzaje, przechodzenie grafu
Zbiory i rekordy mgr inż. Agata Pacek. Deklaracja typu zbiorowego (określa ilość elementów w zbiorze) type biegi=set of 0..6; Definiowanie zmiennej typu.
Model relacyjny.
Informatyka MZT1 Wykład 6 Iteracje while i repeat Tablice Rekordy
Ogólna struktura programu w TP
Algorytmy i Struktury Danych
Obliczalność czyli co da się policzyć i jak Model obliczeń sieci liczące dr Kamila Barylska.
Algorytmy i Struktury Danych
WYKŁAD 06 Programowanie dynamiczne Grażyna Mirkowska.
Algorytmy i Struktury Danych Struktury Danych
Zbiory dynamiczne.
ALGORYTMY I STRUKTURY DANYCH
Wykład 1 Informatyka II MPZI2 sem.letni. Tablice Tablice deklarujemy array [ lista typów indeksów ] of typ bazowy (składowych) np. var t1,t2:array [1..5,
Temat: Tworzenie bazy danych
Indeksy drzewiaste. ISAM ISAM - INDEXED SEQUENTIAL ACCESS METHOD Problem: –Dany jest plik uporządkowany – w jaki sposób zrealizować efektywnie zapytanie.
Typy wyliczeniowe, kolekcje
Listy.
Programowanie Obiektowe – Wykład 5
Programowanie Obiektowe – Wykład 2
Indeksy.
ALGORYTMY I STRUKTURY DANYCH
ALGORYTMY I STRUKTURY DANYCH
ALGORYTMY I STRUKTURY DANYCH
Zapis prezentacji:

Dynamiczne struktury danych AiSD_W4 Dynamiczne struktury danych dr inż. Kustra Piotr Opracowanie: Anna Adrian oraz Kustra Piotr

… Tablice dynamiczne t2 t1 nElem program DynamicVec; var t1 : array of integer; t2 : array [1..10] of integer; nElem: integer; BEGIN read(nElem); write('Ile elementów? ', nElem); setlength(t1, nElem); for i:=1 to nElem do begin t1[i]:=0; end; end. t2   t1 …     nElem

Macierz dynamiczna sizeY sizeX program DynamicMatrix; var sizeX, sizeY, i, j:integer; m:array of array of integer; begin size:=15; SetLength(m, sizeX, sizeY); for i:=0 to sizeX-1 do for j:=0 to sizeY-1 do m[i,j]:=1; end; readln(); end. sizeY sizeX

Zbiory dynamiczne Zbiory – w matematyce pojęcie fundamentalne, niezmienne; - w informatyce zbiory mogą być zmieniane w wyniku działania algorytmów (powiększać, zmniejszać, albo zmieniać w czasie) – stąd ich nazwa zbiory dynamiczne. Zbiór dynamiczny do którego można dodawać (wstawiać) elementy, usuwać elementy ze zbioru i sprawdzać czy element należy do zbioru nazywane są słownikami. Metoda realizacji zbiorów dynamicznych zależy od operacji, które na konkretnym zbiorze mogą być wykonane.

Elementy zbioru dynamicznego Każdy element zbioru dynamicznego jest reprezentowany przez obiekt, którego pola można odczytać lub modyfikować, jeśli mamy wskaźnik tego obiektu. W pewnych rodzajach zbiorów dynamicznych wyróżnione jest jedno z pól każdego elementu i nazywane kluczem (key) obiektu. Jeśli każdy element zbioru dynamicznego ma własny unikalny (niepowtarzalny) klucz, wtedy zwykle taki zbiór traktujemy jako zbiór kluczy. W niektórych implementacjach zbiorów dynamicznych zakłada się, że zbiór kluczy jest liniowo uporządkowany Obiekt może zawierać też inne dane (dodatkowe dane) zawarte w innych polach, jednak one nie wpływają na realizację zbioru Istnieje możliwość występowania w obiekcie pól zawierających wartości zmieniające się przez operacje na zbiorze (np. wskaźniki do innych obiektów w zbiorze)

Operacje na zbiorach dynamicznych Wyróżnia się dwie grupy operacji na zbiorach dynamicznych, są to: Zapytania– pozwalające uzyskać pewne informacje na temat zbioru: SEARCH, MINIMUM, MAXIMUM, SUCCESSOR(następca), PREDECESSOR(poprzednik) Operacje modyfikujące– umożliwiające wprowadzanie zmian w zbiorze dynamicznym : INSERT i DELETE. Wymienione operacje uznawane są jako typowe. W konkretnych implementacjach zbiorów dynamicznych zwykle znajdują zastosowanie tylko niektóre z nich.

Operacje na zbiorach dynamicznych Zapytania SEARCH(S,k) - dla danego zbioru S i klucza k zwraca wskaźnik x do takiego obiektu w zbiorze S, dla którego key[x]=k albo NIL- gdy w zbiorze S nie znaleziono żadnego obiektu spełniającego podany warunek. MINIMUM(S) – zwraca w wyniku element zbioru S o najmniej -szym kluczu; dotyczy zbiorów liniowo uporządkowanych. MAXIMUM(S) wskazuje element zbioru S o największym kluczu; dotyczy zbiorów liniowo uporządkowanych.

Operacje na zbiorach dynamicznych Zapytania SUCCESSOR (S,x) - dla danego elementu x o kluczu należącym do uporządkowanego zbioru S daje w wyniku następnik elementu x w S, tj najmniejszy element ze zbioru S który jest większy od x. Jeśli x jest największym elementem w zbiorze S wynikiem jest stała NIL PREDECESSOR (S,x) dla danego elementu x o kluczu należącym do uporządkowanego zbioru S daje w wyniku poprzednik elementu x w S, tj największy element ze zbioru S który jest mniejszy od x. Jeśli x jest najmniejszym elementem w zbiorze S wynikiem jest stała NIL

Operacje na zbiorach dynamicznych Operacje modyfikujące INSERT(S,x) – dodaje do zbioru S wskazany element x. Przy tej operacji zakłada się zwykle, że wcześniej zostały zainicjowane wartości wszystkich pól obiektu wskazanego przez x istotne dla realizacji zbioru S DELETE(S,x)- dla danego wskaźnika x do obiektu zawartego w zbiorze S usuwa ten element ze zbioru S. Warto zauważyć, że argumentem tej operacji jest wskaźnik do elementu x a nie wartość jego klucza. Czas wymagany do realizacji operacji na zbiorze wyrażany jest zwykle jako funkcja rozmiaru zbioru.

Elementarne dynamiczne struktury danych Zbiory dynamiczne mogą być realizowane przez różne struktury danych. W dalszym ciągu wykładu przedstawiono podstawy realizacji elementarnych struktur danych, takich jak: Stosy Kolejki Listy Drzewa

Stosy i kolejki Stosy i kolejki są realizacją zbiorów dynamicznych w których element usuwany jest określony jednoznacznie: stos: strategia LIFO (last in first out) –najpóźniej dodany usuwany jest jako pierwszy kolejka: strategia FIFO (first in first out) _ najwcześniej usuwany jest element najstarszy Stosy i kolejki mogą być efektywnie implementowane na wiele sposobów

Stos Stos zawierający nie więcej niż n elementów można zaimplementować w n elementowej tablicy S[1..n] Atrybut top [S] oznacza numer ostatnio wstawionego elementu do stosu. Stos składa się z elementów: S[1..top[S]], gdzie S[1] jest elementem na dnie stosu S[top[S]] jest elementem na wierzchu stosu 1 2 3 4 5 6 7 S 15 9   top [S] = 4

Podstawowe operacje na stosie Sprawdzam czy stos jest pusty: Stack-Empty(S) if top (S) =0 then return TRUE else return FALSE Jeśli top[S] =0 to stos jest pusty. Na próbę zdjęcia elementu ze stosu pustego powinien pojawić się komunikat o wystąpieniu błędu niedomiaru. Błąd przepełnienia występuje wtedy gdy top[S] > n

Podstawowe operacje na stosie Insert – PUSH PUSH (S,x) top [S]  top [S] +1 S[ top [S]]  x --------------------------------------------------------------------------- PUSH (S,17) PUSH (S,3) 1 2 3 4 5 6 7 S 15 9 17   top [S] = 6

Podstawowe operacje na stosie Delete - POP POP (S) If STACK-EMPTY (S) then error „niedomiar” else top [S]  top [S] -1 return S[ top [S] +1] --------------------------------------------------------------------------- 1 2 3 4 5 6 7 S 15 9 17   top [S] = 5

Kolejki Kolejkę zawierającą nie więcej niż n elementów można zaimplementować w n elementowej tablicy Q[1..n] Atrybut head [Q] wskazuje głowę (początek) kolejki Atrybut tail[Q] wyznacza następną wolną pozycję na którą można wstawić do kolejki nowy element. Jeśli head [Q] = tail[Q] to kolejka jest pusta. Początkowo head [Q] = tail[Q] =1 Jeśli kolejka jest pusta i próbujemy usunąć z niej element występuje wtedy błąd niedomiaru Jeśli head [Q] = tail[Q] +1, to kolejka jest pełna i przy próbie wstawienia kolejnego elementu występuje błąd przepełnienia

Kolejki Kolejka zawiera 5 elementów na pozycjach Q [7..11] 2 3 4 5 6 7 8 9 10 11 12 Q   15 head [Q]=7 tail [Q] = 12 Kolejka zawiera 5 elementów na pozycjach Q [7..11] Elementy kolejki zajmują pozycje head [Q], head [Q]+1,……………, tail[Q]-1 Zakładamy, że Tablica Q jest cykliczna, tzn pozycja 1 jest bezpośrednim następnikiem pozycji n .

Podstawowe operacje na kolejkach ENQUEUE (Q,x) Q [tail [Q]]  x if tail [Q]=length [Q] then tail [Q] 1 else tail [Q]  tail [Q] +1 ------------------------------------------------------------------------------------------------ ENQUEUE (Q,17); ENQUEUE (Q,3); ENQUEUE (Q,5) 1 2 3 4 5 6 7 8 9 10 11 12 Q   15 17 tail [Q] = 3 head [Q]=7

Podstawowe operacje na kolejkach DEQUEUE (Q) DEQUEUE (Q,x) x Q [head[Q]] if head [Q]=length [Q] then head[Q] 1 else head[Q]  head [Q] +1 return x ------------------------------------------------------------------------------------------------ DEQUEUE (Q); 1 2 3 4 5 6 7 8 9 10 11 12 Q   15 17 tail [Q] = 3 head [Q]=8

Kolejka dwustronna W stosach wstawianie i usuwanie elementów jest realizowane tylko na jednym końcu, na górze stosu. W kolejce dodajemy elementy na jednym końcu a usuwamy z drugiego końca. Kolejka dwustronna (dwukierunkowa) jest strukturą danych pozwalającą na wstawianie i usuwanie elementów na obu końcach kolejki. Napisać procedury służące do wstawiania elementów na obu końcach i do usuwania z obu końców kolejki zaimplementowanej w tablicy

Listy Lista z dowiązaniami jest prostą i elastyczną strukturą danych, służącą do reprezentowania zbiorów dynamicznych, umożliwiającą wykonanie wszystkich typowych operacji na zbiorach. Elementy listy ułożone są w porządku liniowym. Porządek określają wskaźniki związane z każdym elementem listy, a nie jak w tablicach, gdzie porządek jest wyznaczony przez indeksy.

Atrybuty listy Każdy element listy dwukierunkowej (doubly linked list) jest rekordem składającym się z trzech pól : key[x] –zawierającego klucz elementu x, prev[x]- wskazującego na poprzednika elementu x, Jeśli prev[x]=NIL to element x nie ma poprzednika, x jest pierwszym elementem listy, mówimy, że x jest wtedy głową (head) listy. Jeśli head[L] = NIL to lista jest pusta next[x] – wskazującego na następnika x na liście Jeśli next [x]=NIL to element x nie ma następnika , czyli x jest ostatnim elementem listy, nazywanym ogonem listy

Rodzaje list Lista jest jednokierunkowa (singly linked list) gdy pomijany jest wskaźnik prev Lista jest posortowana gdy kolejność elementów na liście jest zgodna z porządkiem na ich kluczach; - element o najmniejszym kluczu znajduje się w głowie, - element o największym kluczu w ogonie listy. W liście nieposortowanej kolejność elementów jest dowolna. W liście cyklicznej, elementy tworzą pierścień. Pole prev elementu w głowie wskazuje na ogon, a pole next w ogonie na głowę listy cyklicznej.

Operacje na listach - wyszukiwanie Założenie: listy są dwukierunkowe, nieposortowane. Procedura LIST-SEARCH (L,k) wyznacza pierwszy element o kluczu k na liście L za pomocą prostego sortowania. Czas jej działania wynosi (n) LIST-SEARCH (L,k) x head[L] while x NIL i key[x]  k do x next[x] return x Po wywołaniu procedury LIST-SEARCH (L,4) na liście otrzymamy wskaźnik do jej trzeciego elementu, a po wywołaniu LIST-SEARCH (L,7) otrzymamy NIL

Operacje na listach – wstawianie nowych elementów Procedura LIST-INSERT(L,x) przyłącza element x, którego pole key zostało wcześniej zainicjowane, na początek listy. Czas działania procedury na liście o n elementach wynosi O(1) LIST-INSERT(L,x) next[x] head[L] if head[L]  NIL then prev[head[L] ] x head[L] x prev[x]  NIL ------------------------------------------------------------------------------------------------------------------ Po wykonaniu procedury LIST-INSERT(L,x), gdzie key[x]=25 w głowie listy znajdzie się nowy rekord z kluczem 25 pole next zawiera wskaźnik do poprzedniej głowy z kluczem 9

Operacje na listach –usuwanie elementów z list z dowiązaniami Wywołanie procedury LIST-DELETE (L,x) powoduje usunięcie elementu x z listy L. Wycinanie elementu z listy polega na modyfikacji odpowiednich wskaźników. Czas działania procedury na liście o n elementach wynosi O(1) ale pesymistyczny czas usuwania elementu o zadanym kluczu wynosi (n) ponieważ Najpierw musi zostać wywołana procedura LIST-SEARCH, aby wyznaczyć wskaźnik elementu x

Operacje na listach –usuwanie elementów z list z dowiązaniami LIST-DELETE (L,x) if prev[x]  NIL then next[ prev[x]] next[x] else head[L] next[x] if next[x]  NIL then prev [next [x]] prev[x] ------------------------------------------------------------------------------ Wynik wykonania operacji LIST-DELETE (L,x), gdzie x wskazuje na element o kluczu 4 z poprzedniej listy

Tablicowe reprezentacje struktur wskaźnikowych Reprezentacja wielotablicowa Dana jest lista: Przedstawmy reprezentację tej listy za pomocą trzech tablic: Tablica key zawiera wartości kluczy znajdujących się na liście Tablice next i prev zawierają wskaźniki Wartości key[x], prev[x] i next[x] określają jeden element listy o indeksie x. Indeksy odgrywają rolę wskaźnika w tablicach key, next i prev

Tablicowa reprezentacja listy (danej) W zmiennej L pamiętany jest numer pozycji (7) na której znajduje się głowa listy. Na liście klucz 4 znajduje się bezpośrednio za elementem o kluczu 16

Lista jednostronnie wiązana – implementacja wskaźnikowa Definicja elementu listy info *next val: integer next: stos H NIL type stos = ^node; node=record val: integer; next: stos; end; 10 -6 12 H NIL

Dodawanie do stosu H pom x procedure PUSH (x:integer); NIL var pom:^node; begin new(pom); pom^.val:=x; pom^.next:=head; head:=pom; end; H NIL x pom

Dodawanie do stosu H pom x1 x2 procedure PUSH (x:integer); var pom:^node; begin new(pom); pom^.val:=x; pom^.next:=head; head:=pom; end; x1 H NIL x2 pom

Usuwanie ze stosu H pom 10 -6 12 procedure POP; var pom:^node; begin if head <>NIL then pom:=head; head:= pom^.next; dispose(pom); end; 10 -6 12 H NIL pom

Przeglądanie listy jednostronnie wiązanej procedure ShowList; var pom:^node; begin pom:=head; write('HEAD --> '); while (pom<>NIL) do write(pom^.val, '--> '); pom:=pom^.next; end; writeln ('NIL'); 10 -6 12 H NIL pom HEAD--> 10-->

Przeglądanie listy jednostronnie wiązanej procedure ShowList; var pom:^node; begin pom:=head; write('HEAD --> '); while (pom<>NIL) do write(pom^.val, '--> '); pom:=pom^.next; end; writeln ('NIL'); 10 -6 12 H NIL pom HEAD--> 10--> -6-> 12-->

Przeglądanie listy jednostronnie wiązanej procedure ShowList; var pom:^node; begin pom:=head; write('HEAD --> '); while (pom<>NIL) do write(pom^.val, '--> '); pom:=pom^.next; end; writeln ('NIL'); 10 -6 12 H NIL pom HEAD--> 10--> -6-> 12--> NIL