Podstawowe Pojęcia Przy Badaniu Algorytmów I Struktur Danych

advertisement
Podstawowe Pojęcia Przy Badaniu Algorytmów I Struktur Danych
Analiza algorytmiczna: to dział informatyki zajmujący się szukaniem najlepszych
algorytmów dla zadań komputerowych.
- odpowiada na pytania:
* czy dany problem może być rozwiązany na komputerze dostępnym czasie i
pamięci?
* który algorytm zastosować a danych okolicznościach?
* czy jest lepszy algorytm? (czy jest on optymalny?).
* jak uzasadnić, że algorytm rozwiązuje postawione zadanie?
- prowadzona jest w dwóch aspektach poprawności semantycznej i złożoności
obliczeniowej (również w strukturach danych)
- uwzględnia poprawność semantyczną, prostotę, czas działania, zajętą pamięć,
optymalność i okoliczność użycia.
Częściowa poprawność:- (jeśli nie to: dla pewnych danych wejściowych obliczenie
algorytmu dochodzi do punktu końcowego, ale wyniki są różne od spodziewanych
wartości końcowych)
Własność określoności obliczeń:- (jeśli nie to: zatrzymuje się w punkcie nie
końcowym algorytmu)
Własność stopu:- (jeśli nie to: algorytm jest nieskończony (pętla, rekurencja))
Złożoność obliczeniowa:
Definiuje się jako – ilość zasobów komputerowych potrzebnych do jego wykonania
(czas procesora, zajętość pamięci)
Za jednostkę przyjmuje się – wykonanie jednej operacji dominującej.
Wyróżnia się:
- złożoność pesymistyczną (ilość zasobów komputerowych potrzebnych przy
„najgorszych” danych wejściowych o rozmiarze n)
- złożoność oczekiwaną (ilość zasobów komputerowych potrzebnych przy
„typowych” danych wejściowych o rozmiarze n)
- miary wrażliwości algorytmów pesymistyczną i oczekiwaną.
Analiza Probabilistyczna:
- koszt algorytmu jako zmienna losowa, właściwości asymptotyczne (poprawne dla
dużych danych wejściowych)
Typowe złożoności:
- Stała.
- Logarytmiczna,
- Kwadratowo-logarytmiczna,
- Liniowa,
- Liniowo-logarytmiczna,
- Kwadratowa,
- Sześcienna,
- Wielomianowa c.d.
- Wykładnicza – nie realizowalność dla dużych danych.
Struktury Danych
Dana – zapis informacji na nośniku komputerowym
Dana prosta – zapis informacji, którego żadna część nie jest zapisem informacji.
Dana złożona – (statyczna struktura danych) składa się z:
- Podłoża
- Pokrycia tego podłoża
- Wyróżnienia działek podłoża
Podłoże – struktury statycznej to para: zbiór działek (pozycji) podłoża oraz zbiór
relacji (powiązań) między działkami podłoża.
Pokrycie – podłoża to para: zbiór danych składowych oraz funkcja
przyporządkowująca poszczególnym działkom ich pokrycia (nie musi być
różnowartościowa i nie musi być zupełna)
Wyróżnienie – działki to podzbiór zbioru działek.
Dynamiczne Struktury danych - Dynamiczna struktura danych jest obiektem
dynamicznym, którego stan w danej chwili jest strukturą statyczną.
Zmianę stanu struktury dynamicznej realizuje się przez:
- operacje proste (operacje np. przesunięcia na wyróżnieniach, testujące i
modyfikujące strukturę)
- operacje złożone (odszukujące działkę, rozmieszczania i pokrycia, reorganizacji
struktury np. sortowanie)
Wskazanie działki:
- Przez adresacje (para: zbiór adresów + funkcja różnowartościowa przypisująca
adresom działki),
- Przez wyróżnienie (jest podzbiorem działek, najczęściej jednoelementowym)
Klasyfikacja Struktur Danych:
Ze względu na powiązania podłoża:
- Mnogościowe (zbiór relacji (powiązań) jest pusty)
- Liniowe (podłoże jest grafem liniowym)
- Pierścieniowe (rzadko stosowane)
- Drzewiaste
- Sieciowe inaczej grafowe (przypadek ogólny – położenie nie pod poprzednie
szczególne przypadki).
Struktury mnogościowe – zbiory.
Zbiór – struktura dynamiczna o pokryciu zupełnym różnowartościowym.
Operacje proste:
- Sprawdzenie czy jest zbiorem pustym,
- Sprawdzenie zbioru na zawartość elementów,
- Dodanie elementu do zbioru,
- Usunięcie elementu ze zbioru,
- Usunięcie całego zbioru,
- Podanie elementu następnego.
Operacje złożone:
- Sumowanie zbiorów,
- Iloczyn zbiorów
- Różnica zbiorów
- Różnica symetryczna rekordów
Implementacja: bitowa, tablicowa, listowa.
Zastosowania: zbiór znaków, zbiór słów.
Struktury liniowe.
Podłoże liniowe:
- Działki początkowa i końcowa,
- Relacje następstwa i poprzednictwa,
- Relacje osiągalności naprzód i wstecz.
Tablica – jest to struktura dynamiczna o:
- Podłożu stałym,
- Dostępie adresowym,
- Podłożu jednorodnym
Tablica liniowa numerowana (TLN) (struktura o podłożu stałym);
Operacje proste:
- Odczytywanie zawartości działki,
- Zmiana zawartości działki.
REKORDY
Rekordy – rekord jest to struktura mnogościowa o;
- Podłożu stałym (jak tablica),
- O dostępie adresowym, (ale nie numeruje się działek tylko operuje się nazwami),
- O podłożu niekoniecznie jednorodnym (istotna różnica).
Tablica rekordów - tablica o działkach pokrytych przez rekordy.
Pole kluczowe – (jedno z pól w rekordzie);
- Może decydować o położeniu rekordu w tablicy (rozmieszczenie rekordów)
- Może być podstawą odszukania.
Klasyfikacja rozmieszczenia rekordów w tablicy – według;
- gęstości;
* luźne,
* zwarte
- powiązania z zawartością;
* chaotyczne,
* sterowane;
^ monotoniczne (np. niemalejące, nierosnące),
^ algorytmicznie („haszowanie”),
Tablica – operacje złożone;
Dla tablicy chaotycznej (zwartej oraz luźnej);
- Wprowadzenie rekordu,
- Odszukanie rekordu (działek o zadeklarowanym pokryciu) sekwencyjne, krokowe,
losowe,
- Kasowanie rekordu,
- Rozmieszczanie elementów,
- Reorganizacja tablicy (np. monotonizacja).
Dla tablicy monotonicznej dochodzi;
- Odszukanie: binarne (połówkowe), interpolarne,
Dla tablicy z rozmieszczeniem algorytmicznym;
- Odszukanie algorytmiczne,
- Rozmieszczanie algorytmiczne,
- Zmiana algorytmu rozmieszczającego.
Sortowanie
Sortowaniem – nazywamy proces ustawiania obiektów w określonym porządku.
Polega na permutowaniu, aż do chwili osiągnięcia ich uporządkowania takiego, że
dla danej funkcji porządkującej F; F(ak1) ≤ F(ak2) ≤ … ≤ F(akn) (Wartość tej
funkcji nazywa się kluczem).
- metodę sortowania nazywamy stabilną, jeżeli podczas procesu pozostaje
niezmieniony względny porządek obiektów o identycznych kluczach.
- Metody In-situ – wymagania dotyczące pamięci.
Klasyfikacja metod sortowania – według;
Rodzaju struktury;
- Sortowanie tablicy
- Sortowanie listy,
- Sortowanie łańcucha,
Miejsca sortowania;
- Wewnętrzne,
- Zewnętrzne,
Podziału algorytmu na etapy;
- Bezpośrednie – (jeden etap, obiekty ulegają przestawieniu),
- Pośrednie – dwa etapy;
* etap logiczny - informacja jak przestawić obiekty, można wykonać kilka etapów
logicznych.
* etap fizyczny – nie zawsze konieczny.
Wykorzystania pamięci;
- Metody intensywne (In situ),
- Metody ekstensywne (dodatkowa pamięć, metody szybsze),
Efektywności;
- Metody proste O(n2),
- Metody złożone O(n log n),
Stabilności;
- Stabilna,
- Niestabilna.
Sortowania proste:
Sortowanie przez proste wstawianie;
- Dzielimy ciąg na wynikowy i źródłowy w każdym kroku począwszy od i=2,
przenosimy i-ty element ciągu źródłowego do ciągu wynikowego wstawiając go w
odpowiednim miejscu.
- Zachowanie naturalne, algorytm stabilny, działa w miejscu.
- Próba poprawy przez wstawianie połówkowe.
- Liczba porównań nie zależy od ustawiania początkowego elementów, faworyzuje
nieuporządkowane.
- Zmienia się tylko liczba porównań nie przesunięć, czasochłonne, gdy elementy są
uporządkowane, gorsze niż liniowe przeszukiwanie.
Sortowanie przez proste wybieranie;
- Podział też na dwa ciągi, wybieramy element najmniejszy z ciągu źródłowego i
wymieniamy go z pierwszym elementem tego ciągu, aż pozostanie w nim jeden
element.
- Lepszy od prostego wstawiania (mniejsza liczba porównań, gorzej dla elementów
posortowanych, niestabilna, działa w miejscu, zalecane dla n<50)
Sortowanie przez prostą zamianę (bąbelkowe);
- Algorytm polega na porównaniu i ewentualnej zamianie sąsiadujących par ze sobą
dopóki wszystkie elementy zostaną posortowane.
- Ulepszenia tej metody;
* Zapamiętanie, czy dokonano zmian,
* Zapamiętanie pozycji ostatniej zmiany i nie sięganie aż do „i”,
* Zmiana kierunku przejść (mieszane),
* Asymetria ciężkiego i lekkiego końca, korzyści w przypadku prawie
posortowanych ciągów elementów, czyli rzadko, nie stosuje się, złożoność n 2.
Sortowania złożone:
Sortowanie przez podział (szybkie) - Quicksort;
- W celu zapewnienia efektywności wymieniamy elementy położone daleko od
siebie,
- Wersja rekurencyjna i nierekurencyjna,
- Warianty; Horanitza, losowy, z medianą 3, kombinacje z metodą prostą
(Quickersort),
W zależności od wyboru elementu dzielącego; różne działania dla skrajnych
przypadków, mediana najmniejsza liczba porównań, mediana z próbki nie wpływa
na wydajność, losowy wybór efektywność najmniejsza od optymalnej.
Sortowanie grzebieniowe - Combsort;
- Pochodzi z 1991 roku,
- Oparte na metodzie bąbelkowej,
- Włączono tutaj empirię (współczynnik 1.3 wyznaczono doświadczalnie),
- Złożoność O(n log n), statyka gorsza niż Quicksort (1,5-2 razy), ale algorytm
prosty (bez rekurencji),
- Wariant sortowania Combsort;
- Podstawowy – za rozpiętość przyjmij długość tablicy, podziel przez 1.3, odrzuć
część ułamkową, będzie to pierwsza rozpiętość badanych obiektów,
- Combsort 1! – rozpiętość 9 i 10 zastępujemy 11,
Sortowanie przez scalanie – Merqesort
- Jest to metoda ekstensywna o zapotrzebowaniu na dodatkową pamięć równą
pojemność sortowanej tablicy, wyjątkowo dogania Quicksort, statycznie z nim
przegrywa, skomplikowany algorytm, dobra idea dla sortowania zewnętrznego,
- Algorytm scalania – dane dwa pliki (tablice) monotoniczne, należy scalić w jeden
monotoniczny; bierz obiekt z czoła i mniejszy przenieś na plik końcowy,
konkatenuj, aż któryś z plików wejściowych się skończy, resztę dopisz na koniec
wejściowego pliku,
- Wersja podstawowa (iteracyjna); podziel tablice na odcinki 1 elementowe, scalaj
1 z 2, 3 z 4, itd., przepisując do drugiej tablicy, potem dwuelementowe odcinki
scalaj w 4 elementowe, przepisując z powrotem do 1-szej tablicy itd. aż do odcinka
posortowanego o długości tablicy,
- Wersja rekurencyjna – podziel na 2 części i zastosuj metodę Merqesort, wyniki
scal; gorsza od podstawowej,
- Wersja naturalna; zaczyna się od serii naturalnych; kłopot z wyznaczeniem granic
serii, jest atrakcyjna, gdy tablica jest częściowo posortowana.
Sortowanie struktur zewnętrznych:
- Trzeba mieć 3 (najlepiej 4) pliki,
- Plik należy podzielić na 2 pliki (z 1 czytamy 1 podciąg i z 2, 1 podciąg wkładając
do 3 pliku) potem 3 dzieli się znowu na dwa,
- Dokładając 4 plik pozbywamy się przepisywania,
Sortowanie pozycyjne:
- Metoda liczników częstości; Zakładamy, że m=2b (b – długość słowa binarnego).
Dla każdego j = 0, 1, …, m-1 liczymy, ile razy j pojawia się w ciągu wejściowym
a1, …, an. Na podstawie obliczonych liczników częstości umieszczamy każdy
element a i we właściwym miejscu w ciągu wynikowym,
Rozmieszczenie Algorytmiczne
- Wyszukanie; linowe, binarne, tablice zwane indeksami lub skorowidzami, za
mało efektywne (czasowo i pamięciowo).
- Tablica indeksów określająca pewien algorytm = tablica rozproszona, elementów
rozmieszczenie w takiej strukturze = rozmieszczenie algorytmiczne, złożoność
takiego wyszukania O (1).
Tablica rozproszona:
- nazywamy system T= < K,D,h > gdzie: K – zbiór n kluczy, D – zbiór p adresów,
h:K→D funkcja odwzorowująca K w D (laszująca, mieszająca, kodująca,
transformująca klucz w adres.
- p ≥ n ; współczynnik wypełnienia ≥ n/p ( 5-10 %, n=104, 105)k
Rozmieszczenie Algorytmiczne:
- składa się z algorytmów: numeryzacji klucza, rozmieszczenia pierwotnego
(funkcja mieszająca) i rozwiązywania konfliktów.
- problemy: wybór funkcji numerującej i mieszającej, wybór metod rozwiązywania
konfliktów.
- zastosowania; bazy danych, budowa kompilatorów, rozwiązywanie zadań
numerycznych zawierających macierze rzadkie, systemy plików.
Numeryzacji Klucza.
- algorytmy rozmieszczenia pierwotnego i usuwania kolizji są często numeryczne,
klucz natomiast jest często alfabetyczny i na tyle długi, że jego binarnej
reprezentacji nie da się interpretować wzajemni; trzeba go przetworzyć na liczbę.
Metody składania:
- Składanie cykliczne z sumowaniem arytmetycznym;
* potnij konwertowany ciąg bitów na odcinki o długości równej długości żądanego
wyniku, podpisz i sumuj arytmetycznie odrzucając ewentualny nadmiar.
- Składanie cykliczne z różnicą symetryczną;
* jak wyżej, ale zamiast sumy arytmetycznej zastosuj różnicą symetryczną
(XOR), trochę szybsze niż poprzednie.
* Składanie zygzakowe;
* po podpisaniu odcinków jeden po drugim, odwróć kolejność bitów, w co
drugim z nich, sumuj lub stosuj XOR,
Algorytmy rozmieszczania pierwotnego.
- Algorytmy rozmieszczania niezależne od rozkładu kluczy:
* Randomizacja,
* Metody składania,
* Metoda środka kwadratu,
* Metoda mnożenia,
* Metoda dzielenia.
- Algorytmy rozmieszczania zależne od rozkładu kluczy:
* Zbieramy dane statyczne o znakach występujących w reprezentacji kluczy ze
zbioru, K.
Randomizacja: d (i) = rand ( k (i))
Metoda składania:
- Warunek:, jeżeli przez składanie klucz został skrócony do k bitów, to długość
tablicy = 2K działek, a numeryzacja działek Od 0 do 2K-1,
- Własności rozpraszające: dobre,
- Wady: narzucona wielkość tablicy,
Metoda środka kwadratu:
- Algorytm: weź klucz znumeryzowany, podnieś go do kwadratu, wybierz ze
środka
tyle bitów ile ci potrzeba, zinterpretuj to jako
adres,
- Znaczenie metody: raczej historyczne,
- Zalety: względna prostota algorytmu, dobre rozpraszanie,
- Wady: narzucona wielkość tablicy jw., indeksacja od 0 do 2K-1,
Metoda mnożenia:
NWP
  a 


hK    P *    * K  mod 1

  b 

(a,b)=1 a
b

c
5 1
 0,618033...
2
- z ułamka odcina część ułamkową
- Algorytm: weź ponumerowany klucz pomnóż przez rzeczywisty współczynnik
C, odrzuć część całkowitą, część ułamkową pomnóż przez długość tablicy, odrzuć
część ułamkową wyniku. Wynik końcowy będzie liczbą całkowitą z przedziału od
0 do 1-p gdzie p jest długością tablicy.
- Zalety: dowolna długość tablicy, dobre mieszanie przy dobrze dobranym C,
zaleca się, aby C było przybliżeniem liczby niewymiernej np. stosunku złotego
podziału.
- Wady: narzucona numeracja od 1 do p, algorytm stosunkowo skomplikowany,
dwa mnożenia przez liczbę rzeczywistą plus dwie dodatkowe operacje.
Metoda dzielenia (reszty z dzielenia):
- Algorytm: klucz znumeryzowany podziel przez długość tablicy, weź resztę z
dzielenia.
- Warunek: dobre mieszanie, jeżeli długość tablicy jest liczbą pierwszą albo
pseudopierwszą (żaden czynnik pierwszy nie jest mniejszy niż 20).
- Zalety: bardzo prosty algorytm, dobre mieszanie.
- Wady: konieczność dociągania długości tablicy do najbliższej liczby pierwszej
albo pseudopierwszej.
Algorytmy usuwania konfliktów:
Algorytmy rozwiązywania konfliktów bez obszaru nadmiarowego:
- Metody liniowe,
- Metody kwadratowe;
* Wariant prymitywny,
* Metoda Radkego,
* Metoda Daya,
- Metody sześcienne,
- Metody losowe,
- Metody mieszane.
Metody liniowe:
a (i)= (a(O)+b*i) mod p, gdzie;
a (0) – adres początkowy wyznaczony przez algorytm mieszający,
i – numer próby usunięcia kolizji,
b- współczynnik całkowity,
p – długość tablicy.
Wyznacznik b: wszystko jedno, jaki a więc najprościej 1 lub -1. Wzór redukuje
się zatem do;
a (i) = (a(0)+i) mod p albo a (i) = (a(0) - i) mod p
- Zalety: prostota algorytmu brak skoków na długie dystanse, nie narzuca
długości tablicy.
- Wady: skłonność do tworzenia skupień pierwszego rzędu (modyfikacja; b jako
zmienna, double hashing – czyli b jest inną funkcją mieszającą).
- Zalecane: uważać, aby współczynnik zapełnienia nie przekraczał ok. 80%.
Metody kwadratowe:
- Wariant prymitywny a (i) = (a(0)+b*i+c+i2) mod p , gdzie; b, c –
współczynniki rzeczywiste.
Współczynnik b: wszystko jedno, jaki więc najprościej 0,
Współczynnik c: wszystko jedno, jaki byle nie 0, więc najprościej 1 lub -1. Wzór
upraszcza się, więc do postaci: a (i)=(a(0)+i 2) mod p albo a (i)=(a(0)-i2) mod p
Wady dyskwalifikujące: powtórne badanie działek już przebadanych, pomijanie
niektórych działek, skupiska drugiego rzędu.
- Metoda Radkego
Warunek: długość tablicy musi być „liczbą Radkego” tj. liczbą pierwszą
wyrażającą się wzorem 4*i+3 gdzie, i jest dowolną liczbą naturalną.
Algorytm:
a(1)=(a(0)+12) mod p
a(2)=(a(0)-12) mod p
a(3)=(a(0)+22) mod p
a(4)=(a(0)-22) mod p itd.
Uwaga: niech algorytm robi tylko p-1 kroków, bo potem powtórne badania będą
musiały
nastąpić.,
Zalety: niezawodność,
Wady: wymuszenie dotyczące długości tablicy, konieczność obliczania (albo
przechowywania i odszukiwania) kwadratów kolejnych
liczb naturalnych, powstawanie skupień drugiego
rzędu.
- Metoda Daya (metoda Radkego ulepszona)Metoda opiera się na
spostrzeżeniu, że ciąg liczb kwadratowych (tzn. ciąg kwadratów kolejnych liczb
naturalnych) 02 12 22 32 42 itd. Czyli 0, 1, 4, ,9, 16 itd. Daje po zróżnicowaniu ciąg
1, 3, 5, 7, itd. czyli ciąg kolejnych liczb nieparzystych. Powstaje stąd pomysł, aby
kolejne liczby kwadratowe obliczać nie przez podnoszenie do kwadratu ale przez
tworzenie i sumowanie ciągu kolejnych liczb nieparzystych.
Uwaga: metoda Daya jest modyfikacją metody Radkego.
Metody sześcienne:
Metody te są prawdopodobnie lepsze jeżeli chodzi o ilość skupień ale wymagają
większego nakładu obliczeń. d(i)=(d(0)+i3) mod p; d(i)=(d(0)+(i2 mod p)*i) mod p
Skracanie czasu obliczeń może powstać przy obliczeniu sześcianu metodą reszt
sześciennych.
Metoda losowa.
Metody mieszane:
- Algorytmy rozwiązywania konfliktów z obszarem nadmiarowym:
* Z dodatkową tablicą,
* Z listą synonimów (tworzymy dodatkowe pole w rekordzie, aby utworzyć listę.
Operacje na tablicach rozproszonych.
1. Wprowadzenie nowego zapisu – sprowadza się do szukania.
2. Wyszukanie określonego zapisu – sprowadza się do szukania.
3. Usuwanie określonego wpisu – sprowadza się do szukania i reorganizacji.
4. Inne algorytmy przetwarzania tablicy np. reorganizacja, zmiana rozmiaru
tablicy, usuwanie rekordu.
Usuwać nie można, można tylko zaznaczyć, że element usunięto.
Reorganizacja tablic rozproszonych.
1. Przygotowanie reorganizacji.
Każdy rekord wyposażamy w dwa jednakowe pola techniczne:
- bit rekordu żywego b1,
- bit rekordu trwałego b2 (przed uruchomieniem reorganizacji = 0)
2. Przeglądaj sekwencyjne działki tablicy aż do końca.
3. Po napotkaniu rekordu żywego, nietrwałego uruchom algorytm rozmieszczania
pierwotnego (wyznacz mowy adres rekordu), jeśli martwy lub trwały to
pomijamy, postępuj następująco z nowym adresem:
- If działka pusta lub zajęta przez rekord martwy, then umieść nowy rekord i oznacz
bitem trwałości, (czyli go to 2),
- If działka zajęta przez rekord żywy, nietrwały, then wypchnij ten rekord, umieść
nowy rekord i oznacz, b2=1, a rekord wypchnięty traktuj jako nowy (go to 3),
- If działka zajęta przez rekord trwały, then uruchom algorytm usuwania kolizji,
przejdź do działki wskazanej przez ten algorytm i (go to 1).
Ogólny algorytm wprowadzania zapisu rekordu do tablicy rozproszonej (spotykany
w książkach)
0: k = numeryzuj (klucz);
1: i ← 0;
2: di ← h(k);
3: if t[di] = 0 then
begin
t[di] ← zapis (k);
‘koniec algorytmu’
end;
Struktury Danych O Podłożu Zmiennym
- Bardzo ważna grupa struktur liniowych.
- Są to struktury nie posiadające adresacji !. Dostęp do poszczególnych elementów
struktury jest organizowany przez wyróżnienia.
- W takich strukturach nie dopuszcza się elementów pustych, (pokrycie zupełne),
- Do tych struktur należą: stos, kolejka, talia niesymetryczna i symetryczna, lista
jedno- i dwukierunkowa.
- Dla każdej z wymienionych struktur będą przedstawione:
* Wyróżnienie,
* Lista operacji prostych (dynamika struktury),
* Ewentualne uwagi,
* Zastosowania,
* Lista operacji złożonych.
Definicja:
Struktury – stos, kolejka, talia (symetryczna i niesymetryczna) oraz lista (jedno- i
dwukierunkowa) – to struktury o:
- pokryciu zupełnym,
- podłożu liniowym zmiennym,
- o dynamice stosu (dpowiednio); stosu, kolejki, tali, listy.
STOS
Wyróżnienia: wierzchołek stosu, ewentualnie dno stosu.
Operacje proste (5 operacji) :
- Opróżnienie stosu
- Testowanie :
* czy pusty
* na zawartość wierzchołka,
- Dołączanie nowego elementu – tylko na wierzchołku,
- Kasowanie elementu – tylko z wierzchołka.
Uwagi :
- Struktura pracuje jednym końcem,
- Określana jako struktura LIFO (Last In First Out)
Zastosowania :
- Tam gdzie potrzebna jest realizacja zasady LIFO np. algorytmy przeglądania grafu,
obliczenie wartości wyrażenia, derekursywacja programów,
- Gdy zasada ta jest obojętna, stos okazuje się najprostszą strukturą o zmiennym
podłożu.
Operacje złożone :
- Przeglądanie stosu,
KOLEJKA
Wyróżnienia: początek kolejki, koniec kolejki.
Operacje proste (5 operacji) :
- Opróżnienie kolejki,
- Testowanie :
* czy puste,
* na zawartość działki początkowej,
- Dołączanie nowego elementu – tylko na koniec,
- Kasowanie elementu – tylko na początku.
Uwagi :
- Struktura pracuje obydwoma krańcami niesymetrycznie,
- Określana jako struktura FIFO (First In First Out)
Zastosowania :
- Przede wszystkim jako kolejka zadań o jednakowych priorytetach, czekających na
wykonanie.
Operacje złożone :
- Przeglądanie kolejki,
- Konkatenacja kolejki,
TALIA (półka) niesymetryczna
Wyróżnienia : Koniec lewy i prawy (początek i koniec),
Operacje proste (6 operacji) :
- Opróżnianie talii,
- Testowanie:
* czy pusta,
* na zawartość działki początkowej,
- Dołączanie nowego elementu - na początek i na koniec,
- Kasowanie elementu - tylko na początku,
Uwagi :
- Struktura pracuje obydwoma krańcami niesymetrycznie,
Zastosowania :
- Jako kolejka zadań do wykonania przy założeniu, że zadania dzieli się na zadania z
normalnym priorytetem (dołączane na koniec) oraz zadania z priorytetem
zwieszonym (dołączane na początek).
Operacje złożone :
- Przeglądanie talii,
- Konkatenacja talii,
Talia symetryczna
Wyróżnienia : koniec lewy i prawy (początek i koniec).
Operacje proste (8 operacji) :
- Opróżnianie talii,
- Testowanie:
* czy pusta,
* na zawartość działki początkowej,
* na zawartość działki końcowej.
- Dołączanie nowego elementu - na początek i na koniec,
- Kasowanie elementu - na początku i na końcu.
Uwagi :
- struktura pracuje obydwoma krańcami symetrycznie.
Zastosowania :
- Jako kolejka zadań przeznaczonych do wykonania dla dwóch wykonawców, każdy
bierze do wykonania w pierwszej kolejności zadania swoje, a po wyczerpaniu
wykonuje zadania w zasadzie przeznaczone dla drugiego wykonawcy.
Operacje złożone :
- Przeglądanie talii,
- Konkatenacja talii,
Lista jednokierunkowa (niesymetryczna).
Wyróżnienia :
- Stałe:
* koniec lewy (początek),
* koniec prawy (koniec)
- Zmienne: wyróżnienie główne (robocze).
Operacje proste (9 operacji) :
- Opróżnianie listy,
- Testowanie:
* czy pusta,
* czy wyróżnienie główne na końcu,
* na zawartość działki pod wyróżnieniem głównym.
- Przesunięcie wyróżnienia głównego:
* na początek,
* na następną działkę.
- Dołączanie nowego elementu :
* po (na prawo od) wyróżnieniu głównym,
* na koniec (niezależnie od położenia wyróżnienia głównego).
- Kasowanie elementu : pod wyróżnieniem głównym (wyróżnienie główne
przesuwa się wtedy jeśli możliwe na prawo, jeśli nie, to na lewo, jeśli to był ostatni
to wyróżnienie znika.)
Operacje złożone:
- Przeglądanie i przeszukiwanie listy,
- Sortowanie listy (zostanie omówione),
- Konkatenacja listy.
niesymetryczną – na obu listach
Lista dwukierunkowa (symetryczna).
Wyróżnienia:
- Stałe:
* koniec lewy (początek),
* koniec prawy (koniec)
- Zmienne: wyróżnienie główne (robocze).
Operacje proste (12 operacji) :
- Opróżnianie listy,
- Testowanie:
* czy pusta,
* czy wyróżnienie główne na końcu,
* czy wyróżnienie główne na początku,
* na zawartość działki pod wyróżnieniem głównym.
- Przesunięcie wyróżnienia głównego:
* na początek,
* na koniec,
* na następną działkę,
* na poprzednią działkę.
- Dołączanie nowego elementu :
* po (na prawo od) wyróżnieniu głównym,
* na koniec (niezależnie od położenia wyróżnienia głównego).
- Kasowanie elementu : pod wyróżnieniem głównym (wyróżnienie główne
przesuwa się wtedy jeśli możliwe na prawo, jeśli nie, to na lewo, jeśli to był ostatni
to wyróżnienie znika.)
Operacje złożone: jak dla listy jednokierunkowej, ale z możliwością stosowania
bardziej dogodnych algorytmów.
- Przeglądanie i przeszukiwanie listy,
- Sortowanie listy (zostanie omówione),
- Konkatenacja listy.
.
Uwagi ogólne dla listy jedno- i dwukierunkowej
Uwagi :
- Stanowi konkurencje dla tablicy,
- W stosunku do tablicy jest:
* Bardziej elastyczna (podłoże),
* Cale nie posiada adresacji, co uniemożliwia albo przynajmniej utrudnia niektóre
operacje.
Zastosowania :
- Tekst w edytorze,
- Lista rekordów (plik listowy).
Lista rekordów.
W każdym rekordzie znajduje się pole kluczowe i jego zawartość może decydować
o rozmieszczeniu albo stanowić podstawę odszukania rekordu.
Rozmieszczanie rekordów:
- chaotycznie,
- monotonicznie:
- Uwaga : nie można rozmieszczać algorytmicznie (jak to było w tablicy), ze
względu na brak adresacji.
Operacje złożone:
- Dołączanie rekordu : w przypadku rozmieszczenia chaotycznego jest to operacja
prosta „dołącz na koniec”. W przypadku listy posortowanej – szukaj właściwego
miejsca i ulokuj rekord w tym miejscu.
- Odszukiwanie rekordu : sekwencyjne (binarne nie, bo odwołuje się do adresów),
- Kasowanie rekordu : operacja prosta „kasuj pod wyróżnieniem” (ewentualnie
poprzedzona operację odszukiwania rekordu do skasowania),
- Sortowanie (monotonizacja) listy : operacja sortowania list jest bardzo ważna
(mimo braku możliwości wykorzystania wyszukiwania binarnego) ze względu na
ewentualne powiązania struktur listowych z tablicowymi w przetwarzaniu.
Sortowanie proste :
- Proste wstawianie (nadaje się) : listę rozdziela się na dwie niezależne lity
(posortowaną i nieposortowaną), przenosi się kolejne elementy z listy
nieposortowanej do posortowanej, unika się problemu rozpychania.
- Proste wybieranie (nadaje się) : rozdziela się na dwie niezależne lity (
posortowaną i nieposortowaną ) , przenosi się z lity drugiej do pierwszej poprzez
wybieranie elementu, odpada konieczność zamiany lub rozpychania.
- Metoda bąbelkowa (wykonalna) : nie jest brana pod uwagę ze względu na koszt
dużej ilości krótkodystansowych przestawień.
Sortowanie złożone :
- Quicksort (w zasadzie nie nadaje się) : powstaje niezręczność przy wyborze
elementu dzielącego, wymagana jest lista dwukierunkowa, ze względu na
przesuwanie się wskaźników od lewej i prawej strony równocześnie.
- Quicksort (modyfikacja nadająca się do list) : tworzy się trzy listy wyjściowe –
dla mniejszych, równych i większych od elementu dzielącego, wywołuje się to
sortowanie dla 1 i 3 lity (np. rekurencyjnie), następnie konkatenuje 1,2 i 3 listę.
- Metoda scalania (najlepsza metoda złożona do sortowania list) : lista może być
jednokierunkowa, wariant cykliczny - odszukaj pierwszą i drugą serie naturalną od
początku lity, scal je i dołącz do końca sortowanej listy, kontynuuj aż okaże się , że
jest tylko pierwsza seria i to długości całej listy.
Ocena złożoności sortowania listy rekordów: pełna ocena możliwa tylko przy
znajomości zastosowanej implementacji.
Implementacja Struktur Danych
Implementacja struktury A na strukturze B oznacza reprezentację struktury A przez
strukturę B:
- Struktura A: struktura implementowana (reprezentowana),
- Struktura B: struktura implementująca (reprezentująca).
Definicja: Implementacja struktury A na strukturze B to odpowiedniość:
- Między stanami struktur A i B;
* Każdemu dopuszczalnemu stanowi struktury A powinien odpowiadać, co
najmniej jeden dopuszczalny stan struktury B,
* Każdemu stanowi struktury B, który to odpowiada pewnemu stanowi struktury
A, powinien odpowiadać dokładnie jeden stan struktury B,
- Między operacjami na strukturach A i B;
* Każdej operacji prostej O, zdefiniowanej dla A, powinna odpowiadać, co
najmniej jedna operacja O’ (niekoniecznie prosta), możliwa dla B,
- Odpowiedniość między stanami struktur A i B oraz odpowiedniość miedzy
operacjami na tych strukturach powinny być ze sobą związane następującą zasadą;
* Jeżeli stanowi S struktury A odpowiada stan S’ struktury B, a operacja O na
strukturze A odpowiada operacji O’ na strukturze B, to wynikowi operacji
dokonanej na strukturze A w stanie S powinien odpowiadać wynikowi operacji O’
dokonanej na strukturze B w stanie S’.
Twierdzenie o rozszerzonej dynamice :
- Jeżeli struktury A i B mają jednakowe działki , a dynamika struktury B stanowi
rozszerzenie dynamiki struktury A o dodatkowe operacje, to strukturę A można
zaimplementować na strukturze B.
Twierdzenie o przechodniości implementacji :
- Jeżeli strukturę A da się zaimplementować na strukturze B, a strukturę B da się
zaimplementować na strukturze C, to strukturę A da się zaimplementować na
strukturze ( A→ B i B→ C to A→ C ).
Przykłady implementacji.
Implementacja tablic:
- „mała” tablica A na dużej tablicy B (działki tego samego typu, tablice
numerowane, numeracja A jest podprzedziałem numeracji B – nadmiarowe działki
nie mają znaczenia, ale jednemu stanowi tablicy implementowanej może
odpowiadać wiele stanów tablicy implementowanej),
- wiele „małych” tablic A1, A2 ….. na dużej tablicy B,
- tablice jak wyżej ale działka tablicy B ma mniejszą pojemność niż działka w
tablicy A (jednej działce tablicy A odpowiada ciąg sąsiadujących ze sobą działek
tablicy B – ciąg powinien liczyć tyle działek, by zbiór dopuszczalnych pokryć tego
ciągu nie był mniejszy niż zbiór dopuszczalnych pokryć jednej działki tablicy w
pamięci),
- implementacja dowolnej tablicy w pamięci operacyjnej; pamięć operacyjna jest
realnie istniejącą tablicą liniową numerowaną, zwykle o niewielkich działkach (1
bajt), dowolną abstrakcyjną tablice liniową numerowaną można zaimplementować
na niej podobnie jak to było przedstawiane powyżej.
1. Na mocy twierdzeń o rozszerzonej dynamice i przechodniości implementacji
wynika, że stos
i kolejkę można
zaimplementow
ać na obu
taliach listach, a
talię
2. Implementacje struktur liniowych o podłożu zmiennym na tablicach;
- Dla stosu;
* stos na tablicy,
* dwa stosy na tablicy (złączone dnem lub dna na krańcach tablicy),
* wiele stosów na tablicy
- Dla kolejki;
* kolejka na tablicy (pełzanie),
* wiele kolejek na tablicy,
3. Implementacje struktur liniowych o podłożu zmiennym na łańcuchach (inaczej:
na strukturach odsyłaczowych, wskaźnikach);
- stos na łańcuchu jednokierunkowym,
- kolejka na łańcuchu jednokierunkowym,
- kolejka na pierścieniu jednokierunkowym,
- lista jednokierunkowa na łańcuchu jednokierunkowym,
- lista dwukierunkowa na łańcuchu dwukierunkowym,
Struktury pierścieniowe
- Struktury pierścieniowe wykazują duże podobieństwo do liniowych.
- Podłoże pierścieniowe;
* W przypadku tego podłoża każda działka ma następnik, każda działka ma
działkę poprzedzającą i każda działka jest z każdej osiągalna naprzód i wstecz.
- W niektórych przypadkach struktury pierścieniowe są bardziej praktyczne od
liniowych,
Pierścień jednokierunkowy:
Definicja: struktura dynamiczna o podłożu pierścieniowym zmiennym. O
pokryciu zupełnym, o dynamice pierścienia jednokierunkowego.
Wyróżnienia (obydwa wyróżnienia są zmienne):
- umowny początek pierścienia,
- wyróżnienie główne robocze,
Operacje proste (9 operacji) :
- Opróżnianie struktury,
- Testowanie:
* czy pierścień pusty,
* czy wyróżnienie robocze na początku,
* na zawartość działki pod wyróżnieniem roboczym.
- Przesuń wyróżnienie;
* główne na początek,
* główne o jedną działkę na przód,
* początek na miejsce głównego,
- Dołączanie elementu :
* np. na prawo od wyróżnienia głównego (tylko jedno w odróżnieniu od listy
jednokierunkowej),
- Kasowanie elementu : pod wyróżnieniem głównym (wyróżnienie główne
przesuwa się o jedną działkę na prawo), łatwiejsza implementacja kasowania ZA
wyróżnieniem głównym.
Pierścień dwukierunkowy
Definicja: na podstawie pierścienia jednokierunkowego i listy dwukierunkowej.
Struktury drzewiaste
Definicja:
1) Drzewa grafowe (jest to drzewo bez korzenia albo z korzeniem definiowane
jako szczególny przypadek grafu). Drzewo grafowe to struktura statyczna nie
będąca strukturą danych, może być traktowana jako statyczna struktura danych,
jeżeli jego węzły zostaną potraktowane jako działki podłoża struktury.
Dynamiczna struktura danych to struktura, której stany są statycznymi
strukturami drzewiastymi. Zbiór dopuszczalnych stanów i dynamikę takiej
struktury można definiować na wiele sposobów uzyskując m.in.:
- mnogościowe,
- tablicowe (w tym binarne),
- listowe,
Zamiast drzew grafowych z dołączoną dynamiką można wykorzystywać
uprzednio zdefiniowane dynamiki struktur mnogościowych i liniowych, i
rekurencyjnie definiować te same drzewa, wprowadzając dynamikę równocześnie
z tymi elementami definicji, które dotyczą podłoża i pokrycia.
2) Drzewa rekurencyjne (wielowarstwowe):
- mnogościowe,
- tablicowe (binarne, pozycyjny),
- listowe,
Drzewo mnogościowe (rekurencyjne)
Drzewo rekurencyjne mnogościowe to rekord składający się z dwóch pól:
a) pola korzenia pokrytego przez daną składową,
b) pola rozgałęzienia pokrytego przez las mnogościowy.
Las mnogościowy to zbiór (w sensie mnogościowym struktura danych) drzew
mnogościowych.
Las rozgałęziający to las pokrywający pole rozgałęzienia.
Jeżeli las rozgałęziający jest pusty drzewo redukuje się do bezpotomnego
korzenia.
Drzewo elementarne – drzewo zredukowane do korzenia.
Można tu przenieść wprowadzone dla struktur grafowych pojęcia takie jak: liść,
ścieżka promieniowa, poddrzewo, poziom, relacja ojciec syn itd.
Zastosowanie: reprezentacja klas równoważnościowych w zbiorach o znanym
składzie (w przypadku komputerowej analizy grafu może to być – w szczególnym
przypadku – ewidencja przynależności wierzchołków grafu do jego części
spójnych)
Drzewo rekurencyjne tablicowe
Drzewo rekurencyjne tablicowe to rekord składający się z dwu pól:
- pola korzenia pokrytego przez daną składową oraz,
- pola rozgałęzienia pokrytego przez las tablicowy.
Las tablicowy to tablica o działkach pokrytych przez drzewa tablicowe.
Tablica rozgałęziająca – tablica pokrywająca pole rozgałęzienia.
(Jeżeli tablica rozgałęziona jest pusta tzn. działki pozbawione pokrycia, to korzeń
bezpotomny)
Drzewo (tablicowe) elementarne jw.
Szczególnym przypadkiem rekurencyjnego drzewa tablicowego jest drzewo
binarne.
Szczególne przypadki rekurencyjnego drzewa binarnego: drzewo binarne pełne, i
drzewo binarne kompletne.
Drzewo rekurencyjne binarne.
Drzewo tablicowe, w którym wszystkie tablice rozgałęziające są tablicami o
dwóch działkach (działka: pierwsza, druga; bądź działka: lewa, prawa).
Numeracja drzewa binarnego pełnego;
Numeryzacja poziomami
Drzewo kompletne (uwagi);
- Drzewo kompletne może może mieć dowolną liczbę węzłów,
- Jeżeli n=2k-1, gdzie k=1, 2, 3, … to drzewo kompletne staje się drzewem
pełnym.
- Jeżeli węzły drzewa kompletnego ponumerujemy poziomami jak wyżej, to
pierwszy syn węzła k ma numer 2k, a drugi 2k+1, zaś ojciec węzła o numerze k
ma numer kdiv2, węzły numer 1 do ndiv2 są ojcami (mają co najmniej 1 syna),
pozostałe są liściami.
Implementacje (tekstowe, odsyłaczowi, poziomami) drzew pełnych albo
kompletnych to implementacje tych drzew na tablicy liniowej numerowanej,
(obrazem węzła o numerze k jest działka tablicy mająca także numer k).
Uwaga:, ponieważ tablica kompletna może mieć dowolną liczbę węzłów, to każdą
tablicę liniową 1…n można uznać za tablicę implementującą pewne kompletne
drzewo binarne.
Odsyłaczowe i tekstowe implementacje drzew binarnych
Dla drzew binarnych niebędących drzewami kompletnymi implementacja
poziomami uciążliwa i mało wydajna. Stąd implementacje odsyłaczowe, czasem
tekstowe.
Implementacja trójodsyłaczowa:
Każdy rekord wyposażony jest w trzy odsyłacze:
Implementacja dwuodsyłaczowa:
- oszczędniejsza pamięciowo
- wymaga przeglądnięcia od korzenia (notatnik stosowy, gdy potrzebny powrót do
korzenia)
Rekurencyjne implementacje tekstowe
1. + a,b
korzeń – lewe – prawe KLP prefiksowa (przedrostkowa) – Łukasiewicza (Polska)
2. (a + b) – (konieczne nawiasy)
lewe – korzeń – prawe LKP
infiksowi (wzrostkowa)
3. a,b +
lewe – prawe – korzeń LPK
postfiksowa (przyrostkowa) – Odwrotna Notacja
Polska
Analogia do gramatyki, odpowiedniki w konwencjach zapisu wyrażeń
arytmetycznych i logicznych.
Ulepszona metoda wybierania
Sortowanie stogowe (poprzez kopcowanie) (stosujemy kolejki priorytetowe)
Stóg definiujemy jako ciąg kluczy h2, h2+1, … hp takich że hi <= h2i , hi <= h2i+1 dla
wszystkich l = p/2 . Kolejne zdjęte wartości max z wierzchołka stogu dają
posortowany ciąg w odwrotnej kolejności. (mniejsza liczba porównań w stosie do
prostej metody wybierania przez zapamiętania większej ilości informacji – drzewo
binarne.
budowa stogu = O(n)
n – usunąć min*O(log n)
operacja usunięcia = O(nlog n).
czy można bez jeszcze dodatkowej pamięci ? – tak
1. działa w miejscu
2. dobra dla dużych (wtedy lepsze również od Shella)
3. dobra efektywność nawet w najgorszym przypadku 0(n log n)
4. faworyzuje częściowe uporządkowanie w kolejności odwrotnej - zachowanie
nienaturalne
porównanie:
N(n) = 2n logn + O(n); A(i) => nie znana pełna analiza O(n logn) współ. ~ 2 (lepszy
będzie QuickSort)
Kopiec i sortowanie kopcowe
Porządek kopcowy: (≠ porządku symetrycznego dla BST)
Odsyłaczowe i tekstowe implementacje drzew binarnych CD.
Dla drzew binarnych nie będących drzewami kompletnymi implementacja
pomiędzy poziomami => uciążliwa i mało wydajna stąd implementacje odsyłaczowi,
czasami tekstowe.
{sortowanie stogowe}
procedure heapsort (var a:input_data; n:integer);
var a:input_type;
procedure downheap (k:integer);
var i,j : integer; v : input_type ; s:boolean;
begin
v:=a[k];
while k<=n div 2 and not s do
begin
j := 2*k;
{j jest nastepnikiem k}
if j<n then if a[j]<a[j+1] then j := j+1;
if v>=a[j] then begin goto label1; s:=true; end
else begin a[k]:=a[j];
k:=j;
end;
label1: a[k] := v;
end;
deletmax
{function datemax : integer;}
procedure datemax (var d:input_type);
begin
d:=a[1];
a[1]:=a[n];
n:=n - 1;
downheap(1);
end;
procedure construct;
var i : integer;
begin
for i:=n div 2 downto 1 do downheap(i);
end;
begin
construct;
repeat
deletemax(x);
a[n] := x;
until n=1;
end.
{dla input_type = integer lepsza function datemax;}a[n] = datemax;
Przeglądanie drzewa:
- prefiksowe (przedrostkowe, wzdłużne) – KLP
- infiksowe (wzrostkowe, poprzeczne) – LKP
- postfiksowe (przyrostkowe, wsteczne) – LKP
type
link=^node
node=rekord
key=T
left,right=link;
end;
procedure KLP (t:link); ← przez wartość
begin
if t<>nil then
begin
P(t);←procedura odwiedzania wierzchołka
KLP (t^.left);
KLP(t^.right);
end;
end;
Konstrukcja drzewa dokładnie wyrażonego
1. użyj jeden węzeł na korzeń
2. zbuduj lewe poddrzewo z nl = n div 2 węzłami w ten sposób
3. zbuduj prawe poddrzewo z np. = n – nl – 1 węzłami w ten sposób
type
link = ^node;
node = record
el:El;
left,right:link;
end;
function tree ( n:integer) : link;
var
p:link;
x:T;
begin
if n=0 then tree:=nil else begin
read(x);
new(p);
………………..
p^.el:= x;
p^.left:= tree( n div 2);
p^.right:= tree( n – n div 2 – 1 );
tree := p;
end
end { drzewo – tree}
begin
root:=tree(100);
end.
Plik drzewiasty binarny
- drzewo binarne o działkach pokrytych przez rekordy jednakowego typu.
Binarne drzewo poszukiwań – Binary Serach Tree BST
Jest to plik drzewiasty binarny tworzony wg następującego algorytmu:
1. pierwszy rekord wstawiany do pliku umieść w korzeniu.
2. każdy następny rekord wprowadzaj przez korzeń porównując klucze : rekord o
kluczu większym do lewego poddrzewa, o kluczu większym do prawego
poddrzewa, powtarzaj w korzeniu każdego kolejnego poddrzewa. Jeśli dojdziesz do
poddrzewa pustego – rekord umieść jako liść. (porządek symetryczny)
x:
left(x), key(x), right(x)
Wg(1) tworzy się drzewo.
Wg zasady tworzenia (1,2) prowadzi się również wyszukiwanie.
Operacja wyszukiwania jest częścią składową operacji wstawiania i usuwania
wierzchołków.
Usuwanie wierzchołka można przeprowadzić zastępując go wierzchołkiem
zawierającym
albo element bezpośrednio poprzedzający wartość elementu usuwanego w zbiorze
wartości, (b) albo element bezpośrednio następujący.
Opóźnione usuwanie ( zaznaczamy, że usunięty => potem reorganizacja).
BST
type
tree_ptr = ^tree_node;
tree_node = record
element : element_type;
left,right : tree_ptr;
end;
SEARCH_TREE = tree_ptr;
{tworzenia drzewa pustego}
procedure make_null ( var T:serach_tree);
begin
t:=nil;
end;
{operacja szukania}
function find ( x : integer; T:search_tree) : tree_ptr;
begin
if T = nil then
find:=nil
else
if x < T^.element then find:=find (x,T^.right)
else find:=T;
end; {find}
function find_min ( T:search_tree):tree_ptr;
begin
if T = nil then find_min := nil
else
if T^.left = nil then find_min:=T
else find_min := find_min ( T^.left);
end;
function find_max (T:…..):tree_ptr;
begin
if T<>nil then
while T^.right <> nil do
T := T^.right;
find_max := T;
end;
procedure insert ( x:element_type; var T:…..);
begin
if T = nil then
begin
{tworzymy i zwracamy 1 węzeł, korzeń}
New(T);
if T = nil then
fata_error(‘out of space’)
else begin
T^.element := x;
T^.left := nil;
T^.right := nil;
end;
end {if T = nil}
else begin
if x < T^.element then
insert ( x, t^.left)
{ else x jest w drzewie, nic nie robimy}
end;
end: {insert)
Drzewo poszukiwań BST
- usuwanie wierzchołka – wersja rekurencyjna
- 3 możliwości:
1. brak węzła w danym kluczu
2. węzeł o kluczu x ma 0 lub 1 potomka
3. węzeł o kluczu x ma 2 potomków
Węzeł usuwany musi być zastąpiony przez skrajny prawy element lewego
poddrzewa lub lub skrajny lewy węzeł prawego poddrzewa z których każdy ma
co najwyżej jednego potomka.
Procedure delete ( v:T; var p:link);
Var
q : link;
procedure del (var v:link);
begin
if r^.right <> nil the del(r^.right) else
begin
q^.key := r^.key;
{ewentualne inne pola rekordu}
q := r; r:= r^.left;
end;
end
begin
if p = nil then writeln(‘Brak’) else
if v < p^.key then delete(v, q^.left) else
if v>p^.key then delete(v,p^.right) else
begin {delete p^}
q:=p;
if q^.right = nil then p:=q^.left else
if q^.left = nil then p:=q^.right else
del(q^.left);
dispose(q);
end;
end.
var y:node {poprzednik wierzchołka szukanego}
function search (v, p, r :node):node
{ T- dowolny typ uporządkowany liniowo
r – korzeń drzewa BST}
var
x:node;
Begin
x := r; y := nil;
while (x ≠ nil) and (key(x) ≠ v) do
begin
y := x;
if v < key(x) then x := left(x)
else x := right(x);
end;
search := x;
end. {search}{ jeżeli element należy do BST → x ≠ nil i key(x) = v, jeżeli
element nie należy do BST → x = nil.}
procedure insert (v:T; var r:node);
var
x,y:node
Begin
if search(v, r, y) = nil then
begin
new(x);
left(x) := nil;
key(x) := v;
right := nil;
if y = nil then r := x; {r – korzeń}
else
if v < key(y) then left(y) := x;
else right(y) := x;
end;
end. {insert}
procedure construct (var r:node);
begin
r :=nil:
end. {construct}
procedure delete (v:T; var r:node);
var
x, y, z, t:node;
b: 0…1;
Begin
x := search (v, r, y);
if x ≠ nil then {jeśli znaleźliśmy usuwamy}
begin
if (left(x) = nil) or (right(x) = nil) then
begin
if (left(x) = nil) and (right(x) = nil) then z := nil else
if left(x) = nil then x := right(x)
else z := left(x);
if y = nil then r := z; {za korzeń} else
if x = left(x) ten left(y) := z else right(z) := z
end;
else
begin {left(x) ≠ nil; right(x) ≠ nil}
b := random(z); { ??? random(2)???}
Drzewa AVL
Drzewo BST jest drzewem AVL wtedy, kiedy dla każdego wierzchołka
wysokości dwóch jego bliźniaczych poddrzew różnią się co najwyżej o 1.
Wysokość drzewa Al 0(logn) {n- liczba wierzchołków}→ czas działania na
drzewie ≠ O(logn)Operacje (działania na drzewie);serach – taka sama jak dla
drzewa BST
Struktury Grafowe
Wstęp – Definicje
1. Intuicyjna definicja grafu (kropki, odcinki strzałki)
2. Klasyfikacja grafów:
- grafy proste i multigrafy;
- grafy skierowane i niekierowane;
3. Definicja grafu prostego nieskierowanego;
G = (V,E); (Vertices, Edges);
V – zbiór wierzchołków, E – zbiór krawędzi,
Krawędź to nieuporządkowana para wierzchołków (różnych),


E
{ (v1,v2) │v1, v2
V
v1 ≠ v2 }
(Zakaz krawędzi równoległych zapętlonych)
Klasyfikacja Grafowych Struktur Danych
1. Według rodzaju grafu;
Grafowa struktura danych może być oparta na;
- grafie prostym niekierowanym,
- grafie prostym skierowanym,
- multigrafie niekierowanym,
- multigrafie skierowanym,
2. Według sposobu wykorzystania grafu;
Jako działki podłoża mogą być wykorzystane;
- wierzchołki grafu – struktura wierzchołkowa,
(krawędzie = powiązanie między działkami),
- krawędzie grafu – struktura krawędziowa (np. w grafie ważonym),
- wierzchołki i krawędzie grafu – struktura wierzchołkowo - krawędziowa, (rolę
powiązań spełniają elementy relacji incydencji),
3. Według regularności grafu;
Podłoże struktury grafowej może być;
- regularne (np. w przypadku tablic wielowymiarowych),
macierze zupełne;
* pasmowe,
* trójkątne,
* symetryczne,
* antysymetryczne
macierze rzadkie,
- nieregularne,
Graf etykietowany:
Wierzchołki = działki,
Krawędzie = elementy powiązania działki,
Wierzchołkom przypisujemy etykiety = dane składowe struktury danych,
Graf ważony:
Elementy przypisane do krawędzi → wagi,
Krawędzie = działki,
Dynamika Struktur Grafowych
Operacje proste:
- opróżnienie struktury,
- wyróżnienie poszczególnych działek (np. wierzchołków),
- operacje na wyróżnieniach;
* przenoszenie wyróżnienia;
^ z wierzchołka na wierzchołek,
^ z krawędzi na wierzchołek,
^ z wierzchołka na krawędź,
- operacje na pokryciu;
* pokrywanie wskazanego wierzchołka lub krawędzi,
* zdejmowanie pokrycia,
* zmiana pokrycia,
- operacje zmieniające podłoże;
* dołączanie wierzchołka (separowanego) – dołączanie krawędzi,
* odłączanie wierzchołka (separowanego) – odłączanie krawędzi,
* odłączanie podgrafu,
* dołączanie podgrafu,
4. Postępujemy tak dopóki stos nie jest pusty.
UWAGA: Nie przechodzimy przez wszystkie krawędzie. Przejrzane wierzchołki i
krawędzie to „maksymalny” podgrafu acykliczny.
Przykład:
Implementacja Grafu Prostego Nieskierowanego
Dwa rodzaje implementacji:
A - odsyłaczowe,
B – tablicowe.
A: - Dla grafów etykietowanych i ważonych,
2 listy: węzłów i krawędzi,
Przeglądanie Stosowe:
Analogicznie jak dla stosowego tylko dynamika stosowa zastąpiona dynamiką
kolejki; nowe rzeczy wrzucamy na koniec, stare pobieramy z początku.
1. Zaczynamy od dowolnego wierzchołka; odnotowujemy go w kolejce i
markujemy,
2. Według kolejkowego notatnika pobieramy następny wierzchołek nie
zamarkowany,
3. Jeśli początkowy wierzchołek w kolejce nie ma już nie zamarkowanych
następników zdejmujemy go z kolejki i powtarzamy punkt 2.
4. Dopóki kolejka nie jest pusta kontynuujemy.
UWAGA: Drzewo rozpinające jest korzystniejsze, bardziej rozgałęzione.
Przykład:
5, 13, 12, 10, 9, 3, 1, 2, 6, 7, 11
5, 13, 12, 10, 9, 3, 1, 2, 6,
5, 13, 12, 10, 9, 3, 4
5, 13, 12, 10, 9
5, 13, 12, 8 → pusty stos koniec !
Lista Krawędzi
X – dla grafów etykietowanych (nie ważonych)
5, 13, 9, 4, 2, 7
13, 9, 4, 2, 7, 12, 11
9, 4, 2, 7, 12, 11, 10, 3
2, 7, 12, 11, 10, 3, 6, 1
12, 11, 10, 3, 6, 1
- lista wierzchołków adiacentnych – linia czerwona,
- wskazuje na najbliższego sąsiada – linia niebieska,
LISTA SĄSIADÓW (listy sąsiedztwa) → (macierz sąsiedztwa),
B: - Tablicowa incydentna,
Wierzchołki
↔
krawędzie
↓
e1
e2
E3
e4
e5
1
1
1
0
0
0
2
1
0
0
0
0
3
0
0
1
0
1
4
0
0
1
1
0
5
0
1
0
1
1
W każdej kolumnie mogą być tylko dwie jedynki !!!
B: - Tablicowa adiacentna,
przekątna zawsze pusta
1
2
3
4
5
1
0
1
0
0
1
2
1
0
0
0
0
3
0
0
0
1
1
4
0
0
1
0
1
5
1
0
1
1
0
Tablica kwadratowa symetryczna
Dynamika Struktur Grafowych CD:
Operacje złożone:
Najczęściej jest to;
- przeglądanie grafu,
- budowa drzewa rozpinającego,
- badanie spójności grafu,
- badanie cykliczności grafu,
- badanie planarności grafu,
- poszukiwanie maksymalnego podgrafu pełnego (kliki),
- i inne,
Zakładając graf etykietowany, nie ważony;
- przeglądanie stosowe (wzdłuż) – metoda w głąb z użyciem notatnika stosowego,
- przeglądanie kolejkowe (wszerz) – metoda w szerz z użyciem notatnika
kolejkowego,
(Notatnik służy w obu przypadkach służy do informowania o kolejności
przeglądania)
Przeglądanie Stosowe:
1. Zaczynamy od dowolnego wierzchołka; odnotowujemy go na stosie i markujemy,
2. Według stosowego notatnika idziemy do wierzchołka następnego nie
zamarkowanego,
3. W ten sposób postępujemy tak długo, aż dany wierzchołek nie ma nie
zamarkowanych sąsiadów. Wtedy zdejmujemy go ze stosu i wracamy do punktu 2.
Wada: uciążliwość przeszukiwań.
Implementacja odsyłaczowa:
↓
koniec kolejki !
Graf Prosty Skierowany
Jest to para G = (V, E) złożony z dwóch zbiorów;
V - zbiór wierzchołków (dowolny),
E – zbiór krawędzi (zbiór uporządkowanych par wierzchołków)
Zabronione krawędzie zapętlone.
Uporządkowanie znaczymy strzałką.
Graf nie skierowany możemy uważać jako szczególny przypadek grafu
skierowanego (krawędzi nie ma lub są (v1, v2) i (v2, v1).
Operacja neutralizacji grafu;
- krawędzie równoległe nie ruszamy,
- pojedyncze krawędzie uzupełniamy dodatkową krawędzią w drugą stronę,
- uzupełniamy wszystkie krawędzie,
Incydencja;
- dodatnia incydencja,
- ujemna incydencja,
- incydencja (krawędzie w obu kierunkach),
Implementacje grafów skierowanych (tablicowe i odsyłaczowe);
1. Tablica incydencji: +1, -1, =1,
2. Tablica adiacencji: nie musi być już symetryczna,
3. Lista krawędzi: 1 pole = początek, 2 pole = koniec krawędzi,
4. Lista sąsiadów: lista odsyłaczy do sąsiadów – lewo i prawo stronnych = 2 listy
do jednego węzła lub pole bitowe z jedną listą.
Multigrafy
Mogą być skierowane i nie skierowane (multigrafy nie skierowany można
oczywiście też doprowadzić do skierowanego → dalej o skierowanych)
Definicja:
Ciąg trzech elementów G = (V, E, ŋ)
V- dowolny zbiór (jak w grafie prostym)
E – dowolny zbiór (odmiennie niż w grafie prostym!) jedyny warunek: rozłączny w
stosunku do V (krawędzie definiowane są samoistnie, nie może być czegoś co jest
węzłem i krawędzią)
ŋ - funkcja incydencji – przypisuje każdej krawędzi parę wierzchołków, 1początek, 2-koniec.
ŋ :E→VxV
ŋ – nie musi być różnowartościowa (dopuszczalne są krawędzie równoległe i
zapętlone)
Implementacja struktur danych opartych na multigrafach:
1. Odsyłaczowa (lista krawędzi incydentnych) – jak grafy proste (lista
wierzchołków + lista krawędzi + połączenia incydentna),
2. Tablicowa (incydencja dla obu typów naraz) – tablica incydencji nie 3 a 4
możliwości (krawędź zapętlona (podwójna incydencja)).
Zastosowania: do modelowania sieci, do obwodów elektrycznych, sieci
hydraulicznych i komunikacyjnych, komunikacyjnych także do diagramów ORD w
podejściu obiektowym.
Struktury danych:
- ważone,
- etykietowane,
- z obydwoma rodzajami połączeń (szeroko stosowane).
Struktury regularne (linearyzacja)
1. Przykład: tablice trójwymiarowe,
2. Linearyzacja leksykograficzna (najszybciej zmienia się indeks ostatni)
Np. A(1,1,1); A(1, 1, 2); A(1, 2, 1); A(1, 2, 2); …A(4, 3, 2)
3. Linearyzacja antyleksykograficzna (najszybciej zmienia się indeks pierwszy)
Np. A(1,1,1); A(2, 1, 1); … A(4, 1, 1); A(1, 2, 1); …A(4, 3, 2)
Macierze niepełne
Macierz = tablica dwuwymiarowa
Linearyzacja leksykograficzna = linearyzacja wierszowa
Linearyzacja antyleksykograficzna = linearyzacja Kolumnowa
Macierz niepełna to macierz o dużej ilości elementów trywialnych (np. działki
puste, zerowe, spacje, powtarzające się pokrycie).
Macierz pasmowa: elementy nietrywialnie na przekątnej głównej, w pasie
symetrycznie rozmieszczonym względem przekątnej.
Macierze trójkątne: Implementacja: część nietrywialna poniżej linii podziału
mieści się w części w części pustej powyżej linii podziału.
Macierze symetryczne: nietrywialna część macierzy symetrycznej jest macierzą
trójkątną dużą.
Macierze antysymetryczne: nietrywialna część macierzy antysymetrycznej jest
macierzą trójkątną małą.
Macierze rzadkie
Są to macierze o niewielkiej ilości elementów trywialnych (kilka % np. macierze
adiacencji i incydencji implementujące strukturę grafu).
Implementacja na triadach:
Triada – rekord o trzech polach
i – numer wiersza,
j – numer kolumny,
A (i,j) – pokrycie działki
Struktura implementująca – lista o działkach pokrytych przez triady
Zaleta: prostota struktury.
Problemy grafowe
- Problem najkrótszej drogi,
- Problem minimalnego drzewa rozpinającego,
- Problem maksymalnego przepływu,
- Problem najtańszego przepływu,
- Najliczniejsze skojarzenie,
- Problem ścieżki Hamiltona (TSP),
- Problem kolorowania grafu,
- Wyznaczenie składowych spójnych,
- Wyszukiwanie cykli,
- Wyszukiwanie klik,
- Problem planarności,
- Problem wizualizacji grafu.
Sortowanie cd
Sortowania zewnętrzne:
- przez łączenie proste (sortowanie wyważone i nie wyważone),
- przez łączenie naturalne (sortowanie wyważone i nie wyważone),
- przez wielokierunkowe łączenie wyważone,
- sortowanie polifazowe,
- sortowania mieszane.
Sortowania o złożoności liniowej:
- licznikowe (countsort, radixsort),
- rozrzutowe (kubełkowe).
Sortowania wielo kluczowe (pozycyjne):
- na wielu równorzędnych kluczach,
- na zhierarchizowanych kluczach częściowych.
Sortowania zewnętrzne przez łączenie proste (jednofazowe i dwufazowe)
- wykorzystujemy łączenie jak w klasycznym mergsort,
- występują dwie fazy;
* faza dzielenia – rozdzielania danych na dwa pliki (taśmy),
* łączenie dwóch plików (taśm) w trzeci,
- powstałe sortownie dwufazowe posiada bezproduktywne kopiowanie elementów,
- poprawa: sortowanie jednofazowe wyważone.
Sortowania zewnętrzne przez łączenie naturalne
- wykorzystujemy serie naturalne,
- jak w poprzednim przypadku mamy;
* sortowanie nie wyważone (łączymy pierwszą serią pierwszego pliku, z
pierwszą serią drugiego pliku, aż do skończenia jednego pliku, pozostałą resztę
pliku kopiujemy),
* sortowanie wyważone (dodajemy czwarty plik (taśmę) i fazę łączenia
zastępujemy fazą łączenia z jednoczesnym rozdzielaniem serii na dwie taśmy),
- uwaga na łączenie się serii.
Wielokierunkowe łączenie wyważone
- praca sortownia wewnętrznego jest proporcjonalna do liczby potrzebnych
przebiegów (bo w całym przebiegu kopiuje się cały zbiór danych),
- stąd rozwiązaniem może być rozkładanie danych na więcej niż 2 pliki (taśmy),
* scalamy z kilku plików, nie wolno kończyć scalania pików, gdy któryś się
skończy, należy kontynuować jeszcze dla aktywnych
* trzeba zamieniać pliki wejściowe z wyjściowymi (tablica plików),
* ilość plików (N) wchodzi do podstawy logarytmu przy rzędzie złożoności
algorytmu (Xn logN n,)
- uwaga na łączenie się serii.
Sortowanie polifazowe
- dla trzech plików (taśm);
* skoro tylko jeden z plików źródłowych się skończy, staje się natychmiast taśmą
wynikową dla operacji łączenia z jeszcze nie wyczerpanej taśmy źródłową oraz
taśmy, która uprzedni była taśma wynikową,
- dla większej ilości taśm;
Metody mieszane
Wykorzystuje się tablice i pliki; tablice wykorzystuje się do tworzenia serii
początkowych.
- Metoda buforowa – serie równe długości bufora,
- Metoda przelotowa – serie nierówne, o długości większej na ogół od bufora.
Sortowania licznikowe
- Sortowanie licznikowe mountsort,
- Sortowanie licznikowe radixsort.
Sortowania na wielu kluczach równorzędnych
- Wykorzystujemy sortowania pośrednie,
- Np. dla sortownia skorowidzowego wprowadzamy tyle skorowidzów ile jest
interesujących nas pól kluczowych i przeprowadzamy sortowania logiczne tych
skorowidzów,
- Uwaga; etap fizyczny sortowania może być przeprowadzony tylko według
jednego z kluczy, pozostałe skorowidze ulegają dezaktualizacji.
Download