• Nie Znaleziono Wyników

Algorytmy i Struktury Danych, 8. ćwiczenia

N/A
N/A
Protected

Academic year: 2021

Share "Algorytmy i Struktury Danych, 8. ćwiczenia"

Copied!
5
0
0

Pełen tekst

(1)

Algorytmy i Struktury Danych, 8. ćwiczenia

2015-11-20

1 Ukryty słownik

(BKR) Cyklicznym blokiem nazywamy dowolną tablicę S[i, . . . , j], której warto- ści spełniają następujący warunek:

istnieje indeks k, i ≤ k ≤ j, taki, że:

S[k] < S[k + 1] < . . . < S[j] < S[i] < . . . < S[k − 1]

Tablicę S[1..n] o wartościach ze zbioru L nazywamy tablicą cyklicznych bloków, jeśli spełnione są następujące dwa warunki:

• każdy blok jest cyklicznym blokiem,

• wszystkie elementy bloku i − 1 są mniejsze niż wszystkie elementy bloku i dla 2 ≤ i ≤ h, gdzie h jest maksymalnym numerem bloku.

Wykaż, że używając struktury danych tablic cyklicznych bloków operacje access można wykonać za pomocą 2 log n porównań, a operacje insert i delete za pomocą O(√

n log n) instrukcji (n oznacza liczbę elementów w zbiorze S).

• organizujemy tak, tablicę, żeby i–ty blok miał długość i (ewentualnie oprócz ostatniego).

• access — wyszukaj binarnie odpowiedni blok, w bloku wyszukujemy prze- suniecie k, i binarnie wyszukujemy wewnątrz bloku,

• insert — wyszukaj odpowiedni blok (log n), jeśli to nie jest ostatni blok, to trzeba zrobić miejsce na nowy elementy — wyrzucając największy, naj- większy element trzeba przesunąć do następnego bloku (√

n), z którego wypada kolejny element, itd. (√

n razy, ponieważ nie trzeba już nic prze- suwać jedna faza kosztuje log n).

• delete — podobnie.

2 2-3 drzewa

2-3 drzewa to drzewa zrównoważone o następujących własnościach:

• każdy węzeł przechowuje 1 lub 2 klucze,

• każdy węzeł wewnętrzny (oprócz korzenia) ma 2 lub 3 synów,

(2)

• wszystkie liście mają tą samą głębokość,

• zachowany jest porządek kluczy w poddrzewach (mniej więcej jak w drze- wach BST),

Wstawienia do drzewa:

• znajdujemy liść w którym powinien znaleźć się nowy klucz, dodajemy go do węzła,

• może się okazać, że węzeł posiada chwilowo 3 klucze, w takim wypadku dzielimy go na dwie części (w każdej z nich zostawiamy jeden klucz) a trzeci klucz przekazujemy poziom wyżej,

• tak długo jak drzewo zawiera węzeł z 3 kluczami powtarzamy tą procedurę.

Usuwanie z drzewa:

• jeśli klucz leży w węźle wewnętrznym, to zamieniamy go z następnikiem (lub poprzednikiem), i redukujemy problem do usuwania z liścia,

• jeśli klucz leży w liściu, to usuwamy go z węzła,

• jeśli okazuje się, że jakiś węzeł zawiera 0 kluczy, to poprawiamy drzewo idąc od tego węzła do korzenia i próbując zastąpić puste miejsce kluczem pożyczonym od sąsiadów,

Scalanie (zakładamy, że klucze są przetrzymywane w węzłach):

• dane są drzewa T1, T2,

• usuwamy z T2najmniejszy klucz x,

• znajdujemy w T2węzeł v którego poddrzewo ma wysokość |T2|,

• dodajemy do v klucz x z prawym poddrzewem T2,

• jeśli v zawiera 3 klucze, to poprawiamy warunku 2-3 drzewa idąc od v do korzenia.

Złożoność O(log(|T1| + |T2|)).

Scalanie (zakładamy, że klucze są przetrzymywane w liściach):

• jeśli h1 = h2, to tworzymy trzewo T z wartością węzła max(T1.root), lewym poddrzewem T1, prawym poddrzewem T2,

• jeśli h1 > h2, to znajdujemy na skrajnie prawej ścieżce T1, węzeł v o wysokości h2+ 1, dodajemy do v nową wartość z węzła min(T2.root) i podłączamy T2jako skrajnie prawe poddrzewo, jeśli w wyniku tej operacji węzeł v ma 3 wartości, to poprawiamy drzewo idąć od v do korzenia,

• jeśli h1 < h2, to postępujemy analogicznie jak w poprzednim przypadku (ale dodajemy T1 do T2 i szukamy węzła na skrajnie lewej ścieżce).

Złożoność O(1 + |h1− h2|) = O(log(|T1| + |T2|)).

Split (zakładamy, że klucze są przetrzymywane w liściach) – podział drzewa T na dwa poddrzewa T1 (z kluczamy ≤ x) i T2 (z kluczamy > x):

(3)

• szukamy ścieżki od korzenia do liścia w którym należałoby wstawić klucz x, węzły na tej ścieżce oznaczamy przez v0= root, v1, . . . , vk,

• likwidujemy węzły v0, . . . , vk−1, a węzeł vkrozbijamy na dwa węzły (jeden z wartościami ≤ x, drugi z wartościami > x),

• drzewo rozpada się na dwa lasy F (drzewa z wartościami ≤ x), i F>

(drzewa z wartościami > x),

• scalamy drzewa F wg. rosnących wysokości otrzymując T1,

• scalamy drzewa F> wg. rosnących wysokości otrzymując T2,

3 Pokazać, że przy pomocy rotacji można zawsze przejść z jednego BST do drugiego

Za pomocą rotacji możemy dowolne drzewo BST zamienić na listę (i na odwrót).

Wstarczy tak długo jak drzewo zawiera węzeł z lewym synem, wykonujemy na nim (i lewym synie) prawą rotację.

4 ASD Zadania — wzbogacanie struktur danych

Zadanie 3.24

Zaprojektuj strukturę danych umożliwiającą wykonywanie w czasie O(log n) następujących operacji na zbiorze S:

• makeset(S) :: S := ∅

• insert((x, y), S) :: S := S ∪ {(x, y)}

• minx(S) :: usunięcie z S pary (x, y) o najmniejszej pierwszej składowej,

• miny(S) :: usunięcie z S pary (x, y) o najmniejszej drugiej składowej,

• searchx(x, S) :: wyznaczenie takiej pary (a, b) ∈ S, że x = a,

• searchy(y, S) :: wyznaczenie takiej pary (a, b) ∈ S, że y = b.

Rozwiązanie: dwa drzewa AVL (jedno ze współrzędnymi x, drugie ze współ- rzędnymi y), dodatkowo każdy węzeł trzyma dowiązanie do odpowiadającego mu węzła w drugim drzewie.

Zadanie 3.25

Zaprojektuj strukturę danych umożliwiającą wykonywanie w czasie O(log n) następujących operacji na zbiorze S:

• construct(S) :: utworzenie ciągu pustego S,

• insert(S, x) :: S := S ∪ {(x)},

• delete(S, x) :: S := S − {(x)},

(4)

• search(S, x) :: sprawdzenie, czy x znajduje się w zbiorze S,

• elem(S, i) :: wyznaczenie i–tego co do wielkości elementu zbioru S,

• numb(S, x) :: wyznaczenie numeru elementu x w zbiorze S (względem wielkości).

Rozwiązanie: drzewo AVL z atrybutami rozmiar poddrzewa.

Zadanie 3.26

Zaprojektuj strukturę danych do wykonywania ciągów następujących operacji (dla elementów x pochodzących z dowolnego zbioru liniowo uporządkowanego):

• initialization :: Si= ∅ dla i = 1, 2, . . . , n,

• insert(Si, x) :: Si := Si∪ {(x)}, pod warunkiem, że x nie występuje w żadnym zbiorze Sj, 1 ≤ j ≤ n,

• deletemin(Si) :: usunięcie ze zbioru Si najmniejszego elementu,

• f ind(x) :: wyznaczenie numeru zbioru do którego należy element x.

Rozwiązanie: Sijako zwykłe kopce, dodatków utrzymujemy słownik par (x, numerzbioru)

Zadanie 3.27

Zaprojektuj strukturę danych umożliwiającą wykonywanie w czasie O(log n) następujących operacji na ciągu S:

• construct(S) :: utworzenie ciągu pustego S,

• insert(S, i, x) :: wstawienie x na i-te miejsce w ciągu S, tzn. Si= x pod warunkiem, że i ≤ |S| + 1,

• sum(S, i, j) :: obliczenie sumyPj k=iSk,

Rozwiązanie: AVL z dodatkowym atrybutem suma elementów poddrzewa.

Zadanie 3.28

Rozwiązanie: AVL z atrybutem rozmiar poddrzewa.

Zadanie 3.29

Zaprojektuj strukturę danych umożliwiającą wykonywanie w czasie O(log n) następujących operacji na zbiorze S zawierającym przedziały liczb rzeczywistych [l, r]:

• empty(S) :: S = ∅,

• add(S, I) :: S = S ∪ {I},

• delete(S, I) :: S = S − {I},

(5)

• is(S, x) :: sprawdzenie czy element x należy do jakiegoś przedziału w zbioru S;

• intersect(S, I) :: sprawdzenie czy przedział I ma niepuste przecięcie z jakimś przedziałem należącym do S.

Rozwiązanie: Utrzymujemy słownik z parami (x, z) (gdzie x to liczba rzeczy- wista, a z +1 lub -1). Dodatkowo każdy węzeł ma dodatkowy atrybut suma oznaczający sumę wartości z w poddrzewie. Możemy w takim drzewie w czasie O(log n) obliczyć sum(q) oznaczającą sumę wszystkich atrybutów z par (x, z), takich, że x ≤ q.

• add(S, I) – dodajemy do słownika pary (l, +1) i (r, −1),

• delete(S, I) – usuwamy ze słownika pary (l, +1) i (r, −1),

• is(S, x) – jeśli słownik zawiera pary (x, +1) lub (x, −1) to zwracamy true, wpp. obliczamy sum(x) i jeśli suma jest > 0 to zwracamy true, jeśli sum(x) ≤ 0, to zwracamy f alse.

• intersect(S, I), jeśli is(S, l) lub is(S, r) to zwracamy true, jeśli istnieje w słowniu para (x, z), t.że l ≤ x ≤ r, to zwracamy true, wpp zwracamy f alse.

5 Drzewa czerwono-czarne

Cormen, Rozdział 13, strony 273–301.

Cytaty

Powiązane dokumenty

Rozwiązanie: Wzbogacamy węzły kopca o atrybut countEq oznaczającą liczbę węzłów w poddrzewie zawierających identyczną wartość co ten zapisany w klu- czu. Dzięki

Zaprojektuj optymalny algorytm pod względem pesymistycznej liczby porów- nań, który znajduje dwa środkowe elementy w zbiorze czterech elementów.. Chcemy ją uporządkować tak,

Udowodnij, że jeśli algorytm sortujący tablicę A[1..n] porównuje i zamienia wy- łącznie elementy odległe co najwyżej o 2015 (tzn. jeśli porównuje A[i] z A[j], to.. |i-j|

[r]

Jeśli graf nie jest regularny, to należy dodać nowe krawędzie i ewentualnie wierz- chołki tak by przerobić go na regularny.. Algorithm

Algorytmy i Struktury

Wstarczy tak długo jak drzewo zawiera węzeł z lewym synem, wykonujemy na nim (i lewym synie) prawą

• v należy do poddrzewa p.right, jednak zauważmy, że liczba kroków tego typu nie może przekroczyć O(log n). 3