« poprzedni punkt   następny punkt »


5. Konstrukcja kopca w tablicy
 

Tworzenie tablicy reprezentującej kopiec o n elementach przy użyciu operacji insert, tzn. przez kolejne wstawiane elementów, jest dość kosztowne. Jeśli liczba elementów wynosi n, to koszt utworzenia  kopca w tablicy wynosi O(n ´ lg n). Jeżeli  liczba elementów w kopcu nie jest z góry znana, to musi to się odbyć właśnie w taki sposób. Jeśli natomiast, znamy z góry liczbę elementów w kopcu, to koszt utworzenia kopca można zmniejszyć do liniowego. Algorytm konstrukcji kopca w tablicy został przedstawiony jako procedura Construct. Procedura ta wykorzystuje proces poprawiania ścieżki, o którym była mowa w poprzednim punkcie.

Dana jest tablica TAB o n elementach. Zadanie polega na takim przeorganizowaniu elementów tej tablicy, by reprezentowała ona kopiec, tzn. chcemy by spełniona była własność częściowego uporządkowania:

("i) (2i £ n ®TAB[i] < TAB[2i]) Ù (2i+1 £ n ® TAB[i] < TAB[2i+1]).     (*)

Idea algorytmu polega na dwóch obserwacjach:

1. Połowa elementów w tablicy odpowiada liściom drzewa, a więc warunek (*) jest dla tych elementów trywialnie spełniony.

2. Jeżeli zostały utworzone kopce A i B o korzeniach na pozycjach 2i oraz 2i+1, to albo etykieta na pozycji i-tej jest mniejsza od TAB[2i], TAB[2i+1] i wtedy mamy kopiec o korzeniu na pozycji i-tej, albo tak nie jest, i wtedy trzeba poprawić jedną  ścieżkę "w dół drzewa", tak jak w algorytmie usuwania elementu minimalnego.

Algorytm konstrukcji kopca w tablicy.

Zgodnie z opisaną ideą, algorytm konstrukcji kopca w tablicy, polega na sukcesywnym poprawianiu, jeśli trzeba, częściowego uporządkowania kopców, których korzenie znajdują się kolejno na pozycjach n div 2, n div 2-1, ..., 1.

 

construct (TAB : tablica){

 k : int;                        

n := TAB.length; // n jest długością tablicy 

 k := n div 2; //na pozycjach k+1,...,n znajdują się liście budowanego kopca

 while  (k > 0) do

        DownHeap(TAB,n, k);  // utwórz kopiec o korzeniu w TAB[k]

      k := k-1;  

od;                             
      }
 

Analiza poprawności algorytmu

Niezmiennikiem pętli "while" jest tu formuła mówiąca, że na wszystkich pozycjach tablicy TAB począwszy od k+1 do n  znajdują się korzenie poprawnie zbudowanych kopców. Są to kopce jednoelementowe. Jeśli procedura DownHeap utworzy kopiec o korzeniu TAB[k],  i wykonamy instrukcję "k := k-1;", to po wykonaniu treści pętli znów spełniony jest niezmiennik. Po wykonaniu całej pętli, na pozycji 1 w tablicy TAB znajduje się korzeń kopca, którego etykietami są elementy tablicy TAB.

Koszt algorytmu

Niech n będzie liczbą elementów w kopcu, a h jego wysokością, h= ëlg(n+1)û. Oszacujemy koszt algorytmu budowy kopca w tablicy w przypadku pesymistycznym.  Przypomnijmy, że liczba porównań wykonanych przez algorytm DownHeap(TAB, x) zależy od długości drogi od wierzchołka  x od liścia i wymaga w każdym kroku co najwyżej dwóch porównań dla ustalenia właściwej zależności między etykietą wierzchołka i jego następnikami. Dla ścieżki o długości i wykonamy co najwyżej 2i porównań. Mamy:

W(n) £ S i=1,...,h  2h-i ´ 2i .

Sumowanie rozciąga się od 1 do h ponieważ rozważamy tylko wierzchołki wewnętrzne drzewa, a  2h-i odpowiada maksymalnej liczbie wierzchołków odległych o i krawędzi od liści drzewa. Po przekształceniu otrzymujemy:

W(n) = 2h+1 Si=1,...,h  2-i ´ i = 2h+1 (1 ´ 2-1 + 2 ´ 2-2 + 3 ´ 2-3 +...+ h ´ 2-h) =

2h+1 (Sj=1,...,h  (Si=j,...,h2-i) = 2h+1 (Sj=1,...,h  (Ss=0,...,h 2-(j+s)) £

2h+1 (Sj=1,...,h 2-j (Ss=0,...,+¥ 2-s) £ 2h+1 (Sj=1,...,h 2-j (1/(1-1/2)) =

 2h+2 (Sj=1,...,h 2-j ) =  2h+2 (1- 1/2h+1)/(1/2) =  2h+3 -4 = 4´2h+1 - 4 = 4n = Q(n).

Analogicznie najlepszy możliwy koszt tego algorytmu możemy oszacować przez 

Si=1,...,h 2h-i ´ 2 = 2h+1 Si=1,...,h 2-i  = 2n -1 = Q(n).

Wynika stąd, że koszt algorytmu konstrukcji kopca w tablicy jest liniowy.

Lemat 5.1  Algorytm konstrukcji kopca w n elementowej tablicy ma koszt liniowy Q(n). 

Pytanie 6: Niech A będzie kopcem o 200 wierzchołkach, a B kopcem o 127 wierzchołkach. Niech etykietami obu drzew będą liczby naturalne większe od zera. Czy drzewo postaci <A, 0, B>, powstałe z połączenia drzew A i B, jest kopcem?




« poprzedni punkt   następny punkt »