Kolejka Priorytetowa. Algorytmy i Struktury Danych. (c) Marcin Sydow. Kolejka priorytetowa. implementacja. Kopiec Binarny. Tablicowa.

Podobne dokumenty
Kolejka priorytetowa. Często rozważa się kolejki priorytetowe, w których poszukuje się elementu minimalnego zamiast maksymalnego.

Sortowanie. Kolejki priorytetowe i algorytm Heapsort Dynamiczny problem sortowania:

dodatkowe operacje dla kopca binarnego: typu min oraz typu max:

ZASADY PROGRAMOWANIA KOMPUTERÓW ZAP zima 2014/2015. Drzewa BST c.d., równoważenie drzew, kopce.

Algorytmy i Struktury Danych

Struktury danych: stos, kolejka, lista, drzewo

Algorytmy i struktury danych. Drzewa: BST, kopce. Letnie Warsztaty Matematyczno-Informatyczne

Wykład 3. Złożoność i realizowalność algorytmów Elementarne struktury danych: stosy, kolejki, listy

Wykład 2. Drzewa zbalansowane AVL i 2-3-4

Drzewa BST i AVL. Drzewa poszukiwań binarnych (BST)

Porządek symetryczny: right(x)

Drzewa poszukiwań binarnych

Zofia Kruczkiewicz, Algorytmu i struktury danych, Wykład 14, 1

Drzewa poszukiwań binarnych

Teoretyczne podstawy informatyki

Teoretyczne podstawy informatyki

ALGORYTMY I STRUKTURY DANYCH

Sortowanie. Bartman Jacek Algorytmy i struktury

Wysokość drzewa Głębokość węzła

Uniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych. Algorytmy i struktury danych Laboratorium 7. 2 Drzewa poszukiwań binarnych

Drzewa czerwono-czarne.

Wykład 5. Sortowanie w czasie liniowologarytmicznym

Sortowanie - wybrane algorytmy

prowadzący dr ADRIAN HORZYK /~horzyk tel.: Konsultacje paw. D-13/325

Struktury Danych i Złożoność Obliczeniowa

Rekurencja. Dla rozwiązania danego problemu, algorytm wywołuje sam siebie przy rozwiązywaniu podobnych podproblemów. Przykład: silnia: n! = n(n-1)!

Algorytmy i. Wykład 5: Drzewa. Dr inż. Paweł Kasprowski

Sortowanie bąbelkowe

Listy, kolejki, stosy

0-0000, , , itd

Wstęp do programowania

liniowa - elementy następują jeden za drugim. Graficznie możemy przedstawić to tak:

Algorytmy zachłanne. dr inż. Urszula Gałązka

Wykład 6. Drzewa poszukiwań binarnych (BST)

Algorytmy i Struktury Danych. Co dziś? Drzewo decyzyjne. Wykład IV Sortowania cd. Elementarne struktury danych

Zadanie 1 Przygotuj algorytm programu - sortowanie przez wstawianie.

Drzewo. Drzewo uporządkowane ma ponumerowanych (oznaczonych) następników. Drzewo uporządkowane składa się z węzłów, które zawierają następujące pola:

Strategia "dziel i zwyciężaj"

ALGORYTMY I STRUKTURY DANYCH

Algorytmy i struktury danych. Wykład 4 Tablice nieporządkowane i uporządkowane

Algorytmy i Struktury Danych. (c) Marcin Sydow. Introduction. QuickSort. Sortowanie 2. Limit. CountSort. RadixSort. Summary

Podstawy programowania 2. Temat: Drzewa binarne. Przygotował: mgr inż. Tomasz Michno

Algorytmy i Struktury Danych. (c) Marcin Sydow. Sortowanie Selection Sort Insertion Sort Merge Sort. Sortowanie 1. Listy dowiązaniowe.

Wykład 8. Drzewo rozpinające (minimum spanning tree)

EGZAMIN - Wersja A. ALGORYTMY I STRUKTURY DANYCH Lisek89 opracowanie kartki od Pani dr E. Koszelew

Podstawowe struktury danych

Wykład 2. Drzewa poszukiwań binarnych (BST)

Algorytmy i struktury danych. wykład 5

a) 7 b) 19 c) 21 d) 34

Złożoność obliczeniowa zadania, zestaw 2

Wstęp do programowania

Wykład 8. Drzewa AVL i 2-3-4

Algorytmy i str ruktury danych. Metody algorytmiczne. Bartman Jacek

Programowanie dynamiczne

Wykład 3. Drzewa czerwono-czarne

Algorytmy i złożoności. Wykład 3. Listy jednokierunkowe

Rekurencja. Przykład. Rozważmy ciąg

Koszt zamortyzowany. Potencjał - Fundusz Ubezpieczeń Kosztów Algorytmicznych

Drzewa spinające MST dla grafów ważonych Maksymalne drzewo spinające Drzewo Steinera. Wykład 6. Drzewa cz. II

wstęp do informatyki i programowania część testowa (25 pyt. / 60 min.)

TEORETYCZNE PODSTAWY INFORMATYKI

Algorytmy i Struktury Danych, 2. ćwiczenia

Algorytmy i struktury danych. Co dziś? Tytułem przypomnienia metoda dziel i zwyciężaj. Wykład VIII Elementarne techniki algorytmiczne

Lista liniowa dwukierunkowa

Temat: Liniowe uporzdkowane struktury danych: stos, kolejka. Specyfikacja, przykładowe implementacje i zastosowania. Struktura słownika.

Laboratorium nr 7 Sortowanie

Analiza algorytmów zadania podstawowe

Algorytmy i Struktury Danych. (c) Marcin Sydow. Słownik. Tablica mieszająca. Słowniki. Słownik uporządkowany. Drzewo BST.

Struktury Danych i Złożoność Obliczeniowa

Drzewa wyszukiwań binarnych (BST)

Drzewa binarne. Drzewo binarne to dowolny obiekt powstały zgodnie z regułami: jest drzewem binarnym Jeśli T 0. jest drzewem binarnym Np.

Wykład X. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2016 Janusz Słupik

< K (2) = ( Adams, John ), P (2) = adres bloku 2 > < K (1) = ( Aaron, Ed ), P (1) = adres bloku 1 >

Egzamin, AISDI, I termin, 18 czerwca 2015 r.

Programowanie dynamiczne cz. 2

Przypomnij sobie krótki wstęp do teorii grafów przedstawiony na początku semestru.

Kompletna dokumentacja kontenera C++ vector w -

TEORETYCZNE PODSTAWY INFORMATYKI

Tadeusz Pankowski

Temat: Algorytmy zachłanne

WSTĘP DO INFORMATYKI. Drzewa i struktury drzewiaste

Wstęp do programowania. Drzewa podstawowe techniki. Piotr Chrząstowski-Wachtel

Twój wynik: 4 punktów na 6 możliwych do uzyskania (66,67 %).

KOPCE KOLEJKI PRIORYTETOWE - PRZYPOMNIENIE KOPCE WYSOKOŚĆ KOPCA KOPCE I KOLEJKI PRIORYTETOWE PROJEKTOWANIE ALGORYTMÓW I METODY SZTUCZNEJ INTELIGENCJI

Algorytmy i Struktury Danych

Stos LIFO Last In First Out

Dynamiczne struktury danych

Kody Huffmana. Konrad Wypyski. 11 lutego 2006 roku

Dynamiczny przydział pamięci w języku C. Dynamiczne struktury danych. dr inż. Jarosław Forenc. Metoda 1 (wektor N M-elementowy)

Wstęp do Programowania potok funkcyjny

Temat: Algorytm kompresji plików metodą Huffmana

Kolokwium ze wstępu do informatyki, I rok Mat. (Ściśle tajne przed godz. 10 : grudnia 2005.)

Programowanie w VB Proste algorytmy sortowania

Wstęp do programowania

Podstawą w systemie dwójkowym jest liczba 2 a w systemie dziesiętnym liczba 10.

Nierówność Krafta-McMillana, Kodowanie Huffmana

Lista 0. Kamil Matuszewski 1 marca 2016

TEORETYCZNE PODSTAWY INFORMATYKI

Algorytmy sortujące i wyszukujące

PLAN WYKŁADU BAZY DANYCH INDEKSY - DEFINICJE. Indeksy jednopoziomowe Indeksy wielopoziomowe Indeksy z użyciem B-drzew i B + -drzew

Transkrypt:

Priorytetowa

Zawartość wykładu Definicja kolejki priorytetowej proste implementacje (nieefektywne) kopiec binarny (najprostsza efektywna ) operacje kolejki priorytetowej na kopcu binarnym trik: jako zwykłej tablicy szybkie konstruowanie przykłady zastosowań rozszerzenia kolejek priorytetowych podsumowanie

Definicja Kolejki Priorytetowej Priorytetowa (ang. Priority Queue (PQ)) to abstrakcyjna struktura danych do przetwarzania elementów wraz z przypisanymi priorytetami (numerycznymi) zdefiniowana przez następujące operacje (interfejs): insert(e, p) // dodaj element e o priorytecie p do kolejki findmin() // // zwróć (bez usuwania) element o priorytecie najpilniejszym spośród przechowywanych obecnie w kolejce delmin() // //zwróć (z usuwaniem) element j.w. Każdy element ma przypisany priorytet - liczbę całkowitą. Interpretacja jest następująca: im niższa liczba tym wyższy priorytet Czasami rozważana jest odwrotna interpretacja: im wyższa liczba tym wyższy priorytet. W takim wypadku kolejkę nazywamy typu max a nazwy operacji są zmodyfikowane na findmax i delmax.

vs kolejka? Czy kolejka jest specjalnym rodzajem kolejki?

vs kolejka? Czy kolejka jest specjalnym rodzajem kolejki? Nie: bo jej zbiór operacji nie zawiera zbioru operacji kolejki (jest to po prostu inny zbiór operacji)

Kolejki Priorytetowej Proponowano wiele, coraz bardziej efektywnych i wyrafinowanych implementacji kolejki priorytetowej: naiwne (nieefektywne) implementacje (za pomocą tablic lub list dowiązaniowych) kopiec binarny (ang. Binary Heap, 1964 Williams; Floyd 1964) drzewo veb* (van Emde Boas, 1975) kopiec dwumianowy (ang. Binomial Heap, 1978 Vuillemin) Pairing Heap* (1986 Fredman, Sedgewick, Sleator, Tarjan; 2000 Iacono; Pettie 2005) kopiec Fibonacciego* (1987 Fredman, Tarjan) Thin Heap, Fat Heap * (1999 Kaplan, Tarjan), etc. * - nie omawiane w tym kursie

naiwne Jak zwykle, zaczniemy od omównienia bezpośredniej (naiwnej) implementacji kolejki priorytetowej: za pomocą tablic 1. Są 2 możliwe warianty: trzymanie priorytetów posortowanych i nieposortowanych: priorytety nieposortowane: insert: O(1), deletemin: O(n), : O(n) priorytety posortowane: insert: O(n), deletemin: O(1): : O(n log(n)) Jak widać, w obu wariantach niektóre operacje mają nieakceptowalnie wysoką złożoność. Potrzeba bardziej pomysłowej implementacji, która zapewni złożoność niższą niż liniowa. 1 za pomocą listy dowiązaniowej nie polepsza sytuacji

binarny (ang. Binary Heap) binarny jest binarnym drzewem zupełnym. Priorytety (wraz z odpowiadającymi im elementami) trzymane są w węzłach drzewa, oraz zachodzi następujący warunek porządku : Dla każdego węzła, priorytet w tym węźle jest mniejszy (pilniejszy) lub równy, priorytetom w węzłach-potomkach. Dodatkowa własność: zupełność drzewa oznacza, że kopiec wypełniany jest od góry do dołu i na każdym nowym poziomie od lewej do prawej (tzn. pierwsze wolne miejsca to zawsze skrajnie lewe wolne miejsca na ostatnim poziomie). binarny jest najprostszą znaną konkretną strukturą danych, która pozwala zaimplementować kolejkę priorytetową przy złożoności czasowej operacji nieprzekraczającej logarytmicznej.

Przykład i własności Przykład (w węzłach pokazano tylko priorytety): Obserwacje: z warunku porządku wynika, że minimalny (najpilniejszy) priorytet jest zawsze w korzeniu z w/w warunku wynika też, że priorytety na każdej ścieżce od korzenia do liścia stanowią ciąg niemalejący uwaga: priorytety na danym poziomie nie są posortowane z warunku zupełności wynika, że wysokość n-elementowego jest zawsze Θ(log(n))

Implementacja operacji kolejki priorytetowej na kopcu binarnym insert(e): dodaj nowy element e (wraz z jego priorytetem) w pierwszym od lewej wolnym węźle x ostatniego poziomu, a następnie przywróć porządek począwszy od węzła x w górę (operacja upheap) findmin(): zwróć element e znajdujący się w korzeniu delmin(): usuń element z korzenia, wstaw do korzenia element ostatni (skrajnie prawy na ostatnim poziomie ) i przywróć porządek począwszy od korzenia w dół (operacja downheap)

Przywracanie porządku za pomocą operacji upheap i downheap Operacje kolejki priorytetowej zaimplementowane są na kopcu za pomocą 2 pomocniczych operacji wewnętrznych, które mają na celu przywracanie porządku po ewentualnym jego zaburzeniu z powodu modyfikacji w węźle x: upheap(x): zaczynając od węzła x, przywróć warunek porządku podążając w górę od x downheap(x): zaczynająć od węzła x, przywróć warunek porządku podążając w dół od x Uwaga: obie operacje zakładają poprawność warunku dla wszystkich priorytetów poza węzłem x, którego priorytet ewentualnie jako jedyny może zakłócać porządek.

Przykład działania operacji insert Dodajemy do przykładowego nowy element o priorytecie 5 : Przywracamy porządek operacją upheap przesuwając nowo-dodany element w górę do momentu aż jego rodzic nie będzie większy (lub gdy dotrzemy do korzenia) 2 : Porządek został przywrócony. 2 analogia do wstawiania w algorytmie insertionsort

Przykład działania operacji deletemin 1 oryginalny kopiec (przypomnienie) 2 z oryginalnego usuwamy korzeń i zastępujemy go ostatnim węzłem w kopcu 3 Przywracamy porządek operacją downheap począwszy od korzenia zamieniając nowo-dodany element z minimum z jego obu synów, chyba że obaj synowie mają już niemniejsze priorytety (lub doszliśmy do ostatniego poziomu)

Złożoność czasowa operacji kolejki priorytetowej na kopcu binarnym rozmiar danych: liczba elementów w kopcu (n) operacja dominująca: porównanie priorytetów) Zauważmy, że operacje wykonują co najwyżej 1 (upheap) lub 2 (downheap) porównania na każdym poziomie, a więc łączna liczba porównań jest proporcjonalna co najwyżej do wysokości, która wynosi O(log(n)) Wobec tego złożoności na kopcu binarnym są następujące: insert(x): dodaj x na dole i wykonaj upheap (O(log(n))) findmin(): zwróć korzeń (O(1)) delmin(): zastąp korzeń ostatnim elementem i wykonaj downheap z korzenia (O(log(n)))

Jak zaimplementować kopiec binarny? Ogólnie można zaimplementować każde drzewo binarne (a więc i kopiec binarny) jako strukturę dowiązaniową. W przypadku każdy węzeł zawierałby: element, priorytet, oraz wskaźniki (dowiązania) do rodzica i obu synów (NULL jeśli brak). Można jednak skorzystać z własności zupełności i dzięki temu można sprytnie zaimplementować kopiec za pomocą zwykłej tablicy, co bardzo upraszcza kod operacji i oszczędza pamięć na wskaźniki.

Implementacja za pomocą tablicy Dzięki zupełności, elementy można wpisać do tablicy (pozostawiając nieużywany indeks 0) i idąc w porządku od góry do dołu i od lewej do prawej na każdym poziomie następująco, np: indeksy: 0 1 2 3 4 5 6 7 8 9 zaw. tablicy: n 2 6 3 7 12 9 4 8 10 Nawigacja w tablicy jest następująca: indeks rodzica (oprócz korzenia) jest 2 razy mniejszy, indeks lewego syna 2 razy większy, a prawego dodatkowo plus 1: parent[i] == i/2 (dzielenie całkowitoliczbowe: ucinamy ułamek) i.left == 2i, i.right == 2i + 1 (poza liścmi) np. indeks węzła zawierającego rodzica 12 to 5/2 = 2.

Pseudokod operacji upheap (zakładamy reprezentację w tablicy) upheap(i) // i > 0 key = heap[i] parent = i/2 while((parent > 0) && (heap[parent] > key)) heap[i] = heap[parent] i = parent parent /= 2 heap[i] = key

Pseudokod operacji downheap (zakładamy reprezentację w tablicy) downheap(i) l = 2i // lewy syn r = 2i + 1 // prawy syn if l <= n and heap[l] < heap[i]: min = l else: min = i if r <= n and heap[r] < heap[min]: // n to rozmiar min = r if min!= i: swap(i,min) // zamiana elementów, nie samych indeksów downheap(min) // kontynuuj niżej Uwaga: rekurencja jest tu użyta tylko, aby skrócic prezentację kodu, można to oczywiście zapisać iteracyjnie, unikając rekursji

e konstruowanie () Załóżmy, że znamy od razu n elementów, które mają być wstawione do pustej kolejki priorytetowej. Bezpośrednie wstawianie pojedynczo n razy (w przypadku ) dałoby złożoność n insert (czyli w sumie Θ(nlog(n))) Szybka operacja pozwala to zrobić efektywniej: Najpierw wstawiamy wszystkie elementy w podanej kolejności do tablicy a następnie wykonujemy następującą procedurę: for(i = n/2; i > 0; i--) downheap(i) Można udowodnić, że taka sprytniejsza procedura daje łączną złożoność czasową zaledwie O(n)

Przykładowe zastosowanie: algorytm HeapSort Oto jak można prosto posortować ciąg używając kolejki priorytetowej: (zakładamy, że pq jest obiektem reprezentującym kolejkę priorytetową) while(s.hasnext()) pq.insert(s.next()) while(!pq.isempty()) result.add(pq.delmin()) rozmiar danych: liczba elementów (n), op. dom.: porównanie złożoność czasowa: Θ(nlog(n)) Ilustruje to potęgę używania abstrakcyjnych struktur danych do upraszczania algorytmów. Uwaga: powyższy algorytm, przy użyciu, ma

Inne przykładowe zastosowania kolejek priorytetowych Kolejki priorytetowe są standardowo używane w wielu algorytmach (tzw. zachłannych) np.: obliczanie drzewa optymalnego drzewa kodowania Huffmana algorytm Dijkstry obliczania najkrótszych ścieżek w grafie algorytm Prima znajdowania minimalnego drzewa rozpinającego etc.

kolejek priorytetowych Dynamiczna kolejka (2 dodatkowe operacje): (sequence<t> s) H insert(t e) // zwraca wskaźnik do wstawionego elementu T findmin() T delmin() decreasekey(h pointer, T newpriority) // (zmniejsz priorytet danego elementu) delete (H pointer) (usuń dany element) Złączalna kolejka (wszystko powyżej i dodatkowo): merge(pq priorityqueue1, PQ priorityqueue2) // złącz podane dwie kolejki w jedną Powyższe operacje można oczywiście zaimplementować na kopcu binarnym, ale istnieją bardziej wyrafinowane implementacje, które zapewniają lepsze złożoności czasowe

Złożoność czasowa operacji kol. prior. w różnych ch Jedną z implementacji, która pozwala np. na efektywniejszą implementację operacji merge jest tzw. kopiec dwumianowy 3 Poniżej podsumowano porównanie rzędów złożoności operacji na kilku przykładach implementacji kolejki priorytetowej (w tym 2 naiwnych ): operacja nieposort. posort. kopiec binarny kopiec dwumianowy insert 1 n lg n lg n findmin n 1 1 lg n delmin n 1 lg n lg n decreasekey 1 n lg n lg n delete 1 n lg n lg n merge 1 n n lg n (wszystkie elementy otoczone są symbolem O(.)) 3 ang. binomial heap nie jest omawiany w tym wykładzie

/przykładowe zadania: definicja kolejki priorytetowej deficja dokonać analizy złożoności naiwnych implementacji kol. prior. wykonać każdą z operacji kol. prior. na podanym kopcu binarnym i pokazać na rysunku jak wygląda po tej operacji zastosować szybką procedurę do podanego ciągu elementów i narysować jak wygląda skonstruowany kopiec binarny reprezentacja tablicowa dokonać analizy złożoności czasowej operacji kol. prior. w przypadku implementacji na kopcu binarnym przykłady zastosowań kolejek priorytetowych rozszerzenia kolejki priorytetowej dokonać analizy złożoności czasowej operacji decreasekey, delete oraz merge na przypadku.

Dziękuję za uwagę