--- title: L6Z6 AISD --- ## Algorytmy i struktury danych ### Lista 6, zadanie 6 ==Marek Padlewski, 299778== :::info Niech $h(v)$ oznacza odległość wierzchołka $v$ do najbliższego pustego wskaźnika w poddrzewie o korzeniu $v$. Rozważ możliwość wykorzystania drzew binarnych, równoważonych poprzez utrzymywanie następującego warunku: $\forall v \quad h(lewy\ syn\ v) \geq ­ h(prawy\ syn\ v)$ do implementacji złączalnych kolejek priorytetowych. ::: #### Idea Kolejka priorytetowa jest strukturą przechowującą dane posiadające priorytet. Dzięki niej jesteśmy w stanie łatwo dostać się do elementu o najwyższym priorytecie. Chcemy zaimplementować tę strukturę używając kopca binarnego, pamiętając o warunku zrównoważenia drzewa podanego w treści zadania oraz tego, że żaden z synów danego wierzchołka, nie może mieć większego priorytetu niż ten wierzchołek. Taka struktura ułatwi nam łączenie kopców, a więc także łączenie kolejek priorytetowych. Aby zaimplementować taką strukturę potrzebujemy napisać metody: `delete_min`, `insert` oraz `join`. #### Algorytmy Aby usunąć element minimalny z kopca (z największym priorytetem) po prostu pomijamy korzeń drzewa i łączymy ze sobą lewe oraz prawe poddrzewo. Zwracamy ten element minimalny. ``` function delete_min(T){ min_elem = T.val join(T.left, T.right) return min_elem } ``` Aby dodać nowy wierzchołek do kopca, możemy stworzyć nowe drzewo zawierające tylko ten wierzchołek, a następnie złączyć je z drzewem do którego chcemy ten wierzchołek wstawić. ``` function insert(T, v){ T2 = drzewo zawierające tylko v join (T, T2) } ``` Aby złączyć dwa kopce, najpierw sprawdzamy który z kopców ma element o większym priorytecie w korzeniu. Oznaczmy przez $k_1$ kopiec o większym priorytecie w korzeniu, a drugi kopiec jako $k_2$. Następnie rekurencyjnie łączymy prawe poddrzewo $k_1$ z kopcem $k_2$. Wtedy w kopcu wynikowym $k$, korzeniem jest korzeń $k_1$, lewe poddrzewo to te, które ma większą wartość $h$, a prawe poddrzewo ma mniejszą wartość $h$ (aby zachować warunek z zadania). Jeśli oznaczymy korzeń kopca wynikowego jako $w$, to obliczamy dla niego wartość $h$ inkrementując wartość $h$ prawego poddrzewa, czyli $h(w) = h(w.right)+1$. ``` function join(T1, T2){ if (T1.val < T2.val){ if (T1.left == null) T1.left = T2 else if (T1.right == null) T1.right = T2 else T1.right = join(T1.right, T2) if (T1.left.h < T1.right.h) swap(T1.left, T1.right) T1.h = T1.right.h + 1 return T1 } else{ if (T2.left == null) T2.left = T1 else if (T2.right == null) T2.right = T1 else T2.right = join(T2.right, T1) if (T2.left.h < T2.right.h) swap(T2.left, T2.right) T2.h = T2.right.h + 1 return T2 } } ```