wyklad6 drukuj


Kolejki priorytetowe. Zastosowania.
Jednym z zastosowań kolejki priorytetowej typu max jest
Kolejka priorytetowa to struktura danych reprezentująca zbiór
szeregowanie zadań, na przykład na współdzielonym komputerze.
dynamiczny S, którego każdy element ma przyporządkowaną
Elementami kolejki sa zadania, które mają być wykonane. Klucze
wartość, zwaną kluczem. Na kolejce priorytetowej typu max
oznaczają priorytety zadań względem siebie. Kiedy zadanie kończy
można wykonać następujące operacje:
się lub zostaje przerwane, zadanie o największym priorytecie jest
INSERT(S, x) dodaje element x do zbioru S.
wybierane spośród zadań czekających za pomocą operacji
MAXIMUM(S) daje w wyniku element o największym kluczu.
EXTRACT-MAX. Nowe zadanie może być dodane do kolejki w
EXTRACT-MAX(S) usuwa i daje w wyniku element o
dowolnej chwili za pomocą operacji INSERT.
największym kluczu.
Kolejki priorytetowej typu min można użyć jako symulatora
INCREASE-KEY(S, x, k) zmienia wartość klucza elementu x
zdarzeń. Elementami są zdarzenia, każde z przyporządkowanym
na nową wartość k, o której zakłada się, że jest nie mniejsza
czasem wystąpienia, który służy jako klucz. Program symulacyjny
niż dotychczasowa wartość klucza.
korzysta w każdym kroku z operacji EXTRACT-MIN do wybrania
Na kolejce priorytetowej typu min można wykonać analogiczne
zdarzenia, które będzie symulował. Kiedy generowane są nowe
operacje INSERT, MINIMUM, EXTRACT-MIN i
zdarzenia, zostają one dodane do kolejki za pomocą operacji
DECREASE-KEY.
INSERT.
Funkcja HEAP-EXTRACT-MAX stanowi implementacje operacji
Kopiec jako kolejka priorytetowa.
EXTRACT-MAX. Podobnie jak w procedurze HEAPSORT,
element o największym kluczu A[1] zostaje  usuniety z kopca, a
na jego miejsce zostaje przeniesiony ostatni element A[n].
Do implementacji kolejki priorytetowej możemy użyć kopca
Następnie w tablicy A[1..n - 1] zostaje przywrócona własność
(takiego samego typu max/min). Dla prostoty będziemy
kopca typu max za pomocą MAX-HEAPIFY.
utożsamiać elementy kolejki z ich kluczami, które będziemy
przechowywać w tablicy A traktowanej jako kopiec. W sytuacji,
HEAP-EXTRACT-MAX(A, n) //n = rozmiar kopca
gdy elementami kolejki są bardziej złożone obiekty (np. rekordy),
1. begin
to w tablicy przechowujemy wskazniki do tych obiektów.
2. if n < 1
3. then error  kopiec pusty
Funkcja HEAP-MAXIMUM implementuje operację MAXIMUM w
4. else begin
czasie O(1):
5. max := A[1];
HEAP-MAXIMUM(A)
6. A[1] := A[n];
1. begin
7. n := n - 1;
2. return A[1];
8. MAX-HEAPIFY(A, n, 1);
3. end;
9. return max;
10. end;
9. end;
Czas działania funkcji HEAP-EXTRACT-MAX wynosi O(log n),
HEAP-INCREASE-KEY(A, i, k)
ponieważ wykonuje ona stałą ilość operacji elementarnych poza
1. begin
procedurą MAX-HEAPIFY w wierszu 7, która działa w czasie
2. if k < A[i]
O(log n).
3. then error  nowy klucz jest mniejszy niż klucz aktualny
4. else begin
Procedura HEAP-INCREASE-KEY jest implementacją operacji
5. A[i] := k;
INCREASE-KEY. Element, którego klucz ma zostać zwiększony,
6. while i > 1 i A[parent(i)] < A[i] do
jest określony przez indeks i w tablicy.
7. begin
Na początku procedury klucz A[i] przyjmuje nową wartość.
8. zamień A[i] z A[parent(i)];
Ponieważ zwiększenie klucza mogło naruszyć własność kopca typu 9. i := parent(i);
max, zatem przechodzimy ścieżkę od tego węzła w kierunku 10. end;
korzenia w celu znalezienia właściwego miejsca dla nowego, 11. end;
zwiększonego klucza (porównaj z pętlą w wierszach 6-10 procedury 12. end;
INSERTION-SORT).
HEAP-INCREASE-KEY(A, 9, 10) dla A = [12, 9, 7, 8, 5, 6, 2, 1, 3, 4].
i=9, k=10
Liczba iteracji pętli while jest nie większa niż długość ścieżki od
węzła uaktualnianego w wierszu 5 do korzenia, która jest nie
12 12
większa niż wysokość kopca, czyli log n . Zatem czas działania
9 7 9 7
procedury HEAP-INCREASE-KEY na n-elementowym kopcu
wynosi O(log n).
8 5 6 2 8 5 6 2
Poprawność procedury HEAP-INCREASE-KEY można wykazać,
1 3 4 1 10 4
korzystając z następującego niezmiennika pętli:
Podczas każdego sprawdzania warunku wejścia do pętli while w
12 12
wierszu 6 tablica A[1..n] spełnia własność kopca typu max z co
9 7 10 7
najwyżej jednym wyjątkiem: A[i] może być większe niż
A[parent(i)].
10 5 6 2 9 5 6 2
1 8 4 1 8 4
Inicjowanie: Tablica wejściowa jest kopcem typu max. Po zmianie
Procedura MAX-HEAP-INSERT jest implementacją operacji
wartości A[i] na wartość większą w wierszu 5 może być
INSERT. Jej argumentami są tablica A, rozmiar kopca n oraz klucz
A[i] > A[parent(i)], a w pozostałych węzłach zostaje zachowana
k nowego elementu, który ma być dodany do kopca. Najpierw
własność kopca.
dodajemy nowy liść o kluczu -", a następnie za pomocą
Utrzymanie: Załóżmy, że niezmiennik jest prawdziwy przed
HEAP-INCREASE-KEY zmieniamy wartość klucza na właściwą i
sprawdzeniem warunku, który jest spełniony. Wtedy
odtwarzamy własność kopca typu max.
A[parent(i)] < A[i] i po zamianie A[i] z A[parent(i)] w wierszu 8,
w węzle i będzie spełniona własność kopca typu max. Ponieważ MAX-HEAP-INSERT(A, n, k)
wartość A[parent(i)] zmieniła się na większą, więc własność kopca 1. begin
w węzle parent(i) mogła zostać utracona. Pozostałe węzły nadal 2. n := n + 1;
spełniają własność kopca. Zamiana i na parent(i) powoduje, że 3. A[n] := -";
niezmiennik będzie prawdziwy przed kolejnym sprawdzeniem 4. HEAP-INCREASE-KEY(A, n, k);
warunku w wierszu 6. 5. end;
Zakończenie: Podczas ostatniego sprawdzania warunek w wierszu Czas działania funkcji MAX-HEAP-INSERT wynosi O(log n),
6 nie jest spełniony, to znaczy, że i = 1 lub A[i] d" A[parent(i)]. W ponieważ wykonuje ona stałą ilość operacji elementarnych poza
obu przypadkach na mocy niezmiennika własność kopca typu max procedurą HEAP-INCREASE-KEY w wierszu 4., która działa w
jest spełniona dla każdego węzła tablicy A[1..n] nie będącego czasie O(log n).
korzeniem.
Podsumowanie.
MAX-HEAP-INSERT(A, 10, 10).
12 12
9 7 9 7
8 5 6 2 8 5 6 2
Implementacja w postaci kopca umożliwia wykonanie wszystkich
1 3 4 -"
1 3 4 10
operacji kolejki priorytetowej na zbiorze n-elementowym w czasie
O(log n).
12 12
9 7 10 7
8 10 6 2 8 9 6 2
1 3 4 5 1 3 4 5


Wyszukiwarka