You are on page 1of 58

ALGORYTMY i STRUKTURY DANYCH

Dr in. Dokimuk Jerzy


KAE (K-26), gmach A11, IVp. pok. 409, tel. 042-631-2666
jdokimuk@p.lodz.pl
1.
2.
3.
4.

Pojcie algorytmu: klasyfikacje, metody zapisu, operacje dominujce, przykady.


Analiza algorytmw: pojcie zoonoci, notacje, klasa algorytmu, opis matematyczny.
Rekurencja: definicje, problemy, typy rekurencji.
Projektowania algorytmw: dziel i zwyciaj, programowanie dynamiczne, algorytmy
zachanne, algorytmy z powrotami.
5. Sortowanie: przez wstawianie, bbelkowe, Shella, QuickSort, przez zliczanie, pozycyjne,
kubekowe, i inne, drzewa decyzyjne.
6. Wyszukiwanie wzorca: Brute Force, Knutha-Morrisa-Pratta, Rabina-Karpa.
7. Haszowanie: idealna funkcja haszujca, kolizje, haszowanie acuchowe.
8. Abstrakcyjne struktury danych: stos, kolejka, lista, przykady implementacji i zastosowa.
9. Drzewa: binarne, BST, wstawianie/usuwanie kluczy, przechodzenie, rwnowaenie,
algorytm DSW, drzewa AVL.
10. Kopiec: operacje, implementacja, sortowanie przez kopcowanie, zastosowanie.
11. Bdrzewa: tworzenie, wstawianie i usuwanie kluczy.
12. Grafy: definicje, przeszukiwanie BFS/DFS, algorytm Kruskala, Dijkstry.
13. Wstp do kompresji danych: kodowanie prefiksowe, metoda Huffmana.
14. Zarys Problemw NP - zupenych

LITERATURA
[1] Cormen T. H., Leiserson C. E., Rivest R. L.: Wprowadzenie do algorytmw.
WNT, Warszawa, 2006.
[2] Drozdek A.: C++. Algorytmy i struktury danych. Helion, Gliwice, 2004.
[3] Neapolitan R., Naimipour K.: Podstawy algorytmw z przykadami w C++.
Helion, Gliwice, 2004.
--------------------------------------------------------------------------------------------------------------------------[4] Harris S., Ross J.: Od podstaw Algorytmy. Helion, Gliwice, 2006.
[5] Adamski T., Ogrodzki J.: Algorytmy komputerowe i struktury danych. PW, Warszawa 2005
[6] Drozdek A., Simon D. L.: Struktury danych w jzyku C. WNT, Warszawa, 1996.
[7] Sedgewick R.: Algorytmy w C++. RM, Warszawa, 1999.
[8] Sedgewick R.: Algorytmy w C++. Grafy. RM, Warszawa, 2003.
[9] Aho Alfred V., Hopcroft John E., Ullman Jeffrey D.: Projektowanie i analiza algorytmw. Helion,
Gliwice, 2003 (1974).
[10] Wrblewski P.: Algorytmy, struktury danych i techniki programowania. Helion, Gliwice, 2003.
[11] Wirth N.: Algorytmy+struktury danych=programy. WNT, Warszawa, 1989.
[12] Banachowski L., Diks K., Rytter W.: Algorytmy i struktury danych. WNT, Warszawa, 1996.
[13] Syso M. M.: Algorytmy. Wydawnictwa szkolne i pedagogiczne, Warszawa, 1997.

Algorytmy i Struktury Danych wykad

1. POJCIE ALGORYTMU
Pojcie algorytm zwizane jest z nazwiskiem perskiego matematyka Muhammada Ibn Musa
Al Chorezmi (IX w), ktry poda reguy wykonywania operacji arytmetycznych na liczbach
dziesitnych. Jego praca zostaa w XII wieku przetumaczona na acin.
Pierwszym algorytmem by przepis znajdowania najwikszego wsplnego podzielnika /NWD/
dwch liczb naturalnych a i b, podany przez Euklidesa (365 -300 p.n.e.).
Algorytm: uporzdkowany zbr operacji, ktrych wykonanie udostpnia rozwizanie zadania z
okrelonej klasy zada.
Algorytm jest cile okrelon procedur obliczeniow, ktra dla waciwych danych Wejciowych generuje oczekiwane dane Wyjciowe (zwane te wynikami).
Rozwizanie okrelonego problemu obliczeniowego polega na sprecyzowaniu wymaga odnonie relacji danych Wejciowych i Wyjciowych.
Algorytm opisuje stosown technik obliczeniow, ktra realizuje relacj We/Wy.
Specyfikacja: dokadny opis zadania lub problemu do rozwizania, obejmujcy:
Dane: dla postawionego zadania i warunki, ktre musz spenia,
{a ( x ), a2 ( x ) L} dla x > 0
Wyniki: z uwzgldnienie relacji do danych np.: f ( x ) = 1
Error dla x 0
Wskazane jest zamieszczenie penej specyfikacji problemu przed podaniem algorytmu.
Opracowujc algorytm zakada si poziom szczegowoci, bdcy podstaw algorytmu.
Na wstpie naley sprawdzi, czy zadanie jest jednoznaczne rozwizywalne.
Algorytm powinien uwzgldnia wszystkie moliwe teoretyczne warianty
oblicze, wynikajce z rnorodnoci danych Wejciowych.

Cztery cechy algorytmu


Oglno:
powinien rozwizywa zadania okrelonej klasy a nie pojedyncze przypadki.
Skoczono: uzyskanie rozwizania zadania w skoczonej liczbie krokw.
Skoczono algorytmu warunkowana jest jednoznacznie podanym
warunkiem zakoczenia ptli iteracyjnej jak te prawidowym zdefiniowaniem cigu wywoa rekurencyjnych. Moe by badana w trakcie
testowania programu (czy program zatrzymuje si na danych testowych).
Okrelono: kady krok algorytmu musi by jednoznacznie okrelony.
Efektywno: czas wykonania (np. liczba operacji) lub zapotrzebowanie na pami.
Poprawno: naley dowie e (cechy dowodu twierdze matematycznych):
kade wykonanie algorytmu dla danych zawartych w specyfikacji DANE, ktre
dobiegnie do koca, udostpni wynik, speniajcy warunek
kocowy (podany w specyfikacji jako Wynik).
dla kadych poprawnych danych obliczenia w algorytmie skocz si.
Poprawno algorytmu wi si z poprawnoci dziaania programu, bdcego jego realizacj.
W programie mog wystpi bdy: skadniowe lub logiczne.
Bdy logiczne sprawiaj, e dla poprawnych danych wejciowych program generuje ze wyniki.
Najgorszymi bdami s bdy w algorytmach, automatycznie przenoszone do programw.
Algorytm szeregowy: wykonuje instrukcje sekwencyjnie, jedna po drugiej, wg kolejnoci okrelonej
grafami przepywu tzn. t(koniec( oi )) # t(pocztek ( oi+1 )). (
czytaj: dla kadego)
i[1,n ]

Oznaczenia: n liczba operacji w algorytmie; oi - i-ta operacja; t(x) chwila wykonania operacji x.
Kolejno wykonywania operacji ponumerowana jest od 1 do n wcznie.
Algorytm rwnolegy: moliwo wykonywania jednoczenie rnych operacji (instrukcji) w tej
samej chwili czasowej tzn.
t(koniec( oi )) > t(pocztek ( oi+1 )). ( czytaj: istnieje)
i [1, n ]

Algorytm: liniowy (bezwarunkowa lista krokw), -z rozgazieniami (spenienie warunkw okrela kolejno).

Instytut Aparatw Elektrycznych


Algrm1
Dr J. Dokimuk

Algorytmy i Struktury Danych wykad

1.1. Metody zapisu algorytmu


Jzyk naturalny -prostota, obszerne sownictwo, maa precyzja, moliwo bdnej interpretacji.
Algorytmu testowania parzystoci liczby nieujemnej:
Zmniejsz jej warto o 2 tak dugo, a otrzymasz warto 0 lub 1.
Wynik 0 oznacza liczb parzyst za 1 liczb nieparzyst.

START

Schemat blokowy
Graficzny, sformalizowany zapis algorytmu, trudnoci w
fizycznej prezentacji duych problemw
Wykorzystuje si zazwyczaj nastpujce bloki:
pocztek i koniec algorytmu;
operacyjny zawiera opisy operacji na danych;
decyzyjny okrela kierunek sterowania.

dane wejsciowe
zwieksz

operacja

warunek

KONIEC

Instytut Aparatw Elektrycznych


Algrm1
Dr J. Dokimuk

R1.1

Funkcje rekurencyjne gdy problem mona przedstawi za pomoc zapisu rekurencyjnego.

dla n = 0
1
n! =
n ( n 1)! dla n > 0

dla n < 2
n
Fib(n)=
Fib(n 2 ) + Fib(n1) dla n 2

Jzyki formalne lub pseudojzyki jzyk programowania lub specjalnie stworzona notacja.
1.
2.
3.
4.
5.
6.
7.
8.
9.

ptle iteracyjne while - do, for - do, repeat, instrukcje warunkowe if, then, else
// pocztek komentarza a do koca wiersza
a
b; oznacza przypisanie wartoci wyraenia z prawej strony do lewej strony.
Dopuszczalne s podstawienia wielokrotne a
b
c,
uyte zmienne s lokalne w procedurze (zmienne globalne zaznaczane s sowem global),
A[i] jest i-tym element tablicy A; A[3k] jest podtablic zoon z elementw A[3] A[k],
dugo tablicy okrela si piszc length(A),
parametry do procedury przekazywane s przez warto.
struktur blokow sygnalizuje si poprzez wcicia.

Liniowe przeszukiwanie wektora


Dane: wektor X[1..n] zawierajcy n liczb; key -poszukiwany
Wynik: zmienna OK zwracajca indeks lub -1 gdy brak klucza
i1
X[n+1]  key
// wartownik
while X[i] <> key do i  i + 1
if ( i n ) then OK  i else OK  1

Location(int n, type a, X[ ] )
{
index loc= 1;
while (loc <=n && X[loc] != a)
loc ++;
if (loc > n) return -1;
else return loc;
}

Lista krokw kolejne kroki zawieraj opis czynnoci wykonywanych przez algorytm.
Poszukiwanie elementu w wektorze
Dane: wektor X[pk] ze zbiorem elementw; warto poszukiwanego element key.
Wynik: wskanik m okrelajcy pozycj elementu w X (m= -1 jeeli brak elementu w X)
Krok 0: Wprowad elementy do wektora X
//mona pomin
//wstawienie wartownika na koniec
Krok 1: xl+1 = key
Krok 2: i = p
Krok 3: Czy xi = key?, jeeli tak to KONIEC, jeeli nie id do 4
Krok 4: i = i + 1 id do 3
KONIEC:
// Jeeli m=l+1 to m = -1 co oznacza, e wektor X nie zawiera elementu key

Instytut Aparatw Elektrycznych


Algrm1
Dr J. Dokimuk

Algorytmy i Struktury Danych wykad

Algorytm drzewiasty (drzewo decyzyjne)


Forma schematu blokowego, przyjmujca posta drzewa. Kade dwie drogi maj tylko wsplny
pocztek i dalej nie spotykaj si.
Przydatny do wyznaczania liczby wykonywanych operacji.
Elementy drzewa: korze wierzchoek rozpoczynajcy algorytm,
gazie poczenia w drzewie (krawdzie),
licie wierzchoki kocowe, odpowiadaj wynikom dziaania algorytmu.

Projektowanie algorytmu nie jest czynnoci prost, gdy brak jest uniwersalnych
regu jego tworzenia

1.3. Przykady
Przykad 1.1. Schemat Hornera (1819 r.) - warto wielomianu n-go stopnia w zadanym punkcie.
f(n,x) = anxn + an-1xn-1 + + a2x2 + a1x + a0
f(n,x) = (((anx + an-1)x + an-2)x + + a1)x + a0

f ( n , x) :=

w an

Dane: a0, a1,,an wspczynniki; z argument.


Wynik: warto wielomianu dla zadanego argumentu.

for i n 1 .. 0
fw

i = n - 1,,1, 0

w = wz + ai
f(z) = w

g(n,x) = (b0xn-1 + b1xn-2 + + bn-1)x + bn = g(n-1,x)x + bn


Przykad 1.2. Maksymalna warto wektora.

w w x + ai

w = an

1. przyjmij wspczynnik an za warto pocztkow,


2. biec warto wielomianu pomn przez z,
3. dodaj kolejny wspczynnik wielomianu,
4. powtarzaj 23 do wyczerpania lwspczynnikw.

g(n, x) :=

bn if n 0
g(n 1 , x) x + bn if n > 0

y = max {xi } dla i [1, n]

Dane: wektor X zawierajcy n liczb


Wynik: najwikszy element w wektorze X
1. przyjmij za max 1-szy element w zbiorze X;
2. dla wszystkich kolejnych elementw wykonuj czynnoci:
jeeli i-ty element > max to za max przyjmij ten element

Jedn z regu jest upraszczanie algorytmu tak, aby uzyska maksymalnie prost, krtk i
czyteln posta, w ktrej atwo bdzie wyodrbni niezalene fragmenty.
1.2. Pojcie zoonoci obliczeniowej
Zoono obliczeniowa algorytmu: liczba zasobw komputerowych, potrzebnych do jego wykonania.
Zoono pesymistyczna liczba zasobw komputerowych potrzebnych przy najgorszych
danych wejciowych o okrelonym rozmiarze n.
Zoono oczekiwana liczba zasobw komputerowych potrzebnych dla typowych danych
wejciowych o okrelonym rozmiarze n.
Rozmiar danych wejciowych nie jest pojciem jednoznacznym i zaley od problemu.
Dla sortowania rozmiarem danych jest liczba elementw w zbiorze do posortowania.
W analizie efektywnoci mnoenia liczb cakowitych, najbardziej wiarygodnym rozmiarem
jest liczba bitw potrzebnych do przechowywania tych liczb.

// zapis w pseudokodzie
max  X[1]
for i  2 to n do
if X[i] > max then max  X[i]
procedure MaxVec (n: integer; var X:vec; var Max:real;);
var i: integer; max: real;
begin
max := X[1]
for i:=2 to n do if X[i] > max then max:=X[i]
Max:=max;
end;

Rwnolegle z pojciem zoono obliczeniowa, uywane jest pojcie pokrewne:


-efektywno algorytmu, odnoszce si do zoonoci w sensie praktycznym.
Wystpuje gdy porwnujemy rne algorytmy rozwizujce ten sam problem
lub przy praktycznej ocenie przydatnoci okrelonych algorytmw.
Algorytm A1 jest efektywniejszy od A2 chocia oba maja zoono obliczeniow klasy O(n2).
Efektywno algorytmu: czas jego wykonania oraz zapotrzebowanie na pami operacyjn.
Efektywno czasowa: liczba wykona poszczeglnych operacji algorytmu, niezalenie od
zastosowanego komputera czy rodowiska programistycznego.
Czas wykonania algorytmu jak i jego zapotrzebowanie na pami zale od:
-rozmiaru,
-rodzaju danych wejciowych.
Stosujc ulepszon metod sortowania bbelkowego dla dwch zbiorw danych:
[1,5,8,9,3] oraz [9,8,5,3,1], szybciej bdzie posortowana lista pierwsza
Zoono czasowa powinna by niezalena od komputera, jzyka programowania lub
sposobu kodowania, dlatego wyrnia si w algorytmie charakterystyczne operacje zwane
operacjami dominujcymi, ktrych czna liczba jest proporcjonalna do liczby wykona
wszystkich operacji jednostkowych dla dowolnej realizacji algorytmu.
Dla algorytmw sortowania operacjami dominujcymi s:
porwnywanie elementw,
przestawianie elementw.
Dla algorytmw numerycznych, operacje dominujce to operacje arytmetyczne +, -, * /.
Jednostka zoonoci czasowej: czas wykonania jednej operacji dominujcej.
Algorytm optymalny: bezwzgldnie najlepszy algorytm (z dostpnych), dla danego problemu.

Algorytmy i Struktury Danych wykad

R1.2

Sortowanie 3elementowego zbioru X = { x1, x2, x3 }


1-sze porwnanie x1<x2 sortuje podzbir {x1, x2}.
Nastpnie wstawiamy x3 w odpowiednie miejsce
wzgldem x1 i x2.
Wynik sortowania: stan (1a i 1b) po 2-ch porwnaniach
pozostae: po 3-ch porwnaniach
Wysoko drzewa: najwiksza odego od korzenia do
wierzchoka kocowego, jest to te najwiksza
Rys.1.2. Przykad drzewa decyzyjnego
liczba operacji wykonanych w algorytmie.
Dla algorytmu sortujcego (przez porwnanie) n rnych kluczy, drzewo decyzyjne zawiera n! lici.

Instytut Aparatw Elektrycznych


Algrm1
Dr J. Dokimuk

Zoono: liczba porwna Pr = n - 1


Przykad 1.3. Rozpito wektora.
Rozpito: r = max{xi } - min{xi } dla i [1, n].

1.
2.
3.
4.
5.
6.

Dane: wektor X zawierajcy n liczb.


Wynik: rozpito wektora X.
pocz elementy wektora w pary,
porwnaj elementy w parach,
wartoci mniejsze umie w wektorze Xmin,
wartoci wiksze umie w wektorze Xmax,
znajd max w wektorze Xmax jak poprzednio,
znajd min w wektorze Xmin jak poprzednio.

Rys. P1.2. Warto maksymalna


MinMax(int n; type X[ ], min, max)
{
index i;
min = max =X[1];
for (i = 2; i <= n; i++)
if (X[i] < min) min = X[i];
else if (X[i] > max) max = X[i];
}

>

8
6

>

>

>

>

>

>

Rys. P1.3. Algorytm poszukiwania maksimum

Zoono: liczba porwna dla n parzystego:

Pr = n/2 + 2*(n/2 - 1) = 1.5n - 2

Dla liniowego poszukiwania liczba porwna:

Pr = 2 * (n - 1) = 2n 2 (lub 2n - 3)

Algorytmy i Struktury Danych wykad

Przykad 1.4. Miejsce zerowe funkcji cigej jednej zmiennej.


Dane: przedzia (a, b), zawierajcy jedno miejsce zerowe.
Wynik: warto, dla ktrej funkcja przyjmuje warto zero.

NWD(16, 8) = 8, NWD(90, 135) = 45, NWD(46, 48) = 2, NWD(16, 28) = 4


Wasnoci: NWD(0,0) = 0, NWD(a, b) = NWD(b, a), NWD(a, 0) = a.

Przykad 1.4b - SORT1a


Find the smallest key and exchange it
with the first key.
Then find the second smallest key and
exchange it with the second key,
end so on.

Przykad 1.5. Mnoenie dwch macierzy.


Dane: Macierze A [n x m] i B [m x r], (liczba kolumn macierzy A musi by rwna liczbie wierszy macierzy B).

Przykad:

a11
a 21

a12
a 22

b
a13 11
b
a 23 21
b31

b12
c
b22 = 11
c
b32 21

gdzie ci , j = ai ,k bk , j , dla i=1,2,...,n ;


c12
gdzie cij = a i1 + a i 2 b2 j + a13b3 j
c 22

MultiplyMat(A, B)
if col[A] row[B] then return Error Bd wymiarw
for i  1 to row[A] do
for j  to col[B] do
C[i,j]  0
for k  1 to col[A] do C[i,j]  C[i,j]+A[i,k]@B[k,j]
return C
procedure macMult(m n,r: integer; var A, B, C:mac);
var i, j, k: integer;
begin
for i:=1 to m do
for k:=1 to r do
begin
C[i,k]:=0;
for j:=1 to n do C[i,k] := C[i,k] + A[i,j]*B[j,k];
end;
end;

j=1,2,...r.

k =1

cij=0
k=1
cij=cij+aijbjk

i=i+1

i>m

k>r

j>n

Algorytm Euklidesa NWD wystpuje pod nazw gcd(a, b) (greatest commom divisor).
Mona zbudowa algorytm NWD na bazie: odejmowania
dzielenia
Dane: liczby naturalne a, b
Wynik: nwd(a, b)
dopki a b wykonaj
jeeli a > b to a  a b
przeciwnie b  b a
nwd  a

NWD(153, 85)
a b=true; a>b=true; a=a-b=68
a b=true; a >b=false; b=b-a = 85-68 = 17
a b=true; a>b=true; a=a-b = 68-17 = 51
a b=true; a>b=true a=a-b = 51-17 = 34
a b=true; a>b=true a=a-b = 34-17 = 17
a b=false; nwd =a =17

function NWD(a, b:integer):integer


begin
if b=0 then NWD:=a
else NWD:=NWD(b, a mod b)
end;

NWD(30, 21) 

k=k+1
j=j+1
N

KONIEC

Rys.P1.5. Algorytm mnoenia macierzy

Dane:
a, b
Wyniki: nwd(a, b)
while b > 0 do
r  a mod b
ab
br
nwd  a

2 mod 2 = 0
0 mod 23 = 0
46 mod 4 = 2
46 mod 2 = 0
2 mod 48 = 2
46 mod 48 = 46
48 mod 46 = 2
64 mod 24 = 16

NWD(21, 9)
NWD(9, 3)
NWD(3, 0)
3
Rekurencyjna implementacja algorytmu NWD jest skoczona, gdy
w kadym woaniu ulega zmniejszeniu warto 2-go argumentu.

Rys. P1.6. Algorytm NWD

Sortowanie zbioru liczb A = { a1,a2,,an } w kolejnoci rosncej.

Dane: wektor A[1..n] ze zbiorem liczb rzeczywistych.


Wynik: wektor B[1..n] z posortowanym zbiorem A.
Pobieraj elementy ze zbioru A i twrz sukcesywnie nowy
zbir B z elementami posortowanymi.
Kady element ze zbioru A jest porwnywany kolejno z
elementami zbioru B.
Jeeli k-ty element w zbiorze B jest wikszy od
aktualnie pobranego ze zbioru A to wszystkie elementy
od k s przesuwane o jedn pozycj w prawo.
W zwolnione kte miejsce wstaw element ze zbioru A.

j=1

Dla a b wynik dzielenia liczb cakowitych a przez b jest nastpujcy: a = q*b + r


q = a/b jest ilorazem dzielenia, za reszta r = a - qb jest zapisywana jako a mod b
Twierdzenie: dla liczb cakowitych a 0 oraz b > 0 nwd(a, b) = nwd(b, a mod b).
Dowd opiera si na pokazaniu, e nwd(a, b) i nwd(b, a mod b) dziel si nawzajem,
zatem musz by rwne ( jeeli a|b i b|a to a = b).
nwd(64, 24) = nwd(24,16)

Przykad 1.7 - SORT1b

i=1

START

Wynik: C[n x r] = A [n x m] * B [m x r],

Algorytmy i Struktury Danych wykad

Przykad 1.6. Najwikszy wsplny dzielnik NWD(a, b) dwch liczb naturalnych dodatnich.

jeeli warto funkcji na jednym z kracw przedziau jest rwna zero


to warto ta jest rozwizaniem
w przeciwnym razie
jeeli na kracach przedziau warto funkcji na identyczne znaki
to w przedziale nie ma miejsca zerowego
powtarzaj
podziel przedzia na p
jeeli dla wartoci rodkowej funkcja przyjmie warto zero
to warto ta jest rozwizaniem
w przeciwnym razie
jeeli przedzia jest dostatecznie may
to rodek przedziau jest wystarczajcym przyblieniem rozwizania
w przeciwnym razie wybierz t poow przedziau, w ktrej ma miejsce zmiana znaku
dopki nie zostanie znalezione rozwizanie
Przykad 1.4a
odczytaj znak
dopki istniej dalsze dane wejciowe
zwiksz licznik znakw
jeeli odczytano sowo to zwiksz o licznik_slow
jeeli odczytano wiersz to zwiksz licznik_wierszy
odczytaj nastpny znak

Instytut Aparatw Elektrycznych


Algrm1
Dr J. Dokimuk

R1.6

Instytut Aparatw Elektrycznych


Algrm1
Dr J. Dokimuk

Komentarz do schematu blokowego P1.7.


i biecy wskanik elementu wektora A;
j aktualnie najwikszy wskanik zbioru B;
k biecy wskanik elementu tablicy B, z ktrym
porwnywany jest element ai.
Jeeli aibk oraz k<j to nastpuje porwnywanie ai z bk+1.
Jeeli aibk oraz kj wtedy ai dopisujemy na koniec wektora B.
Jeeli ai < bk to podzbir B[k..j] jest przesuwany o 1 w prawo,
za na pozycj k wstawiany jest element ai.

START
i=j=1
bj=a1
i<n
KONIEC
i=i+1
h=j+1

k=1
T a >b
i
k
T

k<j

bh=bh-1

h=h-1

N
T

k=k+1

j=j+1
bj=ai

h>k
bk=ai
j=j+1

R1.7

Rys. P1.7. Algorytm sortowania

Algorytmy i Struktury Danych - wykad

2. ANALIZA ALGORYTMW
Zadaniem analizy algorytmw, -dziau informatyki- jest poszukiwanie najlepszych algorytmw
realizujcych okrelone zadania komputerowe, prbujc odpowiedzie na pytania:
Czy problem opisany algorytmem moe by zrealizowana na komputerze w realnym czasie?
Ktry z algorytmw naley zastosowa dla okrelonego problemu i zadanego sprztu?
Czy przyjty algorytm jest optymalny?
Moe istnieje lepszy od przyjtego?
Czy mona udowodni, e dla wybranego algorytmu uzyska si jednoznaczne rozwizanie?
2.1. Pojcie zoonoci
Identyczny problem moe by rozwizany z wykorzystaniem algorytmw o rnej efektywnoci, dajcej si odczu dopiero przy przetwarzaniu narastajcych liczebnie zbiorw.
Zoonoci obliczeniowa jako miar porwnywania efektywnoci algorytmw
wprowadzili J. Hartmanis i R. E. Stearns.
Okrela ona ile zasobw zuywa dany algorytm lub jak jest on kosztowny.
Zbir: zestaw oddzielnych, nie numerowanych obiektw, zwanych elementami zbioru.
Moe zosta zdefiniowany przez wypisanie elementw w nawiasie np. Z = { 2, 5, 4, 7 }.
Zapis A B oznacza: wszystkie elementy zbioru A zawieraj si w zbiorze B, tym samym jeeli x A to x B.
Zbir A jest podzbiorem zbioru B.
A B -cz wsplna, zbir wsplnych elementw
Oznaczenia typowych zbiorw:
w obu zbiorach.
pusty, nie zawiera elementw,
A B -suma, zbir wszystkich elementw wystpujcych w obu zbiorach.
Z liczb cakowitych Z = {-2,-1,0,1,2,},
A / B -rnica midzy A i B, zbir elementw
R liczb rzeczywistych,
bdcych w A lecz nie wystpujcych w B.
N liczb naturalnych, N = {0,1,2,3,}.
Mona zdefiniowa nowy zbir, bazujc istniejcych zbiorach, stosujc zapis z dwukropkiem ( takie, e ).
Zbir liczb parzystych mona zdefiniowa: P = { X: X Z i reszta z X/2 jest zerem }
Rozmiar danych wejciowych liczba pojedynczych danych wchodzcych w skad zbioru danych.
Dla sortowania -liczba elementw zbioru; dla analizy drzewa liczba wzw w drzewie.
Wprowadmy oznaczenia:
D2
D1
m1
m2
n zbir z zestawami danych wejciowych D o jednakowych rozmiarach,
D4
mDn liczba operacji dominujcych dla zestawu danych D,
D5
D3
Xn zmienna losowa zawierajca wartoci mDn dla D n,
pk,n prawdopodob., e algorytm wykona k operacji dominujcych dla danych o rozmiarze n.
Podstaw okrelenia rozkadu prawdopodobiestwa zmiennej losowej Xn s informacje o aplikacjach algorytmu.
Czsto przyjmuje si, e kady zestaw danych o rozmiarze n, z jednakowym prawdopodobiestwem moe stanowi zbir wejciowy algorytmu.
W praktyce, dla realnego zbioru danych nie zawsze tak musi by.
Pesymistyczna zoono czasowa: W(n) = sup{ mDn: D n },

kres grny zbioru

Oczekiwana zoono czasowa: A( n ) = k pk ,n = ave(Xn) warto oczekiwana zm. losowej Xn


k

n
A

Pesymistyczna wraliwo czasowa: W(n) = sup{ mD1 mD2: D1, D2 n }


Oczekiwana wraliwo czasowa: ( ) = dev( X n ) std. odchylenie zmiennej losowej Xn
gdzie dev ( X n ) = var( X n )

za

var( X n ) = ( k ave( X n ))2 pk ,n jest wariancj zmiennej losowej X n


k

Wzrost wartoci funkcji wraliwoci W(n) i A(n) sygnalizuje, e


 algorytm jest bardziej wraliwy na dane wejciowe,
 jego zachowanie moe odbiega od oczekiwa po wartociach funkcji W(n) i A(n).
Zoono czasowa algorytmy implementowanego jako procedura obliczeniowa w
okrelonym rodowisku programistycznym, rni si od wyznaczonej teoretycznej.
Istotna jest, z praktycznego punktu widzenia, informacja o rzdzie wielkoci funkcji
zoonoci W(n) i A(n), tzn. o ich zachowaniu dla n dcego do nieskoczonoci.

Instytut Aparatw Elektrycznych


Algrm2
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

2.2. Definicje notacji


Efektywno algorytmu nie powinna by wyraana w jednostkach czasowych (ms, s) lecz jako
zaleno midzy rozmiarem n zbioru danych a czasem jego przetworzenia.
Przykadowo, zwizek f(n) = cn ma charakter liniowy i ckrotny wzrost rozmiaru
danych daje ten sam wzrost czasu potrzebnego na wykonanie algorytmu.
Zalenoci pomidzy czasem t a rozmiarem n maj posta zoonych funkcji wieloskadnikowych i
ich wyznaczanie ma sens jedynie dla duych zbiorw danych. W tej sytuacji skadniki wzoru,
ktre w sposb istotny nie zale od n naley wyeliminowa. Otrzymuje si przyblion
funkcj jako miar efektywnoci algorytmu, ktrej zgodno z oryginaem wzrasta ze wzrostem n.
Rozwamy przykadow funkcj efektywnoci: f(n) = n2 + n1.5 + nlg(n) + lg(n)

lg(n) log2(n)
lg(n) = ln(n)/ln(2)

Tabela 2.1. Szybko wzrostu skadnikw funkcji f(n)

n
256
4096
65536
1048576

n2
65536
16777216
4294967296
1099301922576

n1.5
4096
262144
16777216
1073588228

nlg(n)
2048
49152
1048565
20969520

lg(n)
8
12
16
20

Z tabeli 2.1 wynika, e dla zbioru danych wyej 1 miliona funkcj opisujca zoono obliczeniow f(n)
mona ograniczy do jednego skadnika tzn. f(n) = n2, bez popenienia istotnego bdu obliczeniowego.

Asymptotyczna zoono algorytmu: okrela rzd wielkoci dziaania algorytmu dla


dostatecznie duych rozmiarw danych wejciowych. Stosowana jest gdy pomija si w niej mniej
istotne skadniki funkcji analitycznej lub gdy wyznaczenie wiarygodnej funkcji jest niemoliwe.
W notacji asymptotycznej wykorzystuje si funkcje, ktrych argumentem jest zbir liczb
naturalnych. Jest ona przydatna do opisu pesymistycznego czasu dziaania, bdcego
zazwyczaj funkcj wielkoci danych wejciowych.
Funkcje czysto kwadratowe (pure-quadratic) nie zawieraj skadnikw liniowych, 5n2+22.
Funkcje zupenie kwadratowe (complete quadratic) zawieraj skadniki liniowe, 5n2 - 3n + 22.
Zoono czasow algorytmu A1 okrela funkcja f1(n) = 0.05n2, za algorytmu A2 f2(n) = 120n.
Algorytm A2 bdzie wydajniejszy gdy 0.05n2 > 120n  n > 2400.

Kady algorytm o liniowym czasie dziaania staje si w okrelonym momencie


wydajniejszy od kadego algorytmu o kwadratowym czasie wykonania.
2.2.1. Notacja O
Niech dane bd dwie funkcje: f(n) i g(n) o wartociach dodatnich.
Funkcja f(n) jest klasy O(g(n)) jeeli istniej dwie stae: rzeczywista c > 0 i naturalna n0,
takie e relacja f(n) cg(n) zachodzi dla kadego n n0.
Funkcja f(n) jest duym O z g(n).
Midzy funkcjami f(n) i g(n) istnieje zwizek mwicy, e funkcja g(n) jest grnym
ograniczeniem wartoci funkcji f(n), z dokadnoci do staej c.
Dla dostatecznie duych n funkcja f(n) ronie nie szybciej ni funkcja g(n).
Notacj O wprowadzi 1894 Paul Bachmann i jest ona powszechnie stosowana do wyznaczenia
zoonoci asymptotycznej tzn. szacowania szybkoci wzrostu funkcji.
Niejednoznacznoci notacji O:
f(n)=O
)=O(g(n))
 nie podaje sposobu wyznaczenia staych c i n0,
(n)
cg
 nie nakada adnych ogranicze na ich wartoci,
 brak kryteriw wyboru w przypadku gdy mamy kilka wartoci.
W praktyce dla danej pary funkcji f(n) i g(n) mona znale
nieskoczenie wiele odpowiednich par c i n0.
n( n 1) n 2
n( n 1)
Niech T ( n ) =
. Dla n 0 zachodzi:

n0
2
2
2
Przyjmujc c = 1/2 oraz n0 = 0 dowodzimy, e T(n) O(n2)
Mwimy: due O nakada na funkcj asymptotyczne ograniczenie grne.
f( n
)

Instytut Aparatw Elektrycznych


Algrm2
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad


2

Wemy funkcj: f(n) = 2n + 11n + 13 cg(n) = O(n ), gdzie g(n) = n


i rozwamy odpowiadajc jej nierwno z dwiema niewiadomymi:
2+

11
n

13
n2

dla rnych wartoci n.

Tablica 2.2
n 2n2 11n
1 2
11
2 8
22
3 18 33
4 32 44
5 50 55
6 72 66

Mona wyznaczy nieskoczenie wiele par (c, n0) speniajcych w/wym nierwno.
Wyznaczenie najlepszych wartoci c i n0 wymaga okrelenia, dla jakich
wartoci n0 okrelony skadnik w funkcji f(n) staje si dominujcy i ze
wzrostem n pozostaje.
Dla przykadowej funkcji kandydatami na skadnik dominujcy s: 2n2 raz 11n.
Mona zauway, e nierwno 2n2 11n jest speniona dla n > 5.
Poszukiwane wartoci graniczne to n0 = 6 oraz c 3.28.

Mona wybra nieskoczenie wiele par c, n0 powyej obliczonych wartoci granicznych.


Warto staej c w definicji O zaley od wyboru n0 i odwrotnie.
500
Liczba n0 moe by okrelona jako punkt przecicia f(n)
400
wykresw funkcji f(n) i cg(n).
2
W analizowanym przykadzie funkcja g(n)=n zostaa wybrana 300
2
arbitralnie i bynajmniej nie jest ona jedyna.
200 f(n)=2n +11n+13
Rwnie dobrze jako funkcj g(n) mona wybra funkcje:
100
n3, ,nk dla k > 2 wtedy np.: f(n) O(n4)
3.5n2
Istnieje zasada mwica o wyborze funkcji g(n)
0
najmniejszej z moliwych.
0
2
4
6

5n2

Instytut Aparatw Elektrycznych


Algrm2
Dr J. Dokimuk

10

Algorytmy i Struktury Danych - wykad

2.2.2. Notacja
Funkcja f(n) jest klasy (g(n)) jeeli istniej dwie stae: rzeczywista c > 0
i naturalna n0, takie e relacja f(n) cg(n) zachodzi dla kadego n n0.
Mona powiedzie, e dla dostatecznie duych n funkcja f(n) ronie przynajmniej tak
szybko jak funkcja g(n).

Notacja okrela asymptotycznie doln granic szacowania


Midzy funkcjami f(n) i g(n) istnieje zwizek mwicy, e funkcja g(n) jest dolnym ograniczeniem
wartoci funkcji f(n), z dokadnoci do staej c.
Szacujc czas dziaania algorytmu dla najlepszego przypadku, z wykorzystaniem notacji
, szacuje si rwnie czas dziaania algorytmu dla wszystkich danych wejciowych.
Orzeczenie, e czas dziaania okrelonego algorytmu jest rzdu (g(n)), oznacza, e
niezalenie od struktury danych wejciowych o rozmiarze n czas dziaania algorytmu dla
tych danych wynosi co najmniej cg(n) dla n odpowiednio duego.
Efektywno algorytmu sortowania przez wstawienie dla najlepszej struktury danych
wynosi (n), z czego wynika, e optymistyczny czas dziaania algorytmu jest take (n).
Prawd jest te stwierdzenie, e pesymistyczny czas dziaania w/wym algorytmu sortowania
wynosi (n2), gdy dla pewnych danych czas jego wykonania wynosi (n2).
2.2.3. Notacja

n
8

10

Wasnoci notacji O
1. Jeeli funkcja f(n) jest klasy O(g(n)) i g(n) jest klasy O(h(n)), to f(n) jest O(h(n)) prawo przechodnioci.
2. Jeeli funkcja f(n) jest klasy O(h(n)) i g(n) jest klasy O(h(n)), to f(n) + g(n) jest O(h(n)).
3. Funkcja f(n) = ank jest klasy O(nk).
4. Funkcja f(n) = nk jest klasy O(nk+i) dla dowolnego i > 0.
5. Funkcja f(n) = cg(n) jest klasy O(g(n)).
6. Funkcja loga(n) jest klasy O(logb(n)) dla dowolnych a > 1 i b>1.
Podstawa logarytmu nie ma znaczenia w notacji O. Zachodzi loga(n) = c*logb(n), c = ln(b)/ln(a)
7. Funkcja loga(n) jest O(lg(n)) dla dowolnego a > 0.
Z przedstawionych wasnoci notacji O wynika uoglniony wniosek:
f(n) = aknk + ak-1nk-1 + +a1n + a0
jest klasy O(nk)
Notacja O okrela grn granic asymptotycznego szacowania.
Szacujc pesymistyczny czas dziaania algorytmu, rwnie szacuje si z gry czas
dziaania danego algorytmu dla wszystkich danych wejciowych.
Orzeczenie, e czas dziaania algorytmu jest rzdu O(g(n)) oznacza, e
pesymistyczny czas dziaania szacuje O(g(n)) lub, e niezalenie od struktury
danych o rozmiarze n, czas dziaania algorytmu szacuje O(g(n)).
Koszt algorytmu sortowania przez wstawienie dla najgorszego przypadku danych szacowany jest
jako O(n2), z czego wynikaoby, e pesymistyczny czas dziaania tego algorytmu jest take O(n2).
Notacji O uywa si do opisu czasu dziaania algorytmu poprzez badanie jego oglnej struktury.
Klasycznym przykadem moe by algorytm zawierajcy podwjnie zagniedon ptl,
gdzie wskaniki ptli i oraz j osigaj warto n.
Dla n 1 prawdziwa jest relacja: n 1 n2. Przyjmujc n0 = 1 oraz c = 1 dowodzimy, e n O(n2).
Funkcja zoonoci f(n) nie musi posiada skadnika kwadratowego aby nalee do klasy O(n2).
Jej wykres musi jedynie znajdowa si pod wykresem pewnej czysto kwadratowej funkcji.

Funkcja f(n) jest klasy (g(n)) jeeli istniej stae rzeczywiste c1 > 0 i c2 > 0 oraz
staa naturalna n0, takie e relacja c1g(n) f(n) c2g(n) zachodzi dla kadego n n0.
Funkcja f(n) jest klasy (g(n)), jeeli istniej dodatnie stae c1 oraz c2 takie, e funkcja ta
moe by zawarta miedzy c1g(n) i c2g(n) dla dostatecznie duych n. c1g(n) f(n) c2g(n)
Funkcja f(n) jest rzdu g(n) tzn. obie funkcje rosn tak samo szybko dla dostatecznie duych n.
Funkcja g(n) jest asymptotycznie dokadnym oszacowaniem funkcji f(n), gdy dla
wszystkich n n0 funkcja f(n) jest rwna g(n) z dokadnoci do staego wspczynnika.
Dla dwch dowolnych funkcji f(n) i g(n) zachodzi zaleno:
f(n) (g(n)) wtedy i tylko wtedy, gdy f(n) (g(n)) oraz f(n) O(g(n)).

Graficzna interpretacja notacji asymptotycznych


(g(n))
f(
n)

cg
(n
)

Instytut Aparatw Elektrycznych


Algrm2
Dr J. Dokimuk

)
f(n
)
cg(n

c 2g

(n)

n))
(g(

n)
c 1g(

O(g(n))
n0
5n+12 2n2+6n
2lg(n) 8n2-11
6lg(n)-8 12n2

n0

)
f (n

n0

2n2+6n
2n2+6n 3n6+6n2
8n2-11
8n2-11 2n3-5n
12n2
12n2
2n+2n2
Przykady funkcji nalecych do rnych notacji dla g(n) = n2

Notacja O(g(n))
Nie moe by gorzej
Notacja (g(n))
Nie moe by lepiej
Notacja (g(n))
Moe by dokadnie
(g(n) = O(g(n) (g(n)

Notacja O dotyczy szacowania grnych ogranicze funkcji f(n) z dokadnoci do wspczynnika c.


Notacja dotyczy szacowania dolnych ogranicze funkcji f(n) z dokadnoci do wspczynnika c.
Notacja szacuje funkcj f(n) z dokadnoci do staych wspczynnikw c1 i c2.

Instytut Aparatw Elektrycznych


Algrm2
Dr J. Dokimuk

11

Algorytmy i Struktury Danych - wykad

2.2.4. Przykady algorytmw klasy O


Algorytm stay: czas wykonania jest rzdu O(1), jest niezmienny i nie zaley od liczby przetwarzanych elementw. Przykadem jest dostp do elementw tablicy o okrelonej strukturze.
Algorytm logarytmiczny: czas wykonania jest rzdu O(lg(n)).
Dotyczy zada, ktre sprowadzone zostay do rozmiaru n/2 plus pewne dziaania dodatkowe.
Przykad: poszukiwanie binarne zadanego elementu w cigu uporzdkowanym rosnco.
if x < an/2 then Szukaj w podcigu { a1,,an/2-1 } else Szukaj w podcigu { an/2+1,,an }
Algorytm liniowy: czas wykonania jest rzdu O(n).
Oznacza to wykonywanie pewnej, staej liczby dziaa dla kadego z n elementw zbioru
wejciowego. Przykadem moe by sekwencyjne przeszukiwanie zbioru.
Algorytm liniowo-logarytmiczny: czas wykonania rzdu O(nlg(n)).
Dotyczy zada, ktre sprowadzone zostay do dwch podzada rozmiaru n/2 plus pewne
dziaania dodatkowe. Liniowo wzgldem n wynika z dziaa prowadzcych do utworzenia
dwch podzbiorw o licznoci n/2 a nastpnie ich scalenia.
Przykadem jest sortowanie przez scalanie:
sortuj podcig { a1,,an/2 } oraz { an/2+1,,an } nastpnie scal oba podcigi.
Algorytm kwadratowy: czas wykonania rzdu O(n2).
Dotyczy sytuacji, w ktrej dla kadej pary elementw wykonywana
jest okrelona staa liczba dziaa.
Wystpuje w przypadku podwjnych instrukcji iteracyjnych oraz take
szacowania czasu pesymistycznego sortowania metod wstawiania.
Algorytm szecienny: czas wykonania rzdu O(n3).
Przykadem jest mnoenie macierzy kwadratowych o wymiarze n x n.
Algorytm wykadniczy: czas wykonania jest rzdu O(2n).
Dotyczy sytuacji, w ktrej dla kadego podzbioru danych
wejciowych wykonywana jest pewna staa liczba dziaa.
Tablica 2.3. Przykadowe czasy realizacji rnej klasy algorytmw
Klasa algorytmu
Liczba operacji / Czas wykonania [1 operacja/uS]
n = 100
n = 1.000
n = 1.000.000
Stay O(1)
Logarytmiczny O(log(n))
Liniowy O(n)
Kwadratowy O(n2)
Wykadniczy O(2n)

1
6.64
100
10000
1030

<<s
<<s
<<s
10 ms
3.2*1016lat

1
9.97
1000
106
10301

<<s
<<s
1 ms
1s

1
19.93
106
1012
10301030

<<s
<<s
1s
11.6 dni

Tabela 2.3. pokazuje, e dla pewnej klasy algorytmw ich implementacja na wspczesnych
komputerach jest bezowocna, ze wzgldu na nierealny czas wykonania.

Komputery nanosekundowe tylko w pewnym stopniu bd w stanie urealni ich implementacj.


Zoonoci wykadnicza jest czasami mylca, gdy dotyczy najgorszej struktury danych
wejciowych, ktrej prawdopodobiestwo pojawienia si moe by niewielkie.
Jeeli algorytm na pesymistyczn zoono W(n)=2n + O(1) oraz wraliwo W= 2n + O(1)
to nie mona stwierdzi, e jest on nierealizowalny, gdy dane pesymistyczne mog si
nigdy nie pojawi.
Przykadem moe by metoda programowania liniowego simplex, majc zoono
wykadnicz dla danych najgorszych. Dane wejciowe, ktre pojawiaj si w praktyce daj
algorytmowi klas liniow lub w najgorszym razie klas wielomianow.

Analiza zoonoci algorytmw nigdy nie powinna by lekcewaona, a w szczeglnoci dla


duych struktur danych. Rosnca szybko dziaania komputerw niewiele pomoe,
jeeli wykonywane programy bd realizowa nieefektywne algorytmy.

Instytut Aparatw Elektrycznych


Algrm2
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

12

Dlaczego zazwyczaj szacuje si pesymistyczny czas dziaania algorytmu ?


 Pesymistyczny czas dziaania jest grn granic czasw dziaania algorytmu dla kadego
zbioru danych. Znajc ten czas mamy gwarancj, e algorytm nie bdzie dziaa duej;
 Dla wielu algorytmw pesymistyczny czas dziaania wystpuje bardzo czsto, szczeglnie w
trakcie poszukiwania w bazie danych informacji, ktrej tam nie umieszczono;
 Bardzo czsto redni czas dziaania, zwizany z typowym zbiorem danych jest tego
samego rzdu co klasyczny przypadek pesymistyczny.
Uwarunkowania uwzgldniane w analizie zoonoci algorytmw:
 opracowany algorytm i jego paszczyzna implementacyjna to nie cakiem to samo;
 wraliwo okrelonego algorytmu na dane wejciowe, moe by przyczyn e realne
czasy dziaania bd znacznie odbiega od przewidywanych rozwaa teoretycznych;
 prawidowe okrelenie prawdopodobiestwa rozkadu liczby operacji dominujcych moe
by niemoliwe, co skutkuje trudnociami z okreleniem oczekiwanej zoonoci czasowej;
 jeden algorytm dziaa dobrze dla pewnej klasy danych, drugi za dla innej;
 istotne jest jak czsto okrelona implementacja algorytmu bdzie wykonywana;
 istotne jest czy algorytm bdzie pracowa tylko z maymi lub tylko z duymi zbiorami danych.
Pojcie funkcji anonimowej
Zapis 2.5n2 + 3n + 4 = 2.5n2 + O(n) jest rwnowany 2.5n2 + 3n + 4 = 2.5n2 + h(n)
gdzie h(n) jest pewn funkcj nalec do zbioru O(n).

Jest oczywiste, e h(n) = 3n + 4 rzeczywicie naley do O(n).


Zapis powyszy pozwala wyeliminowa niepotrzebne detale, przyczyniajc si do upraszczania rwna.
Jeeli badamy tylko asymptotyczne zachowanie funkcji T(n) = 2T(n/2) + O(n) to nie
interesuj nas mao istotne skadniki zawarte w anonimowej funkcji O(n).
Zapis 2.5n2 + O(n) = O(n2) oznacza: bez wzgldu na to jakie anonimowe funkcje znajduj si po lewej
stronie znaku rwnoci, zawsze mona wybra funkcje po prawej stronie aby zachodzia relacja.
Tak wic prawa strona rwnania jest zgrubnym opisem lewej strony.
Mona tworzy acuch relacji: 2.5n2 + 3n + 4 = 2.5n2 + O(n) = O(n2)
Dlaczego jedni mwi, e algorytm jest klasy O(n2) inni za, e klasy (n2)
Zapis f(n) = O(g(n)) oznacza, e funkcja f(n) jest elementem zbioru O(g(n)).
Zapis teoriomnogociowy (g(n)) O(g(n)) mwi, e wystpienie f(n) = (g(n)) implikuje
f(n)=O(g(n)), poniewa notacja jest silniejsza ni notacja O.
Jeeli funkcja 2.5n2 + 3n + 4 naley do zbioru (n2) to naley te do zbioru O(n2).
Notacja jest uywana do opisu asymptotycznie dokadnych oszacowa, za
notacja O do oszacowania asymptotycznie grnego.
Notacja O jest uywana nieformalnie do opisu asymptotycznie dokadnych oszacowa.
Za zapis f(n) = O(g(n)) mwi jedynie, e po przemnoeniu cg(n) otrzymuje si
asymptotycznie grn granic, bez podania jej stopnia dokadnoci.
Opracowano dwa algorytmy A1 i A2, ktrych implementacyjna
200lg(n) 10n
n
zoono wynosi odpowiednio f1(n) = 200*lg(n) i f2(n) = 10*n.
10
664
100
Algorytm A1 jest klasy O(lg(n)) za A2 klasy O(n), co oznacza, e
50
1129
500
algorytm A1 jest lepszy od A2.
100
1329 1000
Czy jest tak rzeczywicie skoro dla n=100 mamy: 200*lg(100) > 10*100.
150
1446
1500
Problem wyjania si, jeeli wemiemy odpowiednio due n, gdy 1000 1993 10000
notacja O jest notacj asymptotyczn.
Dostpne s dwa algorytmy B1 i B2 rozwizujce ten sam problem.
Algorytm B1 wykonuje 108n operacji i jest klasy O(n), za B2 n2 operacji i jest klasy O(n2).
Zgodnie z zasad O algorytm B2 naley odrzuci, poniewa czas jego wykonania ronie
szybciej ni B1. Jest to prawd ale dla odpowiednio duego zbioru danych.
Dla zbioru danych o licznoci n 1.000.000 algorytm B2 wykonuje mniej operacji ni B1.

Instytut Aparatw Elektrycznych


Algrm2
Dr J. Dokimuk

13

Algorytmy i Struktury Danych - wykad

2.3. Zoono obliczeniowa algorytmu numerycznego


Miar zoonoci moe by liczba wykonywanych operacji zmiennoprzecinkowych.
Za pojedyncz operacj zmiennoprzecinkow uwaa si sum, rnic, iloczyn oraz iloraz
dwch liczb rzeczywistych.
W przypadku oblicze realizowanych na liczbach zespolonych mamy dwie (suma i rnica) lub
sze (iloczyn i iloraz) operacji zmiennoprzecinkowych.
Niektre rodowiska programistyczne jak MATLAB udostpniaj moliwo wyznaczenia
liczby wykonywanych operacji zmiennoprzecinkowych.
Matlab udostpnia funkcj flops, zwracajc liczb wszystkich wykonanych operacji
zmiennoprzecinkowych od czasu uruchomienia rodowiska.
poczatek = flops;
Funkcja flops(0) zeruje licznik operacji.
FUNKCJA
Pomiar liczby operacji zmiennoprzecinkowych mona
wynik
= flops poczatek
zrealizowa w pakiecie MATLAB wg schemat podany obok.
Dla macierzy kwadratowej o rozmiarach n, podaje si liczby operacji zmiennoprzecinkowych:
suma i rnica: n2
iloczyn: 2n3
rozkad LU: 0.7n3.
Wyznaczanie liczby operacji zmiennoprzecinkowych
n=5; A=randn(n); B=rand(n); p = flops; C=A+B; w = flops - p
% n=5 25, n=10 100,
n=50 500,
n=100 104
n=5; A=randn(n); B=rand(n); p = flops; C=A*B; w = flops - p
% n=5  250,
n=10 2000,
n=50 250000,
Pomiar czasu wykonania
n=50; A=randn(n); B=rand(n); tic; C=A*B; time = toc - tic
% n=50  time=0.05s,
n=100  time=0.16s.

n=100 2*106

2.4. Uwagi o zoonoci obliczeniowej


Analizujc konkretny algorytm, okrelamy jego zoono czasow lub pamiciow,
albo przynajmniej klas zoonoci czasowej lub pamiciowej.

Nie analizujemy na tym etapie problemu rozwizywanego przez ten algorytm.


3

Klasyczny algorytm mnoenie macierzy ma zoono czasow n .


Nie oznacza to, e mnoenie macierzy wymaga algorytmu o zoonoci O(n3).
Funkcja n3 jest wasnoci okrelonego algorytmu i nie musi by wasnoci problemu mnoenia macierzy.
Strassen V. przedstawi algorytm mnoenia macierzy o zoonoci O(n2.81).
Zmodyfikowana odmiana tego algorytmu pozwala uzyska zoonoci czasow O(n2.38).

Wane jest okreli, czy istnieje moliwo znalezienia jeszcze bardziej efektywnego algorytmu.
Analiza zoonoci obliczeniowej jest prb okrelenia dolnej granicy efektywnoci wszystkich
algorytmw rozwizujcych dany problem.
Istnieje dowd, e problem mnoenia macierzy mona rozwiza za pomoc algorytmu, o
zoonoci nie mniejszej ni (n2). Stwierdzenie jest efektem analizy zoonoci obliczeniowej.
Na podstawie przeprowadzonej analizy moemy powiedzie, e dolne ograniczenie dla
problemu mnoenia macierzy to (n2). Nie oznacza to, e musi istnie moliwo
skonstruowania algorytmu mnocego macierze o zoonoci czasowej O(n2).
Oznacza to jedynie, e teoretycznie taka moliwo istnieje.
Celem dla danego problemu jest wyznaczenie dolnego ograniczenia w postaci (g(n))
i stworzenie algorytmu o zoonoci O(g(n)), ktry rozwizuje ten problem.
Kiedy uda si osign ten cel, many pewno, e znalezionego algorytmu nie mona ju
poprawi (oczywicie, poza popraw staych, ktrych nie uwzgldniamy w zapisie zoonoci).
Dla sortowania stworzono algorytmy o zoonoci czasowej zblionej do dolnego ograniczenia.
Dla klasy algorytmw sortujcych na podstawie operacji porwna kluczy
dolne ograniczenie wynosi (nlg(n)).
Powstay ju algorytmy O(nlg(n)).
Algorytmy sortujce wycznie poprzez porwnanie kluczy mog porwnywa dwa klucze aby okreli, ktry
z nich jest wikszy, oraz kopiowa klucze, ale nie mog wykonywa na kluczach adnych innych operacji.

Instytut Aparatw Elektrycznych


Algrm2
Dr J. Dokimuk

14

Algorytmy i Struktury Danych - wykad

2.5. Rwnania rekurencyjne w analizie zoonoci


W wielu przypadkach opis algorytmu zawiera rekurencyjne wywoanie samego siebie.
Wwczas obliczenia zwizane z wyznaczaniem klasy algorytmu (czasu dziaania) mona
sprowadzi do rozwizania rwnania rekurencyjnego.
x najwiksza liczba cakowita nie wiksza ni x
31/2 = 15.5 = 15
x najmniejsza liczba cakowita, nie mniejsza ni x 31/2 = 15.5 = 16
2.5.1. Metoda iteracyjna z zamian zmiennej
Metoda rozwija rwnanie do sumy, po uprzednim podstawienie n = 2k, po czym nastpuje
ograniczenie skadnikw otrzymanej sumy i powrt poprzez podstawienie k = lg(n)).
Rwnanie zoonoci dla problem analizy zbioru wielkoci n, sprowadzonego do analizy
podzbioru n/2 plus pewna staa liczba dziaa.

0
T (n) =
T ( n / 2) + c

dla
dla

n =1
n >1

T(2k) = T(2k-1) + c = T(2k-2) + c +c = T(20) + ck = clg(n)

T(n) = O(lg(n))

Rwnanie zoonoci dla problem analizy zbioru wielkoci n, sprowadzonego do analizy dwch
podzbiorw n/2 plus pewna staa liczba dziaa.

0
T (n) =
T ( n / 2) + T ( n / 2) + c

dla n = 1
dla n > 1

T(2k) = 2T(2k-1) + c = 2(2T(2k-2) + c) +c = 22T(2k-2) + 21c + 20c =


2kT(20) +c(2k-1+2k-2++20) = c(2k-1) = c(n-1)

T(n) = O(n)

Rwnanie zoonoci dla problem analizy zbioru wielkoci n, sprowadzonego do analizy dwch
podzbiorw n/2 plus pewna liniowa liczba dziaa.

0
T (n) =
T ( n / 2) + T ( n / 2) + cn

dla
dla

n =1
n >1

T(2k) = 2T(2k-1) + c2k = 2(2T(2k-2) + c2k-1) +c2k = 22T(2k-2) + c2k +c2k =2kT(20) + kc2k =
= cnlg(n)

T(n) = O(nlg(n))

Rekurencja uniwersalna
Jest metod pozwalajc na szablonowe rozwizanie rwna postaci:
T(n) = aT(n/b) + f(n)
gdzie a > 1, b > 1 pewne stae, za f(n) jest funkcja asymptotycznie dodatni.
Rwnanie opisuje czas dziaania algorytmu, ktry dzieli zadany problem o rozmiarze n na a
podproblemw o rozmiarze n/b kady.
Kady podproblem a rozwizywany jest rekurencyjnie w czasie T(n/b).
Funkcja f(n) opisuje czas dzielenia i czenia wynikw czciowych.
Upraszczanie rwna rekurencyjnych
Rozwizujc rekurencyjne rwnanie warto zastanowi si nad pominiciem szczegw.
Klasycznym zaoeniem upraszczajcym jest przyjcie za argument funkcji liczby cakowitej, gdy
dla innych wartoci prezentowane zalenoci na czas dziaania algorytmu nie musz by aktualne.
Rozwamy rwnanie , ktre dla poprawnego rozwinicia potrzebuje warunkw brzegowych.
Mona przyj zaoenie, e dla maych n funkcja T(n) jest staa i pomin warunki brzegowe otrzymujc:
T(n) = 2T(n/2) + O(n)
Nie podaje si wartoci funkcji T(n) dla maych n, gdy ich uwzgldnienie zmienia jedynie
rozwizanie o pewn sta bez wpywu na rzd wielkoci.

Instytut Aparatw Elektrycznych


Algrm2
Dr J. Dokimuk

15

Algorytmy i Struktury Danych - wykad

Stosujc ide upraszczania rwna rekurencyjnych mona rozwiza rwnanie zoonoci:


n
T ( n ) = 2T + n 1 bez podanych warunkw pocztkowych.
2
n n
n
n
T ( n ) = 2T + n 1 = 2 2T + 1 + n 1 = 4T + 2n 2 1 =
2
4
4 2
n n
n
4 2T + 1 + 2n 2 1 = 8T + 3n 4 2 1
8
4

L L L L
n
n
T ( n ) = 2 T k + k n 2i = 2k T i + k n 2k + 1
2
2
i =0
Jezeli k = lg(n ) to :
k

n
T ( n ) = 2lg( n ) T lg( n ) + n lg(n ) 2lg( n ) + 1 = n lg(n ) n + 1
2

2.5.2. Metoda dodawania stronami


Rozpoczynamy od problemu stopnia n i kolejno schodzimy wstecz, nastpnie dodajemy
stronami otrzymane wyraenia, uwzgldniajc warunek pocztkowy.
1
T ( n 1) + n

T(n) = T(n-1) + n
T(n-1) = T(n-2) + n - 1
T(n-2) = T(n-3) + n - 2

T(2) = T(1) + 2
T(1)= 1

n >1

i =1

n =1

dla

n >1

n ( n + 1)
2

Przykad 2.1. Sprawdzi czy w zbiorze A = {a1,a2,,an} znajduje si okrelony obiekt.


Dane: tablica A zawierajca n obiektw oraz poszukiwany obiekt key.
Wynik: zmienna OK > 0 gdy element znajduje si w tablicy A, przeciwnie OK = -1.

n 1
2
2
2
2
+L+
+
+ = 2 2 ln( n )
i=2 i
2
n 2 n 1 n

n=0

dla

n 1

Operacja dominujca:

porwnanie

Pesymistyczna zoono: W(n) = n + 1


Pesymistyczna wraliwo: W(n) = n

Zaoenia: poszukiwany obiekt key znajduje si w zbiorze A, gdzie wszystkie elementy s rne.
nie ma podstaw do stwierdzenia, e wystpowanie key na jednej pozycji jest bardziej
prawdopodobne ni na innej,
std prawdopodobiestwo znalezienia si poszukiwanego obiektu key na
dowolniej pozycji tablicy A jest jednakowe i wynosi: pk,n = 1/n
dla k = 1,2,,n.
n
1 n
1 n( n + 1) n + 1
Oczekiwana zoono czasowa: A( n ) = k pkn = k =
=
n
k =1
n k =1
2
2
n
n + 1 1
n2 1
=
0.29n
k

k =1
2 n
12
Wnioski: wraliwo czasowa jest klasy O(n) co sugeruje wraliwo algorytmu na struktur
danych wejciowych i moliwo odstpstwa od oczekiwanej zoonoci czasowej.
Gdy key moe nie wystpowa w tablicy, przypisujemy pewne prawdopodobiestwo p do
zdarzenia polegajcego na tym, e key wystpuje w tablicy.
Przyjmujemy, jednakowe prawdopodobne, e key znajdzie si na ktrejkolwiek pozycji tablicy.
Prawdopodobiestwo tego, e key znajduje si na k-tej pozycji, wynosi wwczas p/n,
natomiast prawdopodobiestwo, e nie znajduje si w tablicy, wynosi 1 - p.
n
p
p p
p 1

 A(n, 0.5) = 0.75n+0.25.


A( n, p ) = k + n(1 p ) = n( n + 1) + n(1 p ) = n 1 +
n 2
k =1
2 2
n

int main() / /P25a wypenianie fragmentu tablicy

dla

n 1
1
1 1
+ + L + = = ln( n )
2 3
n i =1 i

Przykad 2.2.
Wypenianie fragmentu macierzy od przektnej wcznie.

Dodajc stronami i redukujc otrzymuje si:


T (n) = 0 +

H n =1 +

dla

2.6. Przykady
Wzory uyteczne przy szacowaniu zoonoci.
n
n +1
n
n ( n + 1)
( n + 1)( n + 2)
i = i + ( n + 1) =
i =
i =1
i =1
i =1
2
2

Oczekiwana wraliwo czasowa: A( n ) = var( X n ) =

T(n) = 1 + 2 ++ n-2 + n-1 + n = i =

1
Rozwiza rwnanie: T ( n ) =
T ( n 1) + 1

T(n) = T(n-1) + 1
T(n-1) = T(n-2) + 1
T(n-2) = T(n-3) + 1

T(1) = T(0) + 1
T(0) = 1

n =1

dla

W rezultacie dodania stronami otrzymuje si:

Rozwiza rwnanie: T ( n ) =
2
T ( n 1) + n

T(n) = T(n-1) + 2/n


T(n-1) = T(n-2) + 2/(n-1)
T(n-2) = T(n-3) + 2/(n 2)

T(2) = T(1) + 2/2


T(1)= 0

dla

16

Algorytmy i Struktury Danych - wykad

Algorytm 2.1 Poszukiwanie elementu w wektorze


i1
A[n+1] key
// wartownik
while A[i] <> key do i i+1
if ( i n ) then OK i else OK 1

k 1

Rozwiza rwnanie: T ( n ) =

Instytut Aparatw Elektrycznych


Algrm2
Dr J. Dokimuk

{
int n=6, A[6][6] = {0}, i, j;
for (i=0; i<n; i++)
for (j=0; j<=i; j++) A[i][j]=2;
Drukuj;
}

2
2
2
2
2
2

0
2
2
2
2
2

0
0
2
2
2
2

0
0
0
2
2
2

0
0
0
0
2
2

0
0
0
0
0
2

Zoono obliczeniowa implementacji algorytmu.


n
i

T ( n ) = t p + t pr + 2t p + 2t pr + (2t p + t pr )
i =1
j =1

T ( n ) = t p + t pr + (2t p + 2t pr + i ( 2t p + t pr ) )
n

i =1

Dodajc stronami otrzymuje si:


T(n) = 1+1++1+1 = n + 1

T ( n ) = t p + t pr + 2n(t p + t pr ) + 0.5n( n + 1)( 2t p + t pr )

int main()
{
int n=6, A[6][6] ={0}, i, j;
i=0;
/
while (i < n) {
j=0;
while (j <= i) {
A[i][j] = 2;
j++;
}
i++;
}
Drukuj;
}

//P25b

/ przypisanie tp
// porwnania tpr
// przypisanie tp
// porwnanie tpr
// przypisanie tp
// przypisanie tp
// przypisanie tp

W ptli while Instrukcje wykonywane s n

razy za warunek sprawdzany jest n+1 razy.


T ( n ) = (1 + 3n + n 2 )t p + (1 + 2.5n + 0.5n 2 )t pr
Algorytm wypeniania macierzy jest klasy O(n2) dla operacji przypisywania i porwnywania.

Instytut Aparatw Elektrycznych


Algrm2
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

17

Przykad 2.3. Dany jest zbir liczb A = {a1, a2,, an}.


Utworzy zbir sum wszystkich podcigw tzn.:
As = {a1, a1+a2, a1+a2+a3,, a1++an)
Dane: tablica A zawierajca elementy zbioru A.
// A = { 1, 2, 3, 4, 5, 6, 7, 8 }
Wynik: tablica sA zwierajca sumy podtablic.
// sA = {1, 3, 6, 10, 15, 21, 28, 36 }
// Suma podcigw wektora A

for i 1 to n do
s 0
for j 1 to i do s s + A[j]
sA[i] s

for (int i=0; i<n; i++) {


Operacja dominujca:
s=0;
przypisywanie
for(j=0; j<=i; j++) s += A[j];
sA[i] = s;
}
1 3 6 10 15 21 28 36

Ptla zewntrzna po i obiega n razy, wykonujc:


ptl wewntrzn,
przypisanie wartoci zmiennym: i, sum, j, sA[j].
Ptla wewnrzna wykonuje si i razy dla kadego i {1n},
-dla kadego obiegu przypada jedno przypisanie do sum oraz jedno do j.
n
n (n + 1)
Liczba przypisa: 4n + 2k = 4n + 2
k =1
2
Zoono czasowa: W(n) = n2 + 5n.

W(n) O(n2)

Przykad 2.4. Dany jest zbir liczb A = {a1, a2,, an}.


Utworzy nowy zbir , ktrego elementy stanowi sumy r elementw podcigu tzn.:
Ar = (a1++ar, a2++ar+1, a3 ++ ar+2, )
Dane: tablica A zawierajca elementy zbioru A; r liczba elementw podcigu.
Wynik: tablica sA[1..nr+1], zwierajca sumy podtablic relementowych..
Operacja dominujca: przypisywanie
Dane przykadowe dla r = 5:
Algorytm 2.4. Suma podcigw r-el. wektora A
A = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
r1 r 1
// zmienna robocza
A = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
for i r to n do
A = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
sum 0
A = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
for j i r1 to i do
A = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
sum sum + A[j]
A = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
sA[i r1] sum
SA = { 15, 20, 25, 30, 35, 40 }
Ptla zewntrzna i wykonuje si n r+1 razy:
-realizuje przypisania do i, sum, j oraz sA[j].
Ptla wewntrzna j wykonuje si r razy:
-na kad iteracj przypada jedno przypisanie do sum oraz do j.
Liczba przypisa: (4 + 2r)(n r + 1).
Zoono czasowa: W(n) = (r + 2)n - r2- r + 2.
W(n) O(n)
Dla 5-cio elementowego podcigu W(n) = 14(n 4).
Uwaga: Algorytmy z ptlami zagniedonymi maj zazwyczaj zoono klasy wikszej ni O(n).
S wyjtki (przykad 2.4), gdzie algorytm z ptl podwjn jest klasy O(n).
Dotyczy to sytuacji, gdy ptla wewntrzna nie realizuje penego obiegu
dla wszystkich zewntrznych n.

Instytut Aparatw Elektrycznych


Algrm2
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

18

W analizie algorytmw naley czasem uwzgldni oprcz czasu wykonania operacji


podstawowych take instrukcje dodatkowe i instrukcje sterujce, w kontekcie
okrelonego rodowiska, na ktrym zaimplementowano algorytm.

Instrukcje dodatkowe zwizane s z inicjalizacj zmiennych przed wejciem do ptli.


Liczba wykona tych instrukcji nie wzrasta ze zwikszaniem rozmiaru danych wejciowych.

Instrukcje sterujce to instrukcje zwikszajce indeks w sterowaniu ptl.


Liczba ich powtrze wzrasta wraz ze zwikszaniem rozmiaru danych wejciowych.
Operacje podstawowe, instrukcje dodatkowe oraz instrukcje sterujce s
waciwociami algorytmu i jego implementacji.
Nie s natomiast waciwociami problemu.
Oznacza to, e mog by one rne w przypadku dwch rnych algorytmw
rozwizujcych ten sam problem.

Instytut Aparatw Elektrycznych


Algrm3
Dr J. Dokimuk

19

Algorytmy i Struktury Danych - wykad

3. REKURENCJA
Rekurencja wystpuje wtedy, gdy obiekt skada si czciowo z samego siebie lub w definicji
odwouje si do siebie samego. Pozwala opisywa zbiory nieskoczone lub due
zbiory skoczone, przy pomocy skoczonego wyraenia.
Narzdziem implementacyjnym dla algorytmw rekurencyjnych jest pojcie funkcji.
W praktycznych realizacjach istotne jest pokazanie, e gboko rekurencji jest
skoczona oraz, e ich liczba jest relatywnie maa.
Struktura definicji rekurencyjnej:
1. warunek pocztkowy: element podstawowy, bdcy czci skadow pozostaych elementw.
2. krok rekurencyjny:
specyfikuje reguy tworzenia nowych obiektw z elementw podstawowych.

Instytut Aparatw Elektrycznych


Algrm3
Dr J. Dokimuk

3.2. Liczby Fibonacciego


Cig Fibonacciego 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... long Fib(int n)
{
okrela zaleno rekurencyjna Fib(n).
if (n<2) return n;
dla n = 0
0
else

return Fib(n - 2) + Fib(n- 1)


Fib(n) = 1
dla n = 1

}
Fib(n 2) + Fib(n 1) dla n 2

Wasnoci cigu liczb Fibonacciego


1. Kada liczba cigu jest sum dwch liczb bezporednio j poprzedzajcych;
2. W wyniku podzielenia liczby cigu przez jej poprzednik otrzymuje si iloraz oscylujcy
wok 1.618. Odwrotnoci 1,618 jest 0.618.
W miar zwikszania si liczb, zmniejsza si odchylenie od tej wartoci.
Liczba 1.618 znana jest jako wspczynnik zotych proporcji.
3. Dowolna liczba cigu podzielona przez liczb o dwie pozycje wczeniejsz daje wynik
2.618, za przez liczb o dwie pozycje pniejsz daje wynik 0.382.

Czy 628 jest liczb naturaln ?


Zbir liczb naturalnych
628 N jeeli 62 N ( regua 2)
1. 0,1,2,3,4,5,6,7,8,9 N;
62 N jeeli 6 N (regua 1 )
2. jeeli n N to n0,n1,n2,n3,n4,n5,n6,n7,n8,n9 N;
Definicja rekurencyjna poza tworzeniem nowych obiektw umoliwia sprawdzenie, czy dany
element naley do okrelonego zbioru.
Technika sprawdzania prowadzi do rozbicia problemu na podproblemy.
Jeeli podproblem jest nadal zoony to rozbija si go dalej a do osignicia
poziomu warunku pocztkowego.

dla n = 0
3.1. Silnia n! = n(n-1)(n-2)(3)(2)(1) dla n 1
1
n! =
Warto silni definiuje wzr rekurencyjny, skadajcy si z:
n
*
(
n

1
)!
dla
n>0

-warunku brzegowego,
-kroku rekurencyjnego.
Istotn cech rekurencji jest to, e do wyznaczenia wartoci long Silnia(int n)
{
elementu ak naley obliczy wczeniejsze elementy a1,ak-1.
if (!n) return 1;
4! wymaga wczeniejszego obliczenia wartoci 0!, 1!, 2!, 3!.
return n*Silnia(n-1);
Zastosowanie definicji rekurencyjnej sprawia, e implementacja formu }
matematycznych jest niemal automatyczna.
Funkcja Silnia(3) otrzymuje jako parametr

liczb 3 i analizuje czy jest ona rwna zero


(warunek pocztkowy). Poniewa 30 zatem
przyjmuje warto 3*Silnia(2).
Warto Silnia(2) nie jest znana, funkcja

wywouje swj kolejny egzemplarz liczcy


warto Silnia(2).
Jednoczenie zamroony jest proces
liczenia 3*Silnia(2).
Proces powtarza si a wywoujc swj
kolejny egzemplarz dojdzie do obliczania
Silnia(0), znanej z warunku pocztkowego.

n:=3
n:=0

Silnia 3!
N

3!:=3
!:=3*2!

F(4)

F(3)

poziom 1

F(3)

F(2)

F(2)
F(0)

F(1)

F(0)

F(1)

F(1)

Problem o rozmiarze n rozbity zostaje na


dwa mniejsze podproblemy o rozmiarach
n-1 i n-2

F(2)

poziom 2
2!:=2
!:=2*1!
n:=1
n=0

poziom 3
1!:=1
!:=1*0!

Proces zagbia sie


n:=0
z poziomu n na n - 1
Wtedy
wynik
czstkowy
poziomu
az do osignicia
T
elementarnego przesyany jest na coraz
poziomu
n=0
0!:=1
!:=1
wyszy poziom, a do szczytu stosu.
elementarnego
Liczba mnoe jest sum mnoe w wywoaniach rekurencyjnych, potrzebnych do obliczenia
Silnia(n-1) plus jedno mnoenie n* Silnia(n-1) na najwyszym poziomie.
Zoono czasow algorytmu okrela zatem zalenoci rekurencyjn T(n).
Dodajc stronami rozpisane wyraenie rekurencyjne i
dla n = 0
1
T (n) =
przeprowadzajc redukcj czynnikw identycznych otrzymuje
T
(
n

1
)
+
1
dla
n

si wyraenie: T(n) = n + 1.
Przedstawia ono czas wykonania algorytmu, ktry wynosi: T(n) = (n + 1)*tm
gdzie tm oznacza jednostkowy czas wykonania operacji mnoenia w okrelonym rodowisku.

1+ 5
2

= 1.61803

= 1 5 = 0.61803

F(0)

F(1)
F (n ) =

n n

5

R3.2

Zoono cigu Fibonacciego ronie wykadniczo

n:=2
n=0

F(5)

F(1)

R3.1

20

Algorytmy i Struktury Danych - wykad

Aby obliczy Fib(5), naley wyznaczy Fib(3) oraz Fib(4).


Aby obliczy Fib(4), obliczamy Fib(2) i Fib(3), std Fib(3) bdzie
liczone 2 razy
Aby obliczy Fib(7), Fib(3) oblicza si 5 razy.
Oglnie dla Fib(n) warto Fib(3) bdzie liczona Fib(n-2) razy.

n
5
10
20
30
40

Dodawanie
7
88
10945
1346268
165580140

Wywoanie
15
177
21891
2692337
331160281

Wyznaczenie Fib(n) wymaga: Fib(n+1)-1 dodawa, 2*Fib(n+1)-1 wywoa funkcji Fib().


Algorytm rekurencyjny jest praktycznie przydatny dla maych wartoci parametru.
Dla duych wartoci parametru liczby Fibonacciego mona oblicza z przyblionego wzoru
opartego na wspczynniku zotych proporcji.
Przyczyn nieefektywnoci algorytmu rekurencyjlong FibIter(int n)
nego jest powtarzanie tych samych oblicze, gdy
{
system zapomina co ju wczeniej obliczono.
if (n < 2) return n;
Lepszy efekt uzyskuje si zachowujc wczeniejsze wyniki i
long i = 2, wrk, a = 1, b = 0;
wykorzystujc je dla kolejnych oblicze.
for (; i<=n; i++) {
Iteracyjna implementacja algorytmu Fibonacciego zawiera
wrk = a; a += b; b = wrk; }
n-2 przebiegi ptli, w ktrych realizowane s:
return
a;
-trzy podstawienia,
}
-jedno dodawanie,
-zwikszanie zmiennej i.

Instytut Aparatw Elektrycznych


Algrm3
Dr J. Dokimuk

21

Algorytmy i Struktury Danych - wykad

3.3. Rekurencja zagniedona


Rekurencja zagniedona wystpuje wwczas gdy funkcja
jest zdefiniowana za pomoc samej siebie oraz jeeli uyta
jest jako jeden z parametrw.

g ( n ) = g ( 2 + g ( 2 n ))
n

dla n = 0
dla n 4
dla n > 4

Dobrym przykadem rekurencji zagniedonej jest funkcja Ackermanna:


dla n = 0
m + 1

A(n, m) = A(n 1, m)
dla n > 0 i m = 0
A(n 1, A(n, m 1)) dla pozostalych

16
A( 4,1) = 2 2 3 = 2 65536 3

Inna definicja funkcji Ackermanna jest nastpujca:


A(1, n ) = 2 n
A( m,1) = A( m 1, 2)

dla n 1
dla m 2

A( m, n ) = A( m 1, A(m, A(m, n 1))

dla m, n 2

N2 16

A(3, 2) = 22

N2 4

22

= 22

22

= 2 65536

3.4. Rekurencja kocowa


Rekurencja kocowa ma miejsce wwczas, gdy wystpuje tylko jedno wywoanie rekurencyjne
na samym kocu funkcji.
Jest ostatni wykonywan instrukcj a wczeniej nie byo innego woania rekurencyjnego.
#include <stdio.h>

void RekKoncowa(int n)
{
if (n>0) {
printf("%d ",n);
RekKoncowa(n-1);
}
}
main( )
// P34 rekurencja koncowa
{
int n=7; RekKoncowa(n);
return 0 ;
}
7654321

#include <stdio.h>

void Non_RekKoncowa(int n)
{
for (; n > 0; n--) printf("%d ",n);
}
main( )
{
int n=7; Non_RekKoncowa(n);
return 0;
}
Rekurencja kocowa jest inn odmian konstrukcji
ptlowych i moe by przez nie zastpiona.

3.5. Rekurencja porednia


Rekurencja porednia wystpuje wwczas, gdy funkcja f( ) wywouje siebie poprzez acuch
wywoa innych funkcji np.
funkcja F1() wywouje funkcj H(), ta za wywouje F1()
acuch wywoa porednich moe by dowolnej dugoci:
F()  h1()  h2()   Hn()  F()
_________________________________________________________________

Teoretycznie szybki algorytm rekurencyjny moe by realizowany znacznie


wolnej ni jego odpowiednik iteracyjny.
Bdy algorytmw rekurencyjnych:
 ze okrelenie warunku zakoczenia procesu rekurencyjnego,
 nieefektywna dekompozycja problemu.

Implementacja rekurencyjna zapewnia prostot i naturalno rozwizania


lecz jej wynik nie zawsze jest optymalny.

Instytut Aparatw Elektrycznych


Algrm3
Dr J. Dokimuk

22

Algorytmy i Struktury Danych - wykad

Anex Implementacja rekurencji funkcji w C++


Funkcja main() wywouje funcj F1(). Funkcja F1() wywouje F2(). Funkcja F2() wywouje F3().
Gdy funkcja F3() koczy dziaanie nastpuje powrt do F2(). Gdy koczy F2() powrt do F1().
Gdy koczy F1() nastpuje powrt do main().
Woania rekurencyjne przebiegaj identycznie a dotycz dziaa na wielu kopiach jednej funkcji.
Wywoanie funkcji zwizane jest z: -zapamitaniem jej adresu powrotu,
-przechowaniem zmiennych lokalnych i parametrw funkcji.
Jeeli funkcja F1() zawiera deklaracje zmiennej lokalnej x i wywouje funkcj F2() rwnie
zawierajc zmienn lokaln x, to zmienne o identycznych nazwach musz by rozrnialne.
Dane powysze przechowywane s w obszarze zwanym rekordem wywoania lub ramk stosu.
Obsuga wywoa funkcji w C/C++, realizowana jest poprzez dynamiczny przydzia pamici
na stosie programu, gdzie przechowywane s rekordy wywoa (activation record).
Struktura rekordu wywoa funkcji
1. warto zwracana: umieszczana bezporednio nad
rekordem wywoania procesu, wywoujcego dan funkcj.
2. adres powrotu: adres instrukcji bezporednio po
wywoaniu; umoliwia powrt do miejsca wywoania.
3. dowizanie dynamiczne: wskanik do rekordu wywoania
procesu wywoujcego funkcj.
4. wartoci zmiennych lokalnych: w przypadku gdy
przechowywane s w innym miejscu ich identyfikatory i
informacje o miejscu ich ulokowania.
5. wartoci parametrw funkcji: dla tablic adresy ich
pierwszych elementw.

rekord
wywoania
funkcji
F3()

param. i zm. lokalne


dowizania dynam.
adres powrotu
warto zwracana
rekord param. i zm. lokalne
wywoania dowizania dynam.
funkcji adres powrotu
F2()
warto zwracana
rekord param. i zm. lokalne
wywoania dowizania dynam.
funkcji adres powrotu
F1()
warto zwracana
main()

Rekord wywoa istnieje tak dugo, a funkcja dla ktrej


zosta stworzony, zakoczy swoje dziaanie.
Stanowi indywidualny bank danych dla funkcji, 1. Kady poziom rekurencji posiada swoje
wasne zmienne.
przechowujc niezbdne informacje do jej
poprawnego dziaania i powrotu.
2. Kademu wywoaniu odpowiada jeden
Kade wywoanie funkcji zwizane jest z tworzeniem
powrt. Wykonanie return na poziomie
nowego rekordu wywoa, co zapewnia waciw
3, powoduje powrt na poziom 2.
obsug rekurencji.
3. Instrukcje w funkcji rekurencyjnej
Wywoanie rekurencyjne tworzy kolejne kopie z
znajdujce si przed miejscem, w
poprzednich, pochodzcych od tego samego oryginau.
ktrym funkcja wywouje sam siebie,
Tworzone kopie maj indywidualne rekordy wywoa,
wykonywane
s
w
kolejnoci
wywoywania poziomw.
co sprawia, e s rozrnialne przez system.
4. Instrukcje znajdujce si po miejscu,
Przykad.
w ktrym funkcja wywouje sam siebie,
Podnoszenie liczby rzeczywistej
1
wykonywane s w kolejnoci odwrotnej
dla
n
=
0
do naturalnej potgi n okrela x n =
do kolejnoci wywoywania poziomw.
xn n -1 dla n > 0

zaleno rekurencyjna.
Funkcja main() wywouje funkcj Power(4.4, 2) jest to "pierwszy poziom rekurencji".
float Power(float x, int n)
{ float wrk=-999;
printf("poziom %d, wrk=%g\n", n,wrk);
if (n==0) wrk= 1;
else wrk = x*Power(x, n-1);
printf("POZIOM %d, wrk=%g\n", n,wrk);
return wrk;
}
main()
// P33a
{ float f;
f = Power(4.4, 2);
printf("Power=%g \n",f);
}

poziom 1: Power(4.4, 2)
poziom 2: Power(4.4, 1)
poziom 3:
Power(4.4, 0)
poziom 2, wrk=-999
poziom 1, wrk=-999
poziom 0, wrk=-999
POZIOM 0, wrk=1
POZIOM 1, wrk=4.4
POZIOM 2, wrk=19.36

poziom 3:
poziom 2:
poziom 1:

1
4.4
19.36

23

Algorytmy i Struktury Danych - wykad

ALGORYTMY
Dziel i
zwyciaj

Zachanne

Programowanie
dynamiczne

z
powrotami

4.1. Strategia dziel i zwyciaj (Divide and Conquer)


Istota strategii: podzia problemu na mniejsze o tej samej strukturze co problem gwny.
Dzielenie podproblemw na coraz mniejsze a otrzyma si zadanie tak maego rozmiaru,
e jego rozwizanie bdzie oczywiste lub znana bdzie efektywna metoda rozwizania.
czenie rozwizania wszystkich podproblemw w cao.

Dziel:
podzia problemu na mniejsze
Zwyciaj: rozwi mniejszy problem rekurencyjnie
Scal:
czenie rozwizanych podproblemw

Maksimum {4, 1, 6, 8, 2, 5, 7, 3}
dziel 
4168
2573
dziel 
4 1 6 8
2 5 7 3
zwyciaj  4
8
5
7
zwyciaj 
8
7
scal 
8

Zoono algorytmu rekurencyjnego, dziaajcego wedug strategii dziel i zwyciaj:


Dzielimy problem na k podproblemw o rozmiarze n/k kady.
Przyjmujemy, e jeeli rozmiar problemu jest may tzn. n < c (c pewna staa) to na jego
rozwizanie potrzebny jest stay czas, zatem jest klasy O(1).
dla n c
O (1)
T (n) =
kT ( n / k ) + ( n ) + (n ) dla n > c

(n) czas dzielenia problemu na k podproblemw.


(n) czas scalania rozwizanych podproblemw.

4.1.1. Wyszukiwanie binarne (Binary Searching)


Problem: Sprawdzenie czy warto key znajduje si w posortowanej tablicy o rozmiarze n.
Dane: Klucz key, rozmiar tablicy n, tablica A z posortowanymi kluczami.
Wynik: Zmienna ind lokalizujca element key w tablicy A (ind=-1, gdy brak element).
Poszukiwanie elementu w cigu uporzdkowanym:
key = 4
(czy key > 25)
a1, a2, a3,an/2-1,

an/2 an/2+1, an/2+2,,an-1, an

2 4 8 11 14 25 27 33 34 45 55

Problem: Znale warto maksymaln i minimaln zbioru X.


Dane:
Tablica X[1..n] z danymi.
Wyniki: Wartoci max i min.

3. Podziel wektor X na podwektory X1 oraz X2;


4. Wykonaj algorytm dla (X1, max1, min1);
5. Wykonaj algorytm dla (X2, max2, min2);

min = Min(min1, min2)


max = Max(max1, max2)

Operacja dominujca algorytmu MaxMin: porwnywanie.

dla n = 1 brak porwna

0
dla n = 1

Zoono czasowa: T ( n ) = 1
dla n = 2
2T ( n / 2) + 2 dla n > 2

T (n ) =

3
n2
2

dla n = 2 jedno porwnanie

na kocu porwnuje si najwikszy i najmniejszy element z obu podzbiorw.


4.1.3. Sortowanie przez scalanie
Dziel:
podziel n-elementowy cig na dwa podcigi n/2-elementowe.
Zwyciaj: wykonaj sortowanie podcigw, stosujc technik rekurencyjn.
Scal:
pocz dwa posortowane podcigi w jeden cig wyjciowy.
MergeSort(b, e, X[ ])
if b < e then
p (b + e)/2
MergeSort(b, p, X)
MergeSort(p+1, e, X)

Merge(b, p, p+1,e, X)

Sortowanie { 8, 3, 6, 5, 4, 7, 2, 1 }
dziel
8365
4721
dziel
83 65
47 21
dziel
8 3 6 5 4 7 2 1
zwyciaj
38 56 47 12
3568
1247
zwyciaj
scal
12345678

// tablica X[be]
// b = e to dugo 1
// rodkowy indeks
// dziel X[bp]
// dziel X[p+1...e]
// scalanie podtablic

Powrt z wywoa rekurencyjnych rozpoczyna si z cigami


jednoelementowymi, ktre scalane s w cigi dwuelementowe, nastpnie w cigi wieloelementowe.

Dziel: (czy key > 8)  2 4 8 11 14


Dziel: (czy key > 2) 
2 4
Dziel: (czy key > 4) 
4
binarnego Zwyciaj: idn = 2

50 25 18 40 88 19 4 72 15
50 25 18 40 88
50 25 18
50 25
25

18

40 88
40

88

18 25 50

poziom 2

19 4 72 15
19 4
19

72 15
4

72

poziom 3

15 poziom 4
poziom 5

40 88

18 25 40 50 88
R4.1

poziom 1

50

25 50

Niech n = 2k. Najgorszy przypadek wystpi, gdy key jest

dla n = 1
1
wikszy (mniejszy) od wszystkich elementw tablicy.
T (n) = lg(n) + 1
Jeeli n=1 nastpi porwnanie z key, a nastpnie T (n) =
T
(
n
/
2
)
+
1
dla n > 1

rekurencyjne woanie dla l > p, co koczy dziaanie.

p = (b + e)/2
MaxMin(b, p, X, min1, max1)
MaxMin(p+1, e, X, min2, max2)

6. Jeeli max1>max2 to max = max1, przeciwnie max=max2;


7. Jeeli min1<min2 to min = min1, przeciwnie min = min2.

przebiega zgodnie z regu:


IF key > an/2 then sprawdzaj prawy podcig
else sprawdzaj lewy podcig.

Algorytm
rekurencyjny
wyszukiwania
wykorzystuje rekurencj kocow.
Mona j zastpi iteracj, co pozwala unikn BinarySRek(A[ ]; int l, p; type key)
budowania stosu, o gbokoci do lg(n) + 1.
if (l > p) then return -1; // brak elementu
BinSearch(array A, int Left, Right, key)
mid (l + p)/2;
do forever
if (A[mid]=key) then return mid;
if (Left >Right ) then return -1
if (key<A[mid]) then
m= (Right + Left )/2
return BinarySRek(A, l, mid-1, key);
if (key < A[m] then Left =m -1
else
else if (key > A[m]) then Left =m + 1 else return m;
return BinarySRek(A, mid+1,p, key);

MaxMin(b, e; X[ ], min, max)


if b = e then min = max = x1
if e b=1 then
if x1<x2 then { min=x1; max=x2 }
else { min=x2; max=x1 }

1. Jeeli n = 1 to max = min = x1;


2. Dla n = 2, jeeli x1 > x2 to max = x1 przeciwnie max = x2;

Podzia

Brak uniwersalnej metodologii budowy algorytmw, gdy jest to proces indywidualny i twrczy.

Gdy problem zapisany jest w postaci rekurencyjnej,


wwczas strategia dziel i zwyciaj czsto moe
by realizowana wedug schematu:

24

Algorytmy i Struktury Danych - wykad

4.1.2. Wyszukiwanie Maksimum i Minimum

4. METODY PROJEKTOWANIA ALGORYTMW


Wiele algorytmw wykorzystuje okrelone
schematy. Znajc te schematy mona szybciej
rozwizywa nowe problemy, stosujc znane
metody.

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

Scalanie

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

poziom 4

4 19

15 72
4 15 19 72

4 15 18 19 25 49 50 72 88

poziom 3
poziom 2
poziom 1

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

25

Algorytmy i Struktury Danych - wykad

Scalanie dwch posortowanych podcigw


Merge(X1, X2, Xscalony)
1. Porwnaj pierwsze elementy obu podcigw
i mniejszy wstaw do cigu nowego.
2. Powtarzaj proces (1) a jeden z cigw bdzie pusty.
3. Pozostay cig docz na koniec cigu nowego.
void Merge(int first1, int last1, int first2, int last2, int A[ ])
{
int Temp[MaxArray], ind=0, ind1, ind2, num;
ind1 = first1; ind2 = first2;
num = last1 - first1 + last2 - first2 + 2;
while ((ind1 <= last1) && (ind2 <= last2)) {
if (A[ind1] < A[ind2]) Temp[ind++] = A[ind1++];
else Temp[ind++] = A[ind2++];
}
if (ind1 > last1) Move(ind2, last2, A, ind, Temp);
else
Move(ind1, last1, A, ind, Temp);
Move(temp, 0, num-1, A, first1);
}

2 4 16 18 11 13 15 20 30
2
4 16 18
11 13 15 20 30
2 4
16 18
11 13 15 20 30
2 4 11
16 18
13 15 20 30
2 4 11 13
16 18
15 20 30
2 4 11 13 15
16 18
20 30
2 4 11 13 15 16
18
20 30
2 4 11 13 15 16 18
20 30
2 4 11 13 15 16 18 20 30

Niech r, s oznaczaj dugoci


wejciowych podcigw X1, X2.
W najgorszym przypadku zoono
scalania wynosi: T(r, s) = r + s -1
Moe to wystpi, gdy s-1 elementw
z X2 zostanie umieszczonych na Wy, a dopiero potem nastpuje umieszczenie r elementw z X1.
void Move (int lo1, int hi1, int W1[ ], int lo2, int W2[ ])
{
while (lo1 <= hi1) W2[lo2++] = W1[lo1++];
}

Zoono algorytmu MergeSort


Dla n = 1 zoono jest O(1) (cig posortowany) w przeciwnym razie naley rozpatrzy 3 etapy.
Dziel:
Znalezienie rodka nie zaley od licznoci zbioru, zatem (n) = O(1).
Zwyciaj: Rozwizywane s 2 podproblemy o rozmiarze n/2. czny czas wynosi 2T(n/2).
Scal:
Liczba porwna zaley od wzajemnej relacji elementw w obu podtablicach.
W najgorszym przypadku wynosi n 1 dla n-elementowej tablicy wyjciowej.

dla n = 1
0
T (n) =
T (n ) = n lg(n ) ( n 1)
2
T
(
n
/
2
)
+
n

1
dla n > 1

klasa O(nlg(n))

4.1.4. Uwagi
Program P41a1 realizuje algorytm poszu- int Szukanie_Lin_R(int A[ ], int l, int p, int key)
kiwania elementu w tablicy A, zgodnie ze {
if (l > p) return -1;
// brak elementu
strategi dziel i zwyciaj.
Problem gwny rozbijany jest na
podproblemy o analogicznej strukturze lecz
mniejszym stopniu zoonoci, gdy z rozmiaru
n schodzi si do n-1, poprzez sukcesywne
zwikszanie zmiennej l.
Implementacja zrealizowana zostaa z
wykorzystaniem techniki rekurencyjnej, dla
strategii dziel i zwyciaj.
Popeniony zosta istotny bd:
nieefektywna dekompozycja problemu.

else if (A[l] == key) return l;


else return Szukanie_Lin_R(A, l+1, p, key);
}
#include <stdio.h>
int main() //P41a1 Liniowo-rekurencyjne szukanie
{
int n=10, A[10] = {10,8,6,9,-11,15,13,19,33,23},
key=13, l=0, p=n-1, res;
res = Szukanie_Lin_R(A, l, p, key);
printf(" Znaleziono na pozycji=%d \n", res);
}
Znaleziono na pozycji = 6

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

26

4.2. Algorytmy zachanne (greedy algorithm)


Realizuj najlepsz w danej chwili strategi wyboru a nastpnie rozwizuj podproblemy,
wynikajce z podjtej decyzji.
Nie analizuj czy w nastpnych krokach dziaania te bd optymalne.
Nie trac czasu na analizowanie pniejszych skutkw aktualnie podjtej decyzji.
Wybierana jest cieka lokalnie optymalna, zakadajc, e moe ona prowadzi do rozwizania
globalnie optymalnego.

Strategia algorytmw zachannych nie gwarantuje optymalnych rozwiza.


Dla wielu problemw s wystarczajco dokadne w kontekcie niezbdnych nakadw na ich opracowanie.
Metoda odpowiednia dla pewnej klasy zagadnie optymalizacyjnych jak:
wybr najkrtszej drogi w grafie,
wyznaczenie optymalnej kolejnoci wykonywania pewnych czynnoci.
Strategia algorytmw zachannych dobrze koresponduje z natur ludzk.
Czowiek otrzymujc zadanie, czsto zadawala si rozwizaniem szybkim i w miar poprawnym,
lecz niekoniecznie optymalnym.
4.2.1. Maksimum funkcji f(x)
1. We pewn liczb a0 i oblicz warto funkcji f(a0).
2. Powiksz liczb bazow o sta warto, a0 = a0 + i oblicz warto funkcji ponownie f(a0).
3. Jeeli warto funkcji narasta to kontynuuj krok (2), przeciwnie funkcja osigna maksimum
dla wartoci poprzedniej ( ai-1 ).
Jeeli otrzymane rozwizanie nie stanowi globalnego maksimum to przynajmniej znaleziono maksimum lokalne.
4.2.2. Problem kasjera
Naley wyda reszt wysokoci Z.
Dostpne s banknoty i monety w nominaach m1,m2,mk, speniajce zaleno: m1 < m2 <<mk,
Naley okreli najmniejsz liczb nominaw niezbdn
Wydanie reszty w wysokoci 87gr
do wydania reszty Z.
 W pierwszym etapie wyda 50 gr
Rozwizanie: Kasjer rozpoczyna wydawanie reszty od  Nastpnie wyda 20 gr (zostanie 17)
najwikszego nominau, utrzymujc t zasad  Kolejno wyda 10 gr (zostanie 7)
 W kocu wyda 5 gr oraz 2 gr.
w kadym kroku powstajcej rnicy.
Rozwizanie ma charakter metody zachannej, gdy w kadym kroku minimalizowana jest
liczba nominaw.
Kasjer wyda 5 monet co jest liczb minimaln i algorytm zachanny okaza si w tym przypadku optymalnym.
Czy algorytm kasjera jest optymalny globalnie dla kadej struktury nominaw?
Dokonywane wybory mog zalee od dotychczasowych decyzji lecz nie s
uzalenione od przyszych wyborw lub metod rozwiza podproblemw.
Rozwizanie dokonywane jest w sposb zstpujcy tzn. podejmowane s kolejne
decyzje zachanne, stopniowo redukujc podproblemy do coraz mniejszych.

Metoda dowodzenia, e wybr strategii zachannej prowadzi do rozwizania optymalnego globalnie:


 Dowodzi si, e mona problem sprowadzi do rozwizania, rozpoczynajcego si podjciem
decyzji zachannej w pierwszym kroku.
 Wykazuje si, e dokonany wybr redukuje problem do podobnego o mniejszym rozmiarze.
 Uzasadnia si przez indukcj, e strategi zachann mona stosowa w nastpnych krokach.
 Jeeli wykae si, e udao si sprowadzi problem do podobnego, lecz o mniejszych
rozmiarach to dowd poprawnoci algorytmu sprowadzony zosta do udowodnienia
optymalnej podstruktury rozwizania optymalnego.
Optymaln podstruktur wykazuje problem, jeeli optymalne rozwizanie jest funkcj
optymalnych rozwiza podproblemw.
Wasno wyboru zachannego: za pomoc zachannych wyborw (lokalnie optymalnych)
mona uzyska globalnie optymalne rozwizanie.

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

27

4.2.3. Problem plecakowy (knapsack problem)


Cigy problem plecakowy
Mamy n pojemnikw z substancjami vn, gdzie i-ty pojemnik way wi kg i jego warto wynosi pi z.
Naley plecak o wypornoci cap wypeni najwartociowszymi substancjami.
Cigo problemu wynika z moliwoci zabrania dowolnej iloci kadej substancji.
Rozwizanie cigego problemu plecakowego:
1. Oblicz warto masy jednostkowej kadej substancji pi / wi (warto/waga)
p
p
p
2. Posegreguj substancje wedug rosncych cen jednostkowych: 1 2 L n
w1 w2
wn
3. Wybierz najpierw najwiksz ilo substancji najbardziej wartociowej.
4. Jeeli wystpi brak najlepszej to we nastpn pod wzgldem ceny jednostkowej.
5. Wypeniaj plecak zgodnie z punktem (4) a do jego zapenienia.
Wymagane jest sortowania cen jednostkowych, zatem algorytm jest klasy O(nlg(n)).
Dyskretny problem plecakowy dylemat zodzieja
Mamy n rnych przedmiotw, gdzie przedmiot i-go typu way wi kilogramw i jego warto
wynosi pi z. Naley wypeni plecak takim przedmiotami, by ich czna warto bya jak
najwiksza (suma rozmiarw zabranych przedmiotw nie moe przewysza pojemnoci cap plecaka ).
Dyskretno problemu wynika z faktu, e nie mona zabra uamkowej czci przedmiotu.
n wi [kg] pi [z] pi/wi [z/kg]
Prba rozwizania dyskretnego problemu plecakowego
Mamy 3 przedmioty oraz plecak o wypornoci cap = 25kg.
1
5
60
12
Stosujc strategi zachann jak dla problemu cigego, 2
10
100
10
naleaoby jako pierwszy wybra przedmiot nr 1.
3
15
120
8
Nie jest to rozwizanie optymalne. Wybr optymalny to 2 i 3.
Aby w dyskretnym problemie plecakowym osign optymalny wybr, naley przed
podjciem decyzji, ktry przedmiot zabra: porwna rozwizanie podproblemu, w ktrym
przedmiot wystpuje z podproblemem, w ktrym nie jest on brany jeszcze po uwag.
Rozwizanie optymalne w dyskretnym problemie plecakowym nie jest strategi zachann.
Problem plecakowy wykazuje optymaln podstruktur.
Niech w plecaku bdzie najwartociowszy adunek o masie M cap.
Usumy z plecaka i-ty przedmiot. Pozostaa zawarto o wadze cap wi te
jest najwartociowszym adunkiem jaki mona wybra z n - 1 przedmiotw .
Rekurencyjne rozwizanie zakada, e za kadym razem, gdy wybiera si przedmiot i umieszcza go w plecaku, mona znale optymalny sposb zapenienia pozostaej czci plecaka.
Mamy plecak o pojemnoci cap optymalnie spakowany.
#include<stdio.h>
#define nTyp 5
Wyjmujemy z niego przedmiot o rozmiarze s.
Powstaje sytuacja jakbymy mieli plecak o pojemnoci int size[nTyp] = { 3, 7, 12, 15, 22 };
int cost[nTyp] = { 5, 2, 10, 15, 30 };
space = cap - s wypeniony optymalnie.
W rzeczywistoci nie wiemy, jak najlepiej spakowa plecak int Knap(int cap)
o pojemnoci cap, zatem nie znamy wartoci s.
{ int i, space, total, max;
I. Rezerwujemy w plecaku miejsce na 1-szy przedmiot, for (i=0, max=0; i < nTyp; i++) {
wypeniamy optymalnie reszt plecaka, a potem
space = cap - size[i];
wkadamy 1-szy przedmiot i patrzymy na czny koszt.
if (space >= 0) {
II. Nastpnie zaczynamy od nowa, zostawiajc miejsce na
total = Knap(space) + cost[i];
2-gi przedmiot, wypeniajc plecak i dokadajc 2-gi
if (total > max) max = total;
przedmiot.
III itd. dla wszystkich przedmiotw.
}
Rozwizaniem problemu jest plecak o najwikszej cznej
}
wartoci spord wypenionych tym sposobem.
Niech Knap(cap) zwraca czn warto przedmiotw return max;
}
optymalnie wypeniajcych plecak o pojemnoci cap.
int main()
Jest ona rwna: max(Knap(cap - si) + ci), i = 1n.
{ // P4_4c
gdzie si oraz ci rozmiary i wartoci przedmiotw.
printf("maxVal=%d\n", Knap(50));
Program dla kadego przedmiotu oblicza maksymaln warto, ktr
}
maxVal = 80
mona uzyska, a nastpnie pobiera najwiksz z tych wartoci.

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

28

Algorytmy i Struktury Danych - wykad

4.2.4. Problem wyboru zaj

Poszukiwanie najwikszego zbioru wzajemnie zgodnych czynnoci.


Dany jest zbir S = {1, 2, n} zaj, dla ktrych przydzielona zostanie sala wykadowa, w ktrej
tylko jedno zajcie moe odbywa si w danej chwili.
Kade zajcie rozpoczyna si w chwili bi i koczy w chwili ei.
Wytypowane zajcie o numerze i zajmuje prawostronnie otwarty przedzia czasu [bi, ei).
Zajcia o numerach i oraz j s zgodne, jeeli przedziay [bi, ei) oraz [bj, ej) nie zachodz na siebie.
Odpowiada to zalenociom bi ej. lub bj ei mwicym, e czas rozpoczcia bi nie jest
wczeniejszy ni czas zakoczenia ej.
Problem wyboru zaj sprowadza si do wyboru najwikszego podzbioru parami zgodnych zaj.

Zaoenie: zajcia zostay uporzdkowane ze wzgldu na czas ich zakoczenia:


e1 e2 en .
Wartoci bi i ei przechowywane s w tablicach b i e.
Zbir A zawiera wybrane zajcia.
Selector(b, e)
n length(s)
A {1}
j1
for i 2 to n do
if bi ej then A A

// zwraca zbir A wybranych zaj


// wybranie zajcia 1-go i wstawienie go do zbioru wynikowego A
// przypisanie zmiennej j numeru zajcia 1-go (wybranego)

{i} //docza do zbioru A i-tego zajcia zgodnego, ktrego czas rozpoczcia


//nie jest wczeniejszy ni czas zakoczenia zajcia ostatnio dodanego do A

ji
return A

// j zawiera informacj o ostatnio dodanym do zbioru A zajciu

Istot algorytmu jest wybieranie zawsze zaj majcych najwczeniejszy czas


zakoczenia wrd zaj, ktre mog by doczone do zbioru A.
Taki wybr w kadym kroku maksymalizuje ilo wolnego czasu pozostajcego do dyspozycji.
Jest algorytmem zachannym (lokalnie optymalnym) i globalnie optymalnym.
Zoono czasowa algorytmu jest klasy O(n) (przy spenionych zaoeniach).
Przykad 4.1.
Dany jest 8-elementowy zbir zaj 2-, 3- i 4-godzinnych oraz
sala dostpna w godzinach 8 20.
W 1-szym kroku do zbioru A przypisane zostanie zajcie nr 1.
Jeeli czas rozpoczcia bi zajcia 2-go oraz dalszych jest
wczeniejszy ni czas zakoczenia ei zajcia ostatnio
przyjtego (pole kolorowane), to zajcie takie jest odrzucane.
W przeciwnym razie jest ono wybrane i wczone do zbioru A.

i
1
2
3
4
5
6
7
8

nazwa
C1
C2
W1
L1
C3
L1
W1
L2

dT
3
3
2
4
3
4
2
4

bi
815
915
1115
1215
1315
1315
1515
1615

ei
11
12
13
16
16
17
17
20

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

29

4.3. Programowanie dynamiczne


Programowanie oznacza tabelaryczn metod rozwizywania problemw
i nie jest zwizane z programowaniem w okrelonym jzyku.
Wykorzystuje korzyci z rekurencyjnego formuowania problemu
bez uywania rekurencji w procesie implementacji.
Problem rzdu N podzieli si na podproblemy o mniejszej zoonoci i znanych rozwizaniach.
Majc rozwizania problemw elementarnych naley znale optymalne rozwizanie
podproblemu wyszego rzdu i kontynuowa obliczenia, a do rozwizania problemu rzdu N.
Metoda rozwinita zostaa w latach 50-tych przez Richarda Bellmana.
Jest rozwiniciem optymalnoci Bellmana, ktra zaleca aby na kadym kroku podejmowana
bya najlepsza decyzja z uwzgldnieniem stanu wynikajcego z poprzednich decyzji.
Koncepcja programowania dynamicznego zbiena jest ze strategi dziel i zwyciaj, aczkolwiek
dotyczy sytuacji, kiedy podprogramy zawieraj te samy podproblemy.
Strategia dziel i zwyciaj w duo wikszym stopniu absorbuje zasoby komputerowe ni jest to
rzeczywicie potrzebne, gdy wielokrotnie rozwizywany jest ten sam problem (liczby Fibonacciego).
Strategia programowania dynamicznego zakada jednorazowe rozwizanie danego podproblemu
i zapamitanie jego wyniku w tabeli, co eliminuje wielokrotne liczenie tego samego podproblemu.
Programowanie dynamiczne zmniejsza czas dziaania funkcji rekurencyjnych tak,
e jest on rwny co najwyej czasowi niezbdnemu do obliczenia funkcji dla
wszystkich argumentw mniejszych (rwnych) od danego argumentu.
Metoda powysza stosowana jest czsto do zagadnie optymalizacyjnych, w ktrych moliwe
jest wiele rnych rozwiza, przy czym z kadym z nich zwizany jest pewien koszt.
Metoda wstpujca (bottom-up) to technika rozpoczynajca obliczenia od najmniejszych
podproblemw, poprzez coraz wiksze, zapamitujc po drodze wszystkie
wczeniejsze rozwizania w odpowiedniej tablicy.
Etapy projektowania algorytmw technik programowania dynamicznego
1. charakterystyka struktury rozwizania optymalnego;
2. rekurencyjna definicja kosztw (zapotrzebowania na zasoby) szukanego rozwizania;
3. obliczenie optymalnych kosztw metod wstpujc;
4. budowanie optymalnego rozwizania na podstawie wczeniejszych wynikw, ktre powinny
by zapamitywane w etapie 3-cim.
Cechy problemu, zapewniajce efektywno techniki programowania dynamicznego
1. Problem powinien wykazywa optymaln podstruktur, ktra czsto sugeruje waciw
przestrze dla tworzonych podproblemw. Wybranie losowo jednej z wielu dostpnych
podprzestrzeni, moe by przyczyn wykonywania duo wicej oblicze, ni jest potrzeba;
2. Odpowiednio maa przestrze istotnie rnych podproblemw.
Problem optymalizacyjny na wasno wsplnych podproblemw, ktre w metodzie
programowania dynamicznego obliczane s raz i zapamitywane aby przy ponownym ich
wystpieniu mona byo atwo sign po rozwizania.
Metodyka programowania dynamicznego
koncepcja
budowa rekurencyjnego modelu rozwizujcego problem (z okreleniem przypadkw elementarnych),
budowa tablicy do przechowywania rozwiza elementarnych lub podproblemw;
inicjacja
zapenianie tablicy obliczonymi wartociami, odpowiadajcymi przypadkom elementarnym;
realizacja
w oparciu o wartoci wpisane do tablicy, obliczanie rozwiza podproblemw coraz to
wyszego rzdu, uywajc formuy rekurencyjnej, oraz wpisywanie ich do tablicy;
postpowanie kontynuowane jest a do osignicia podanego rezultatu.

Programowanie dynamiczne eliminuje wszystkie przypadki obliczania tej samej wartoci w


procedurze rekurencyjnej, o ile mona zapamita wartoci funkcji dla argumentw mniejszych od
argumentu biecego jej wywoania.

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

30

Algorytmy i Struktury Danych - wykad

4.3.1. Obliczanie cigu Fibonacciego


koncepcja: -wzr rekurencyjny jest powszechnie znany;
-deklarujemy tablic F[maxN] do przechowywania wartoci elementarnych;
inicjacja: -wartociami pocztkowymi bd warunki pocztkowe F[0] = 0 oraz F[1] = 1;
realizacja: -rozwizaniem problemw wyszego rzdu s wartoci Fib(n) dla n 2, zapamitawane jako: F[n] = F[n-1] + F[n-2]

+
0

// metoda wstpujca
long FibD1(int arg)
{ if (arg <= 0) return 0;
if (arg == 1) return 1;
long F[47] = { 0, 1 }; // inicjalizacja
for (int i = 2; i <= arg; i++)
F[i] = F[i-1] + F[i-2] ;
return F[i -1];

+
1

13
R4.2

Funkcja FibD1 realizuje programowanie dynamiczne


wstpujce, wyliczajc w kadym kroku biece wartoci
funkcji
na
podstawie
uprzednio
obliczonych
i
zapamitanych wartoci. Mona zrezygnowa z tablicy F,
}
Fib(46) = 1836311903
w przypadku rejestrowania ostatnich dwu wartoci.
Zoono obliczeniowa proporcjonalna do n.
long FibD2(int arg) // metoda zstpujca
W programowaniu dynamicznym zstpujcym
funkcja rekurencyjna zapisuje kad obliczon
przez siebie warto na kocu.
Sprawdza zapisane wartoci na pocztku, by
nie oblicza jeszcze raz tych samych wartoci.

Nastpuje redukcja liczby wywoa rekurencyjnych.

{ if (arg <= 0) return 0;


static long F[maxN];
// zerowanie tablicy F
if (arg == 1) return F[1] = 1;
if (F[arg] != 0) return F[arg]; // czy ju jest wynik

if (arg > 1)
return F[arg] = FibD2(arg-1) + FibD2(arg-2);
}

4.3.2. Dyskretny problem plecakowy


i 1 2 3 4 5
Mamy plecak o rozmiarze cap = 10 i zbir przedmiotw (indeks i).
warto pi 6 4 5 7 10
 kada rzecz moe by wybrana co najwyej raz,
waga wi 6 2 3 2 3
 kolejno rozpatrywanych rzeczy jest bez znaczenia.
Sprowadzamy problem do najmniejszego, czyli zaczynamy wypenia plecak o pojemnoci 1kg.
Tablica P[i, j] zawiera wartoci j-tego plecaka wypenionego rzeczami (1, i ).
Pola tablicy P wypenia si wierszami: w 1-szym uwzgldnia si tylko rzecz nr1,
w 2-gim dysponujemy 2-ma rzeczami (nr1 i nr2),
w kolejnych wierszach narasta liczba rzeczy, ktre moemy dowolnie woy do plecaka.
Tablica Q skojarzona jest z tablic P i pokazuje, ktre rzeczy zostay woone.
Warto Q[i, j] = 1 oznacza, e i-t rzecz ostatnio woono do plecaka o pojemnoci j.
Tablica Q umoliwia identyfikacj numerw rzeczy w plecaku poprzez ich odejmowanie.
P[i, j] wartoci plecaka o pojemnoci j
i /kg
1 /6
2 /2
3 /3
4 /2
5 /3

1
0
0
0
0
0

Narastajce rozmiary plecaka j [kg]


2 3 4
5
6
7
8
9
10
0 0
0
0
6
6
6
6
6
2:4 2:4 2:4
2:4 1:6 1:6 1,2:10 1,2:10 1,2:10
2:4 3:5 3:5
2,3:9 2,3:9 2,3:9 1,2:10 1,3:11 1,3:11
4:7 4:7 2,4:11 3,4:12 12 16 2,3,4:16 16 1,2,4:17
7 10 11
17 17 21 3,4,5:22 22
26

Q[i, j] czy i-t rzecz ostatnio woono do j


i
1
2
3
4
5

Narastajce
2 3 4
0 0 0 0
0 1 1 1
0 0 1 1
0 1 1 1
0 0 0 0
1

rozmiary plecaka [j ]
5 6 7 8 9 10
0 1 1 1 1 1
1 0 0 1 1 1
1 1 1 0 1 1
1 1 1 1 1 1
0 1 1 1 1 1

Q5, 10 = 1 oznacza, e rzecz nr 5 o wadze 3 kg zostaa woona do plecaka.


Nowa pojemno plecaka: space1=cap 3 = 7, sprawdzamy element Q4, 7 (rzecz nr 4  2kg).
Nowa pojemno plecaka: space2= space1 2 = 5, sprawdzamy element Q3, 5 (rzecz nr 3  3kg).
Nowa pojemno plecaka: space3= space2 3 = 2, sprawdzamy element Q2, 2 (rzecz nr 2  2kg).
Nowa pojemno plecaka: space4= space3 2 = 0, zatem wybrano rzeczy: 2, 3, 4, 5.

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

31

Algorytmy i Struktury Danych - wykad

Cakowita zoono przedstawionego algorytmu plecakowego jest proporcjonalna do liczby


elementw tablicy P[n, W], gdzie n jest liczb rzeczy, za W maksymaln pojemnoci plecaka.
Nie istnieje adna relacja midzy n i W, std dla danego n warto W moe by dowolnie dua.
Im warto W staje si wiksza (ciarwka), tym efektywno algorytmu maleje, i moe
by mniej wydajny od algorytmu siowego (rozpatrzenia wszystkich podzbiorw).
Implementacja problemu plecakowego pozwala zastpi tablice dwuwymiarowe P i Q wektorami.
Ponadto kada rzecz moe by wybrana dowoln liczb razy.
Implementacj
prowadzca
do
liniowej
zoonoci czasowej jest modyfikacja algorytmu
rekurencyjnego Knap, poprzez zapisywanie w
tablicy maxK obliczonych wczeniej wartoci.
Prowadzi to do ograniczenia liczby wywoa
rekurencyjnych.
Pamitane dodatkowo w funkcji Knap1 indeksy
przedmiotw,
umoliwiaj
odtworzenie
zawartoci plecaka po wykonaniu oblicze, gdy
tablica S zawiera rozmiary przedmiotw wybrane
przez funkcj.
space=cap=17; w plecaku znajduje si przedmiot
o rozmiarze S[17] = 3;
rozmiar plecaka po wyjciu tego przedmiotu:
space S[17] = 17 3 =14  S[14] = 7;
space1 = 14;
rozmiar plecaka po wyjciu kolejnego przedmiotu:
space1 S[4] = 14 7 = 7  S[7] = 7;
Wybrano przedmioty A, C, C majce sumaryczn
warto 24, zatem optymalnie.

#define num 5
int size[num] = {3, 4, 7, 8, 9};
int cost[num] = {4, 5,10,11,13};
int maxK[60], S[60];

0 1 2 3 4

s 3 4 7 8 9
c 4 5 10 11 13
A B C D E

int Knap1(int cap)

cap S
0: 3
1: 3
3
2:
if (maxK[cap] != 0) return maxK[cap];
3: 3
4: 4
for (i = 0, max = 0; i < num; i++)
5: 4
if ((space = cap - size[i]) >= 0) 6: 3
if ((t = Knap1(space) + cost[i]) > max) {7: 7
8: 8
max = t; maxi = i;
9: 9
}
10: 3
3
11:
maxK[cap] = max;
12: 0
S[cap] = size[maxi]; // rozmiary przedmiotw 13: 3
14: 7
return max; // zwraca max. warto plecaka
15: 0
}
16: 0
17: 3
maxVal = 24 dla cap = 17
{ // modyfikacja funkcji rekurencyjnej P4_4c1
int i, space, max, maxi = 0, t;

Funkcja Knap2 realizuje metod programowania


wstpujcego
Zaczyna od samego dou tj. od plecaka o
pojemnoci 0, i rozwaa kolejno pojemnoci a
do znamionowej cap, zapamitujc rozwizania
podproblemw w miar ich obliczania w tablicy
maxK.
Nastpnie odszukuje si zapisane wartoci, gdy s
one potrzebne, zamiast wykonywa wywoania
rekurencyjne.

#define num 5
int size[num] = { 3, 7, 12, 15, 22 };
int cost[num] = { 5, 2, 10, 15, 30 };

int Knap2(int cap)


{

//P4_4b
// metoda wstepujca

Int maxK[500] = {0}, max, i, type, total, space;


for(i=1; i <= cap; i++) {
max = -3333;

for(type=0; type < num; type++)


if((space = i-size[type]) >=0) {
total = maxK[space] + cost[type];
if(max<total) max = total;
}

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

4.3.3. Wspczynniki dwumianu Newtona


Liczb kkombinacji zbioru nelementowego opisuje rekurencyjna zaleno C(n, k).

5,3

dla n = k lub k = 0
1
n

C ( n, k ) = = n 1 n 1
k
+
dla 0 < k < n
k k 1
int Dwumian(int n, int k)
{ // n k
if ((n==k) || (k==0)) return 1;
else
return Dwumian(n-1,k)+Dwumian(n-1,k-1);
}

4,3
3,3
1

Trzy kryteria wyboru kolejnych rzeczy do plecaka:


1. wybiera najcenniejsze rzeczy, czyli w kolejnoci nierosncych wartoci,
2. wybiera rzeczy zajmujce najmniej miejsca, czyli w kolejnoci niemalejcych wag,
3. wybiera rzeczy najcenniejsze w stosunku do swojej wagi, czyli w kolejnoci nierosncych
wartoci ilorazu warto/waga, czyli jednostkowej warto rzeczy.
Powysze kryteria wyboru s przejawem strategii zachannej, w ktrej zawarto plecaka
kompletowana jest krok po kroku i kada decyzja dokonuje wyboru najlepszego na danym etapie, z
oczekiwaniem, e ostatecznie doprowadzi to optymalnego rozwizania.
Strategia ta nie zawsze gwarantuje optymalne rozwizanie dyskretnego problemu plecakowego.
Strategia programowania dynamicznego gwarantuje rozwizanie optymalne.

4,2

3,2

3,2

2,2 + 2,1

2,2 + 2,1

3,1
2,1 + 2,0

1 1,1 + 1,0 1 1,1 + 1,0 1,1 + 1,0 1

1
1
1
1 1
Algorytm rekurencyjny na zoono
wykadnicz, wynikajc z powtarzajcych si wywoa funkcji.

R4.3

Programowanie dynamiczne wymaga tablicy do przechowywania czstkowych oblicze.


Wemy tablic B(n, k), w ktrej wiersze odpowiadaj wartociom n, za kolumny wartociom k.
i j 0
dla i = j lub j = 0
1
0
1
B(i 1, j) + B(i 1, j 1) dla 0 < j < k
1
1
2
i = 0...n
j = 0...k
1
3
1
Warto C(n, k) znajdziemy na skrzyowa4
1
niu n-tego wiersza i k-tej kolumny.
5
1
Najpierw oblicza si pierwszy wiersz (0,0),
6
1
nastpnie 2-gi wiersz pozycje: (1,0) i (1,1),
1
dalej 3-ci wiersz pozycje: (2,0), (2,1), (2.2), 7
8
1
itd. a do znalezienia szukanej wartoci.
9
1
B(i, j) =

Algorytm wypeniania tablicy Pascala


-P(0,0) 1
-Wykonaj:
dla kadego wiersza i (1, n)
B(i, 0) B(i, i) 1
dla kadej kolumny j (1, i - 1)
B(i, j) B(i-1, j) + B(i-1, j-1)

maxK[i] = max > maxK[i-1] ? max : maxK[i-1];


}
return maxK[cap]; // zwraca max. warto plecaka
}
maxVal = 80 dla cap = 50

32

Algorytmy i Struktury Danych - wykad

1
2
3
4
5
6
7
8
9

1
3

10
15
21
28
36

10
20
35
56
84

1
5
15
35
70
126

1
6
21
56
126

1
7
28
84

1
8
36

1
9

void Pascal(int n, int B[ ][10])


{ int i, j;
for (i=0; i<n; i++) { B[i][0]=1; B[i][i]=1; };
for (i = 1; i < n; i++)
for (j=1; j <= i-1; j++)
B[i][j] = B[i-1][j] + B[i-1][j-1];
}

Uwaga: Po obliczeniu wszystkich wartoci w wierszu i nie s potrzebne wartoci w wierszu i-1.
Obliczajc warto C(n,k) mona uy tablic jednowymiarow, indeksowan od 0 do k.
Zoono obliczeniowa algorytmu tablicowego
Tabelka obok pokazuje liczb obiegw ptli for-j w zalenoci od zmiennej i.
Cakowit liczb obiegw okrela zaleno:
1 + 2 + 3 + 4 + L + k + ( k + 1) + ( k + 1) + L + ( k + 1)
14444
4244444
3
nk +1
k ( k + 1)
( k + 1)(2n k + 2)
+ ( n k + 1)(k + 1) =
O ( nk )
2
2

i
0
1
2
3

przy czym k n

Algorytm tablicowy ma zoono klasy O(nk) czyli O(n2)

j
1
2
3
4

k
k+1
k+1 k+1

n
k+1

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

33

4.4. Algorytmy z powrotami (backtracking algorithm)


Poszukiwanie rozwiza pord caego zbioru moliwych przypadkw.
Dana jest przestrze stanw, zawierajca rozwizania problemu
lub wskazujca metod rozwizania.
Znany jest sposb przechodzenia od jednego stanu do drugiego.
Metoda pozwala na systematyczne testowanie wszystkich drg wyjcia z
danego stanu, w miar jak odkrywamy, e niektre z nich nie prowadz do celu.
Przykadem jest gra w szachy, gdzie przechodzi si od jednego stanu do drugiego, poprzez zmian ustawie figur.
Celem poszukiwa jest znalezienie stanu, z ktrego przeciwnik nie ma wyjcia.
Przeszukujc przestrze stanu, wykonuje si wiele ruchw, gdy do kadego stanu prowadzi wiele drg.

Wykonanie zego posunicia moe doprowadzi do stanu, w ktrym nie ma rozwizania.


Naley wycofa ruch i kontynuowa poszukiwania inn drog.
Jeeli cofnicie o krok nie pomaga, cofamy si o kolejny krok i poszukujemy w innym kierunku.
Naley zapamita wszystkie wykonane ruchy i odwiedzane stany aby mona byo wycofa posunicie.
W wielu problemach liczba moliwych stanw do odwiedzenia i drg odwrotu moe by dua, std
technika bezporednich powrotw moe okaza si kosztowna.
Czasami moliwy jest inteligentny wybr nastpnego posunicia, poprzez funkcj oceniajc.
Funkcja oceniajca oblicza dla danego stanu prawdopodobiestwo, e stan ten prowadzi do
rozwizania problemu lub jakiej klasy rozwizanie otrzymamy, jeeli szukamy rozwizania optymalnego.
Organizujc przeszukiwania, mona tak wykorzysta funkcje oceniajce aby unikn
przegldania nieistotnych fragmentw przestrzeni stanw.
4.4.1. Misjonarz i Ludoerca
Na jednym brzegu rzeki znajduje si 3-ch misjonarzy i 2-ch ludoercw, zamierzajcych
przeprawi si na drugi brzeg. Dostpna jest jedna dka mieszczca tylko dwie osoby.
Sterowa odzi potrafi tylko misjonarz.
Zakada si, e jeeli na kadym brzegu w danej chwili znajdzie si wiecej ludoercw
ni misjonarzy, to ci ostatni zostan zjedzeni.
Naley znale rozwizanie aby wszyscy bezpiecznie dotarli na drugi brzeg.
Kady moliwa sytuacja czy stan na obu brzegach moe by kodowany trzema liczbami.
Uatwieniem w analizie i implementacji problemu moe by kodowanie poszczeglnych stanw
jedn liczb semkow, gdzie poszczeglne trjki bitw zawieraj kolejno informacje o:
odzi | ludoercach | misjonarzach  123 co w jzyku C daje liczb: char kod = 0123;
Naley pamita wszystkie stany realizacji przeprawy aby umoliwi wycofanie, gdy zajdzie potrzeba.
Wykonanie ruchu wymaga analizy kolejnych moliwych stanw, celem znalezienia stanu
poprawnego (uwzgldniajcego ograniczenia).
Po jego wykonaniu poszukujemy nastpnych efektywnych stanw a dojdziemy do koca.
Jeeli znajdziemy si w stanie niedopuszczalnym cofamy si do poprzedniego i
prbujemy wykona inny ruch efektywny.
Misjonarze i Ludoercy

Nr
1
2
3
4

Kod
Lewy brzeg
123 3M 2L 1B
012 2M 1L 0B
113
3M 1L 1B
011
1M 1L 0B

112

2M 1L 1B

Rzeka
1M & 1L 
1M
2M 

1M

Prawy
0 0
1M 1L
1L
2M 1L

1M

Uwagi
ruch efektywny
ruch efektywny
ruch efektywny
ruch efektywny
ruch efektywny
1L
ostatni efektywny ruch
2L
2L
stan nieefektywny
powrt i zmiana stanu 6
1L
znowu ruch efektywny
1L
ruch efektywny
2L 1M

6
001
1M 0L 0B
1M & 1L  2M
7
103
3M 0L 1B
2M
0M
8 (6a) 010
0M 1L 0B
3M
2M 
7a
111
1M 1L 1B
1M
2M
8a
000
0M 0L 0B  1M & 1L
3M
Problem zosta rozwizany z jednym krokiem powrotnym.
Sze pierwszych krokw jest efektywnych. Stanu 7 uniemoliwia wykonanie efektywnego ruchu,
std konieczno wycofania si do stanu 6 i pjcie inn drog (stan 6a), tzn. przeprawienie si
dwch misjonarzy, z ktrych jeden powrci po ludoerc. Dalsze kroki prowadz do sukcesu.

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

34

W pracy [2] zastosowano kodowanie jedn liczb w zapisie czwrkowym, gdzie poszczeglne
dwjki bitw to informacje o: odzi | ludoercach | misjonarzach  ALL = 1234 = 2710
#include <stdio.h>
#include <stdlib.h>
#define MIS 1
#define CAN 4
#define BOAT 16
#define ALL BOAT+2*CAN+3*MIS
//1 10 11
#define NONE 0
#define SUBSET(x,y) ((x)%4 <= (y)%4 && (x)/4%4 <= (y)/4%4 && (x)/16 <= (y)/16)
int n, position[ALL+1], visited[ALL+1];
void printSide(int p)
{ printf("%*dM %dC %dB\n", n+1, p%4, (p/4)%4, p/16); }
int validMove(int pos1, int pos2)
/* Returns 1 if move is valid from pos1 to pos2, pos2 is legal, and has not already been seen.
Otherwise returns 0. */
{
//change in position
int diff = (SUBSET(pos2,pos1)?pos1-pos2:(SUBSET(pos1,pos2)?pos2-pos1:0));
int mis2 = pos2%4;
//missionaries in pos2
int can2 = pos2/4%4;
//cannibals in pos2
return(!visited[pos2]
//have not been there already
&& (diff==BOAT+MIS || diff==BOAT+MIS+CAN || diff==BOAT+2*MIS)
//valid move
&& can2 <= 2
//pos2 has at most two cannibals
&& (mis2 == 0 || can2 <= mis2)
//left bank missionaries uneaten
&& (3-mis2 == 0 || 2-can2 <= 3-mis2));
//right bank missionaries uneaten
}

int main()

// P4.2
{
position[0] = ALL;
//initial position is under consideration
visited[ALL] = 1;
printSide(position[0]);
position[1] = NONE;
//start with the first possible next move
n = 1;
while(position[n-1] != NONE) {
while(position[n]<=ALL && !validMove(position[n-1],position[n]))
position[n]++;
//loop until a valid next move, or no move
if(position[n]<=ALL) {
//there is a valid next move
visited[position[n]] = 1;
//mark that it is being considered
printSide(position[n]);
position[++n] = NONE;
//start its next moves at first possible one
}
else {
// no valid next move
visited[position[--n]] = 0;
// no longer considered prev state, backtrack
if(n==0) return 0;
position[n]++;
//advance previous state's next move
}
3M 2C 1B
}
2M 1C 0B
return 1;
3M 1C 1B
}
1M 1C 0B
2M 1C 1B
1M 0C 0B
3M 0C 1B
0M 1C 0B
1M 1C 1B
0M 0C 0B

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

35

Algorytmy i Struktury Danych - wykad

4.4.2. Problem 8 Hetmanw


Naley ustawi na szachownicy 8 hetmanw tak aby aden z nich nie szachowa innych.
Hetman moe zbi inn figur, jeeli stoi ona w tym samym rzdzie, kolumnie lub na przektnej.
Prba rozwizania problemu
Umieszczamy 1-go hetmana na szachownicy; nastpnie 2-go tak aby nie szachowa 1-go;
pniej 3-go tak aby nie szachowa innych i HETMAN(row)
sam nie by szachowany itd.
for kada pozycja col w rzdzie row
Niech ity hetman nie da si ustawi bez kolizji.
if pozycja col nie jest szachowana
Wwczas zmieniamy pozycj poprzedniego tak
then {
dugo a uda si umieci i-tego bezkolizyjnie.
umie kolejnego Hetmama na col
Jeeli to nie pomaga wracamy do i-2, i-3, i
if row < 8 then Hetman(row+1) else Disp
rozpoczynamy od nowa.
}
Problem mona zapisa rekurencyjnie, w
else Usu_Hetmana z pozycji col
postaci zwartego algorytmu HETMAN.
Dla Hetmana szachownica to rzd (row) i kolumna (col) oraz przektne (diag) lewe i
prawe, ktre s jego wasnoci w chwili gdy stoi na okrelonym polu.
0,0 0,1 0,2 0,3
Rozwamy szachownic 4 x 4 z czterema Hetmanami, ktrej pola
1,0 1,1 1,2 1,3
ponumerowane s zgodnie z konwencj indeksowania tablic w jzyku C.

Indeksy lewych przektnych sumuj si zgodnie z ir + jc, przy czym 2,0 2,1 2,2 2,3
jest to numer tej przektnej np.: ir + jc=2.
Szachownica zawiera 7 lewych przektnych, ktrym przypisujemy numery 3,0 3,1 3,2 3,3
od 0 6, czemu odpowiada tablica LDiag[7].
Indeksy prawych przektnych maj rnice zgodnie z ir - jc co pozwala przypisa im numery
od 3 3. Tworzymy tablic Pdiag[7], lecz do indeksw obliczonych ze wzoru ir jc naley
doda sta liczb norm, likwidujc ujemne wartoci.
Dodatkowa tablica PosInRow[row] kojarzy wiersz z aktualnym stanem kolumny.
Nie potrzeba pamita stanu wierszy, gdy ity Hetman przesuwa si wzdu rzdu i-tego.
Hetmany o numerach < od itego s ju ustawione w wierszach o numerach mniejszych od i.
void Hetman(int ir)
{ int jc, norm=3, OK=1;
for (jc=0; jc <= 3; jc++)
if (Col[jc]==OK && LDiag[ir+jc]==OK && RDiag[ir-jc+norm]==OK) {

PosInRow[ir] = jc;
Col[jc]=!OK; LDiag[ir + jc]=!OK; RDiag[ir-jc+norm]=!OK;
if (ir < 3) Hetman(ir+1); else Wynik();
Col[jc] = OK; LDiag[ir + jc] = OK;
}

RDiag[ir-jc+norm] = OK;

}
(1)
1

(2)
1

(3)

(4)

1
2

1
2
3

8 ir=3, jc=2,
4 ir=2, jc=1, Adr
7 ir=2, jc=0,
2 ir=1, jc=2, Adr
3 ir=1, jc=3, Adr
6 ir=1, jc=3,
1 ir=0, jc=0, Adr0 1 ir=0, jc=0, Adr0 5 ir=0, jc=1,
(2)
(4)
(8)
Zawarto ramek wywoa funkcji Hetman

//przywraca dostp do pl

Tablica 4.6
r
c
1
0
1 0
2
2 no
2
2 1
3
3
2 1
1 no
4
3 2
4
5
1
1 0
Adr
6
3
2 1
7
0
Adr
3 2
8
2
4 3
Adr
Adr0 Tablica 4.6 przedstawia kolejne
wykonane kroki przez funkcj Hetman,
prowadzce do pierwszego udanego
ustawienia czterech Hetmanw.
(8)
1

//testuje dostpnoci pl
// lokalizacja Hetmana
//markuje pola jako niedostpne

Rruch Nr H

Instytut Aparatw Elektrycznych


Algrm4
Dr J. Dokimuk

36

Algorytmy i Struktury Danych - wykad

#define OK 1
#define size 4
#define norm size-1
int Column[size], PosInRow[size], Count = 0;
int LDiag[2*size - 1], RDiag[2*size - 1];
void Disp()
{ int col, row;
for (row = 0; row < size; row++) {
for (col = 0; col < PosInRow[row]; col++) putchar('.');
putchar('Q');
for (col = PosInRow[row] + 1; col < size; col++) putchar('.');
putchar('\n');
} putchar('\n');
Count++;
}

.......Q
.Q......
....Q...
..Q.....
Q.......
......Q.
...Q....
.....Q..

void Queen(int row)


{
int col;

for (col = 0; col < size; col++)


if (Column[col] == OK && LDiag[row+col] == OK && RDiag[row-col+norm] == OK) {
PosInRow[row] = col;
Column[col] =
LDiag[row+col] = RDiag[row-col+norm] = !OK;

if (row < size-1) Queen(row+1); else Disp();


Column[col] =
}

.......Q
..Q.....
Q.......
.....Q..
.Q......
....Q...
......Q.
...Q....

LDiag[row+col] = RDiag[row-col+norm] = OK;

int main()
{ int i;
for (i = 0; i < size; i++) PosInRow[i] = -1;
for (i = 0; i < size; i++) Column[i] = OK;
for (i = 0; i < 2*size - 1; i++) LDiag[i] = RDiag[i] = OK;
Queen(0);
printf("%d solutions\n", Count);
}

.Q..
...Q
Q...
..Q.
..Q.
Q...
...Q
.Q..
2 solutions

.......Q
...Q....
Q.......
..Q.....
.....Q..
.Q......
......Q.
....Q...
92 solutions

Dziaanie funkcji Hetman


1. Pierwsze woanie Hetman(0) umieszcza 1go H na poz. (0,0). Warunek ptli if jest speniony,
zerowa kolumna, prawa diagonala i skrajna lewa przektna otrzymuj status zajte !OK.
2. Rekurencyjne woanie Hetman(1), gdy ir=1<3, tworzona jest ramka wywoania zawierajc:
adres powrotu i warto zmiennych ir, jc. Sprawdzana jest dostpno pola w 2-gim wierszu.
Dla ic = 0 niedostpna jest kolumna zerowa, dla jc=1 niedostpna jest prawa diagonala.
Dla jc = 2 warunek if jest speniony i 2-gi H na pozycj (1,2), odpowiednie pola markowane s jako !OK.
3. Kolejne wywoanie Hetman(2), gdy ir = 2<3 i prba umieszczenia hetmana w rzdzie 2.
Warunek ptli if nie jest speniony (brak wolnych miejsc), nastpuje wyjcie z bloku if
i koniec ptli for, a tym samym koczy si aktualne wywoanie funkcji Hetman(2).
Sterowanie przekazywane jest do miejsca wywoania, a wic do funkcji Hetman(1)
zajmujcej si rzdem nr 1 (drugi fizycznie).
4. Odtworzone zostaj ze stosu wartoci zmiennych ir oraz ic. Kontynuowane jest wykonanie 2-go
wywoania funkcji Hetman(1), pola tablic otrzymuj status OK, jc = 2 zatem ptla for dziaa
dalej i po pozytywnym sprawdzeniu warunku if, 2-gi H umieszczony zostaje na poz. (1, 3).
5. Kolejne wywoanie Hetman (2), z ponownym ir = 2<3, umieszcza 3-go H na poz. (2, 1).
Nastpne wywoanie Hetman(3) w celu ustawienia 4-go H jest nieskuteczne. Koniec wywoa.
6. Powrt do wywoa z kroku 4 i ponowna, bezskuteczna prba przesunicia 3-go hetmana.
Zmienna ic = 3 i ptla for koczy bieg.
7. Nastpuje aktywacja pierwszego wywoania Hetman(0) i ustawienie 1-go H na poz. (0,1).
Dalsze dziaania przebiegaj bez zakce, prowadzc do prawidowego rozwizania.

Instytut Aparatw Elektrycznych


Algrm5
Dr J. Dokimuk

37

Algorytmy i Struktury Danych - wykad

Instytut Aparatw Elektrycznych


Algrm5
Dr J. Dokimuk

38

Algorytmy i Struktury Danych - wykad

5.1. Sortowanie przez wstawianie

5. SORTOWANIE
Sortowanie jest procesem ustawiania zbioru obiektw w okrelonym porzdku.
Dana jest lista obiektw Q = [X1, X2, X3, ......, Xn ], bdca podzbiorem zbioru X.
Sortowanie moe polega na przestawianiu obiektw tak dugo a uzyska si ich ustawienie
w cigu niemalejcym X1 X2 X3 ...... Xn wedug zadanego klucza (funkcji sortujcej).
W praktyce klucz sortujcy jest przechowywany w postaci jawnej, jako
skadowe okrelonego pola obiektu. Wygodn form opisu obiektu jest struktura.
Dla analizy algorytmw sortowania istotne jest zdefiniowanie skadowej
struktury z kluczem, pozostae pola s nieistotne.
Typ klucza dopuszcza du dowolno np. char, integer, double.

struct Osoba {
int
wiek;
char[30] nazwisko;
char[20] zawod;
double waga;
};

Mona unikn opisu obiektw w postaci rekordw gdy elementami zbioru Q s:


pary wartoci [xi, yi ], gdzie kluczem jest xi dla 1 i n.
liczby cakowite lub rzeczywiste znajdujce si w tablicy X[1..n].
Stabilna metoda sortowania: jeeli podczas sortowania pozostaje nie zmieniony pocztkowy
porzdek ustawienia obiektw o identycznych kluczach drugoplanowych.
Dotyczy to sytuacji, gdy obiekty s ju uporzdkowane wedug drugoplanowych kluczy.
Przykadem moe by tablica rekordw zawierajca list studentw i wyniki egzaminw.
W wyniku sortowania damy dodatkowo aby nazwiska studentw majcych te
same oceny byy podawane w porzdku alfabetycznym.
Jeeli sortowanie dotyczy obiektw znajdujcych si w pamici wewntrznej np. tablic, to
istotniejszym kryterium wyboru metody jest oszczdne korzystanie z pamici, co oznacza,
e przestawianie obiektw w procesie sortowania powinno by realizowane in situ.
Kryteria efektywnoci algorytmw sortowania:
1. liczba porwna klucza Po,
6
12 23
23 12 6
2. liczba przestawie Ps,
// swap(a, b) 
11

3. liczba przesuni obiektw Pr.

12

13

14

15

16

Kryteria efektywnoci s funkcjami liczby sortowanych obiektw: T(n) = f(n)


Metody sortowania mona podzieli na:
void swap(typ x1, typ x2)
 proste, wymagajce liczby porwna kluczy rzdu n2;
{ typ temp = x1;
x1 = x2;
 efektywne, wymagajce liczby porwna rzdu nlg(n).
x2 = temp;
Sens stosowania metod prostych:
}
implementacje s krtkie i zrozumiae,
dobrze opisuj i wyjaniaj pryncypia metod sortowania,
metody efektywne zawieraj wicej operacji i dla maych n mog by wolniejsze.
x1#x2
Poprawne drzewo: przy sortowania n kluczy dla kadej permutacji
N
T
tych kluczy zawiera ciek od korzenia do licia.
x3#x1
x3#x2
Lemat 5.1. Dla kadego determistycznego algorytmu sortujcego
T
T
N
N
n rnych kluczy istnieje odpowiadajce mu drzewo
x3,x1,x2 x2#x3 x3,x2,x1 x3#x1
decyzyjne, zawierajce dokadnie n! lici.
N
T
T
N
Lemat 5.2.. Pesymistyczna liczba operacji porwnania kluczy w
x
,x
,x
x
,x
,x
x
,x
,x
x
,x
1 2 3
1 3 2
2 3 1
2 1,x3
drzewie decyzyjnym jest rwna gbokoci drzewa.
Lemat 5.3. Jeeli n jest liczb lici w drzewie decyzyjnym to gbokoci drzewa h = lg(n)
Twierdzenie 5.1. Determistyczny algorytm sortujcy n kluczy wycznie poprzez porwnywanie ich
wartoci w najgorszym przypadku wykonuje lg(n!) porwna.
Lemat 5.4. Dla dodatniej liczby cakowitej n zachodzi: lg(n!) nlg(n) 1.45n
n

n ln( n ) n + 1

i =2

ln( 2)

Dowd: lg( n! ) = lg(i ) lg( x ) dx =

n lg( n ) 1.45n

Twierdzenie 5.2. Determistyczny algorytm sortujcy n kluczy wycznie poprzez porwnywanie ich
wartoci w najgorszym przypadku wykonuje nlg(n) 1.45n porwna.

Metoda stosowana automatycznie przy grze w karty, podczas ukadania ich w rozdaniu.
Obiekty sortowane dzielone s umownie na dwa podcigi o zmieniajcej si licznoci.
Jeden to podcig wynikowy (uporzdkowany) x1,.
..xi-1,
for i  2 to length(X) do
drugi to podcig rdowy (nieuporzdkowany) xi,....., xn.
v  X[i]
Dla kadego i poczwszy od i=2 i-ty element podcigu
rdowego przenoszony jest do podcigu wynikowego i v  w odpowiednie miejsce:
x1,..,xi-1
wstawiany w odpowiednie miejsce.
6

12

23

28

33

25

18

48

Istot metody jest przesuwanie wielu elementw w prawo o 1 pozycj a nastpnie wstawienie wybranego.

Algorytm sortowania przez wstawianie jest stabilny.


Jest to algorytm klasy O(n2) i praktycznie nie nadaje si do
sortowania duych tablic.
Biorc pod uwag jego prostot i naturalno moe by
przydatny dla maych zbiorw.
Tablica 5.1 zawiera przykad sortowania przez wstawianie 6
losowo pobranych liczb.
Proces sortowania przebiega w 5-ciu krokach (n-1).
Podcigi z prawej strony s podcigami rdowymi o
zmniejszajcej si liczbie elementw w kadym kroku .

Tablica 5.1

15 12 30 40 33

Pocztek:

22

Krok 1:

15 22

Krok 2:

12 15 22

Krok 3:

12 15 22 30

Krok 4:

12 15 22 30 40

12 30 40 33
30 40 33
40 33
33

Krok 5:
12 15 22 30 33 40
Proste wstawianie
Miejsce do wstawienia elementu podcigu rdowego mona przygotowa poprzez
naprzemienne wykonywanie operacji porwnywania i przesuwania (przesiewanie).
InsertSort1(X)

// P5.1a
// i indeks zbioru rdowego
// j indeks zbioru wynikowego
// v zmienna robocza

X[0]
 -32000
// wartownik
for i 2 to length(X) do
Liczba porwna w i-tym kroku: 1<Po# i - 1, rednio 0.5i
v  X[i]
ji1
Elementy X[1]X[i-1] to podcig wynikowy.
while v < X[j] do
Elementy X[i]X[n] to podcig rdowy.
X[j+1]  X[j]
Indeks i wskazuje element aktualnie wstawiany; przesuwa
si od lewej do prawej.
jj1
W kadej iteracji ptli for element X[i] jest pobierany z X[j+1]  v
tablicy i przypisywany do zmiennej roboczej v.
//
bez wartownika byoby:
Porwnuje si element v z poprzednim elementem X[j],
// while v < X[j] && j > 0 do
poczym albo wstawia si v albo przesuwa X[j] na prawo.
Wartownik jest elementem cigu i
Zakoczenie przesiewania:
pilnuje jego koca, czyli
znaleziono element xi mniejszy od v;
powstrzymuje przeszukiwania przed
wyjciem poza cig.
osignito lewy koniec podcigu wynikowego.
Liczba porwna Po i przesuni Pr dla tablicy X[n]:
Pomin = n 1
Posr = 0.25(n2 + n - 2)
Pomax = 0.5(n2 + n) - 1
2
Prsr = 0.25(n +9n - 10)
Prmax = 0.5(n2 + 3n - 4)
Prmin = 2(n-1)
W/wym zalenoci pokazuj, e czas sortowania jest:
najmniejszy gdy elementy s ju uporzdkowane,
najwikszy gdy s ustawione w kolejnoci odwrotnej.

Instytut Aparatw Elektrycznych


Algrm5
Dr J. Dokimuk

39

Algorytmy i Struktury Danych - wykad

Polepszenie szybkoci sortowania przez wstawianie mona osign optymalizujc


metod znajdowania waciwego miejsca w podcigu wynikowym
(uporzdkowanym) do wstawiania obiektu podcigu rdowego.
Jedn z moliwoci moe by zastosowanie tzw. techniki wstawiania powkowego (InsertSort2).
Wstawianie powkowe
Metoda wykorzystuje informacj, e podcig wynikowy jest zawsze uporzdkowany.
Proces rozpoczyna si prbkowaniem podcigu wynikowego w rodku.
Jeeli miejsce to nie jest waciwe do wstawienia InsertSort2(X)
nowego elementu, dzieli si go dalej na poow a
// P5.1b. wstawianie powkowe
znajdzie si waciw pozycj.
for i2 to length (X) do
Miejsce do wstawienia nowego elementu uwaa si v
X[i]
za znalezione, jeeli zachodzi relacja xj v xj+1.
l1
pi-1
6
12 23
28 33
2
48
while l p do
m  (l + p) div 2
6
12
23
28
33
2
48
if v<X[m] then pm-1
6
12
23
28
33
2
48
else lm+1
for ji-1 downto l do X[j+1]X[j]
Po = n[lg(n) - lg(e)0.5] za Pr jest cigle rzdu n2.
X[l]
v
Metoda wstawiania powkowego zmniejsza tylko liczb porwna a nie przesuni, ktre
s bardziej czasochonne.
W pewnych sytuacjach mona si spodziewa si gorszych wynikw ni w metodzie
prostego wstawiania.
Analiza zoonoci algorytmu sortowania przez proste wstawianie InsertSort1
InsertSort1(n, X)
Lp Instrukcja
1 for i2 to n do
2 v X[i]
3 ji 1
4
5

ci dla i(1, 7) koszt wykonania wiersza programu


Koszt Liczba wykona
c1
n
c2
n-1
c3
n-1

while v < X[j] do

c4

X[j+1]X[j]

c5

ki

i=2

( ki 1)

i=2

jj-1

c6

X[j+1]v

c7

( ki 1)

i=2

n-1

ki liczba testowa warunku ptli while


Przypadek optymistyczny cig uporzdkowany:
Dla kadego i (2, n) zachodzi relacja:
v X[j] jeeli j = i 1.
std ki = 1 dla i (2, n).
Tym samym minimalny czas dziaania wynosi:
T(n) = nc1+c2(n-1) + c3(n-1)+c4(n-1)+c7(n-1) =
= (c1+c2+c3+c4+c7)n (c2+c3+c4+c7) =
= O(n) + O(c)

1 = n 1
i =2
Algorytm sortowania przez wstawianie jest klasy O(n) dla zbioru posortowanego.
Przypadek pesymistyczny wystpuje dla cig uporzdkowanego w kierunku malejcym.
Kady element tablicy X[i] naley porwna z kadym elementem podtablicy X[1i-1],
std ki = i dla i (2, n).
n

Z teorii sum mamy: i =


i =2

n( n + 1)
1 oraz
2

(i 1) =
i =2

n( n 1)
2

T(n) = c1n+c2(n-1)+c3(n-1)+c4[0.5n(n+1)-1]+c5[0.5n(n-1)]+c6[0.5n(n-1)]+c7(n-1) =
= O(n2) + O(n) + O(c) = O(n2) + O(n)

Instytut Aparatw Elektrycznych


Algrm5
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

40

5.2. Sortowanie bbelkowe


Porwnywanie i zamiana par ssiadujcych ze sob elementw trwa tak dugo a wszystkie
bd posortowane. Tablica przegldana jest wielokrotnie (ptla i) od koca do pocztku (ptla j), przy
czym za kadym razem najmniejszy element lokowany jest sukcesywnie od lewej strony tablicy.
Jeeli postawimy tablic pionowo to elementy wypychane s do gry jak bbelki na
pozycje proporcjonalne do ich wagi (najlejszy zawsze na grze) std nazwa metody.
Tablica 5.2. Sortowanie bbelkowe
1

Etap 22
y

50
4

18
4

40
4

88
4

19
4

72

4
4
4
i=5 4
i=6 4
i=7 4
i=8 4

22
18
18
18
18
18
18

50
22
19
19
19
19
19

18
50
22
22
22
22
22

40
19
50
40
40
40
40

88
40
40
50
50

19
88
72
72
72
72

72
72
88
88
88
88
88

i=2
i=3
i=4

50
50

72

for i
2 to n do
for j n downto i do
if X[j-1] > X[j] then X[j-1] X[j]
(n 1)*(n 1) = n2 2n + 1  O(n2)
void BubbleSort(int n, int *X)
{ int i, j;
//P5.2a
for ( i= 1; i < n; i++)
for (j = n-1; j >= i; j--)
if ( X[j] < X[j-1] ) swap(X[j-1], X[j]);
}

Po = 0.5(n2 - n)
Prmin = 0
Prsrednia = 0.75(n2 - n)
Prmax = 1.5(n2 - n)
Dwie istotne wady metody BubbleSort:
 czsto wystpuj niepotrzebne przebiegi gdy elementy zostay ju posortowane (w tabeli
5.2. trzy ostanie przebiegi s ju zbdne, gdy stan posortowania uzyskano ju dla i = 5);
 wraliwa na struktur danych: X1 =(8 4 5 22 30 66 50) sortuje w 1-szym przebiegu;
X2 = (8 5 22 30 50 66 4 ) wymaga 2-ch przebiegw.
Moliwoci poprawy algorytmu to midzy innymi:
zapamitanie czy w trakcie przejcia dokonano jakiejkolwiek permutacji - przejcie, w
ktrym nie ma zmian wskazuje, e proces sortowania moe by zakoczony;
zapamitanie indeksu ostatniej permutacji (k = j) pozwala ogranicza zbdne przebiegi,
gdy wszystkie obiekty poniej tego indeksu (k) s uporzdkowane.
Nastpne przejcie mona zakoczy na tym indeksie zamiast i do aktualniej granicy i.
przeczanie kierunku przegldania tablicy agodzi niekorzystne konfiguracje danych.
Tablica uporzdkowana z wyjtkiem lekkiego elementu na kocu X1= 4 12 16 22 44 55 2
posortowana zostanie w 1-szym przebiegu.
Z cikim na pocztku X2= 55 2 4 12 16 22 44 w 6-ciu (X2(1-szy) = 2 55 4 12 16 22 44).
Algorytm sortowania bbelkowego, poprawiony wg w/wym
ShakerSort (n, X)
// P5.2b
uwag nazywa si ShakerSort sortowanie przez wytrzsanie.
lewy2; prawyn
Tablica 5.3. Sortowanie bbelkowe poprawione ShakerSort
kn
repeat
Etapy 1
2
3
4
5
6
7
8
1-szy 22 50 18 40 88 19 4
72 
for jprawy downto lewy do
if X[j-1] > X[j] then
22 50 18 40 88 19 72
2-gi  4
X[j-1]  X[j]
22 18 40 50 19 72 88 
3-ci
4
kj
18 22 19 40 50 72 88
4-ty  4
lewyk+1
18 19 22 40 50 72 88 
5-ty
4
for jlewy to prawy do
Pomin = n 1, za pozostae parametry mona szacowa wg
if X[j-1] > X[j] then
zalenoci podanych przez Knutha:
X[j-1]  X[j]
k
j
Posrednia 0.5(n2 - n(k1 - ln(n)); Prsrednia . n - k2sqrt(n)
prawyk
1
Szybki wzrost czasu sortowania ze wzrostem n.
Modyfikacja nie zmniejsza liczby permutacji tylko redukuje liczb porwna. until lewy > prawy

Instytut Aparatw Elektrycznych


Algrm5
Dr J. Dokimuk

41

Algorytmy i Struktury Danych - wykad

5.3. Sortowanie Shella


Algorytm zaproponowany przez D.L. Shella w 1959 roku jest sposobem poprawienia
efektywnoci zarwno metody BubbleSort jak i metody sortowania przez proste wstawianie.
Istot metody jest sortowanie podtablic, utworzonych z elementw odlegych od siebie.
W kolejnych etapach liczba podtablic maleje (do warto 1), za ronie ich liczno.
Ostatni etapem jest zwyke sortowanie wszystkich elementw.
Algorytm o regularnej zmianie odstpu, w pierwszym etapie tworzy
Dziel tablice DANE
podzbiory z elementw oddalonych od siebie o k (np. k = 4) i sortuje je;
na k podtablic D[k]
w drugim o k/2 , itd. a osignie si k = 1.
for
i 1 to k do
Dla tablicy 8elementowej sortowanie moe przebiega w 3 fazach
Sortuj(D[i])
co cztery grupuje elementy oddalone o 4 miejsca i sortuje 4 podzbiory,
co dwa grupuje elementy oddalone o 2 miejsca i sortuje 2 podzbiory, Sortuj (DANE(n))
co jeden sortuje wszystkie elementy jedn z wybranych technik.

Instytut Aparatw Elektrycznych


Algrm5
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

5.4. Sortowanie szybkie


Algorytm sortowania szybkiego QuickSort wykorzystuje ulepszon metod sortowania
przez zamian, zosta opracowany przez C.A.R. Hoarea w 1962 roku.
2
redni czas sortowania okrela zaleno nlg(n), pesymistyczny za szacuje zaleno O(n ).
Istot metody jest podzia zbioru na dwie czci.
Wybieramy arbitralnie jeden element ze zbioru i tworzymy podzbir lewy zawierajcy elementy
nie wiksze (mniejsze) i podzbir prawy elementy nie mniejsze (wiksze) od wybranego elementu.
Proces podziau powtarza si dla obydwu podzbiorw.
Zbir zostaje posortowany jeeli wszystkie podzbiory stan si zbiorami jednoelementowymi.
Algorytm oparty jest na strategii dziel i zwyciaj.
W przykadzie z rysunku R5.4a jako element osiowy wybrano rodkowy z kadego podzbioru.
QuickSort(l, p, X) // lewy,prawy
int pivot;
if l < p then {
pivot = Partition(l, p);
QuickSort(l, pivot-1, X);
QuickSort(pivot+1, p, X);
}

Kady etap sortowania mona realizowa dowoln technik.

R5_3

h=4

h=2

h=1

22 50 18 40 88 19
22 19

72

40 88 50 18 72

22 19 4 40 88 50 18 72
4 19 18 40 22 50 88 72
4

18 19 22 40 50 72 80

p
o
d
z
b
i
o
r
y

12 9
12
9
c
o
5

5 22 4

2 30 1
2
30
1

22

0 28 29
29

0
4

s
ShellSort1(n, X)
// P5.3a
o
r
h  n div 2
// wartoc poczatkowa odstpu
t
while (h > 0) do
wynik: 2
for i  h + 1 to n do
c 2
jih
o
while (j > 0) do
3
jh  j + h
s
o 0
if X[j] X[jh] then j0 //koniec ptli
r
t
else Swap(X[j], X[jh])

28
12

29
30

5
0

0
0

9
1
2
4
1
1
1
2

22
4
4 12 30
30
4
12
28
5
12
5 12 28
5 12 28
5 9 12

28
5 22 28
28
5
22
30
9
22
9 22 30
9 22 30
22 29 28

29
29

29

jjh
wynik: 0 4
2
29
Sort co 1 0 4
h  h div 2
2
29
4
30
0 1
Ptla zewntrzna while kontroluje odstp
midzy porwnywanymi elementami.
W kadym kroku odstp zmniejszany jest dwukrotnie.
ShellSort2(n, X)
//P5.3b
W ptli rodkowej porwnuje si elementy odlege o h.
w3;
k[1..w]
(5,
3,
1)

W ptli wewntrznej elementy s przestawianie, jeeli
nie s uporzdkowane rosnco.
for m1 to w do
rednia efektywno algorytmu Shella wynosi n1.5
hk[m]
sh
//wartownik
Analiza efektywnoci algorytmu Shella wykazaa:
1. przyrosty nie musz by potg liczby 2,
for ih+1 to n do
2. cig przyrostw nie musi by cile zdefiniowany.
wrkX[i];
ji h
Przyrosty odstpw nie powinny by swoimi dzielnikami.
if s=0 then sh
Knuth wykaza, e dobrym cigiem przyrostw jest cig:
ss+1
hi+1=3hi +1 ` np.1,4,13,40,121 lub 1,3,15,31
X[s]wrk
Algorytm ShellSort2 zakada dowolny cigu przyrostw h1, h2,
while wrk < X[j] do
...,hi ,przy czym kade z hisortowa realizowane jest
metod prostego wstawiania.
X[j+h]X[j]
Metoda z z wartownikiem upraszcza warunek szukania miejsca
jj h
wstawienia elementu. Kade z hsortowa musi mie wasnego
X[j+h]wrk
wartownika, co rozszerza deklaracj wektora X o hmax.

42

Podstawa algorytmu to efektywnie zbudowana funkcja


podziau (partition), realizujca podzia tablicy X.
Moe by zrealizowana wg poniszego schematu:
Partition(l, p) // wersja gdy element osiowy nie wchodzi do podtablic
if l < p then
// wybierz element osiowy v
// rozdziel elementy X tak aby
X[l], X[l+1],X[k-1] v X[k+1],X[p]
return k
Funkcja podziau metod przegldu dwustronnego
ustaw wskaniki przegldajce od lewej i = l i od prawej j = p
wybierz element osiowy v z tablicy X (np. rodkowy)
Dla (i <= j) wykonaj
przegldaj tablic od lewej a znajdziesz element Xi v
przegldaj tablic od prawej a znajdziesz element Xj v
dla i < j: -zamie miejscami elementy, ktre spowodoway
zatrzymanie; oraz zmie dwa wskaniki i = i + 1, j = j 1
w przeciwnym razie (jeeli i j) zmie tylko i = i+1.
do skrzyowania wskanikw.

----------Wybierajc za element osiowy v = X[1] lub wykonujc na


pocztku Swap(X[1], X[k] v) naley dooy operacj
zamie element osiowy z elementem wskazywanym przez
prawy wskanik (eliminacja osiowego z podtablic).
QuickSort1(int lo, int hi, int X[ ])

{ // element osiowy czci podtablic

int i=lo, j=hi, v = X[(lo + hi)/2];


while (i <= j) {
// partition
while (X[i] < v) i++;
//
while (X[j] > v) j--;
//
if (i < j) swap(&X[i++], &X[j--]); else i++; }
if (lo < j)
QuickSort1(lo, j ,X);
if (j+1 < hi) QuickSort1(j+1, hi, X);
}

Instytut Aparatw Elektrycznych


Algrm5
Dr J. Dokimuk

43

Algorytmy i Struktury Danych - wykad

Algorytm QuickSort nie jest stabilny oraz nie jest efektywny dla maych n.
Niech warto osiowa v jest zawsze wybierana jako najwiksza ze zbioru.
Przy kadym podziale lewy podzbir zawiera n-1 elementw za prawy tylko 1 element.
Jest to najgorszy przypadek dziaania algorytmu, gdy trzeba dokona n takich podziaw.
Koszt podziau wynosi n - 1, koszt sortowania lewego podzbioru T(n-1), za prawego T(0).

dla
0
T (n) =
T ( n 1) + n 1 dla

n =1
n( n 1)
T (n) =
n >1
2

T(n) = O(n2)

Niech zbir wejciowy bdzie zawsze dzielony w


0
dla n = 1

proporcjach 9:1. Wwczas czas dziaania ma posta T ( n ) =


9 n
podana obok. Mona dowie, e prowadzi to do
T 10 n + T 10 + O ( n ) dla n > 1

zoono klasy O(nlg(n))


Jeeli v = X[1] to najgorszym przypadkiem jest tablica uporzdkowana.
Efektywno metody zaley od wyboru elementu osiowego i pocztkowej struktury zbioru
Dobr elementu osiowego, minimalizujcy wystpienie wartoci najwikszej lub najmniejszej:
 losowy wybr liczby zawartej midzy X[l] i X[p] (generator liczb losowych),
 elementem osiowym jest mediana elementu 1-go, rodkowego i ostatniego.
Funkcja podziau moe przeksztaca tablic X przegldajc j tylko z lewej strony.
Niech i bdzie indeksem przegldajcym tablic z lewej do prawej, za k indeksem
elementu osiowego, wybranym jako skrajnie lewy element tablicy X,
Algorytm przegldu tablicy X tylko z lewej strony:
ustaw warto osiow: k = l (lewy); v = X[l] oraz wskanik i = l + 1
inkrementujc i sprawd relacj X[i] < v, jeeli speniona dokonaj wymiany X[k = k+1] i X[i];
kontynuuj przegldanie zwikszajc i;
po zakoczeniu przegldania dokonaj wymiany elementu osiowego X[l] oraz X[k].
QuickSort2(int l, int p, int X[ ])
// P5.4
{
// przegld jednostronny
int k = l, i;
if (l >= p) Exit();

for(i = l+1; i <= p; i++)


if (X[i] < X[l]) swap(&X[++k], &X[i]);
swap(&X[l], &X[k]);
QuickSort2( l, k-1, X);
QuickSort2( k+1, p, X);
}

Sortowanie QuickSort nie jest bezporednie. Kiedy algorytm sortuje 1-sz podtablic,
pierwszy i ostatni indeks drugiej podtablicy musz by trzymany na stosie.
QuickSort nie daje gwarancji, podziau tablicy na p.
Funkcja Partition moe wielokrotnie dzieli tablic na jedn pust podtablic.
Na stosie znajdzie si wwczas n-1 par indeksw.
Zamiana rekordw wymaga trzech przypisa: w rednim przypadku zoono czasowa liczby
operacji przypisania rekordw wynosi: A(n) = 2.07(n+1)lg(n) .
QuickSort moe by zrealizowany technik rekurencyjn.
Nie absorbuje zbytnio zasobw komputera, gdy nie jest tworzona kopia tablicy X. W procesie
rekurencyjnym przechowywane s na stosie tylko indeksy wyznaczajce segmenty tablicy,
ktrych elementy maj ulec przestawieniu. Gboko stosu moe nie przekracza wartoci lg(n).
Efektywno algorytmu mona zwikszy trzymajc indeksy i, j tablic w rejestrach komputera.

Instytut Aparatw Elektrycznych


Algrm5
Dr J. Dokimuk

44

Algorytmy i Struktury Danych - wykad

5.5. Sortowanie przez zliczanie


Zakada si, e zbr elementw do sortowania to liczby cakowite z przedziau (1, k), przy czym
warto k jest z gry znana.
Dla k = O(n) zoono algorytmu jest klasy O(n).
Istot metody jest zliczanie liczby elementw mniejszych od okrelonej liczby a zbioru X.

Znajc t liczb, znamy dokadn pozycj a w cigu posortowanym.


Naley j wstawi na stosown (liczba el. mniejszych+1) pozycj. 3 9 5 1 8 6 2 7 8
Dane wejciowe o rozmiarze n zawarte s a tablicy A[n]
1 2 3 5 6 7 8 8 9
Wykorzystywane s dwie tablice dodatkowe:
B[n] zawiera posortowane dane wejciowe,
C tablica robocza pamitajca liczby elementw mniejsze lub rwne od zadanej liczby.
Dana jest tablica A[8] zawierajca cakowite liczby dodatnie nie wiksze od k = 7.
Stan po wykonaniu ptli
1

1
1

1
1
1

1
1

Stan po wykonaniu ptli


1
2
3
4
5 6 7 8

Po 1-szym wykonaniu ptli A[8]=5


1

B
C

5
1

Po 2-gim wykonaniu ptli A[7]=2


1

2
1

5
3

C 0 1 2 2 4 6 8 8
Po 3-cim wykonaniu ptli A[6]=7
1

C 0 1 2 2 4 6 7 8
Po 4-tym wykonaniu ptli A[5]=5
1

B
C

Po 5-tym wykonaniu ptli A[4] = 2


1

CountSort(k, A, B)
n  length[A]
for i  1 to k do C[i]
0

// O(k)

// C[i] - liczba elementw rwnych i


for i  1 to n do C[A[i]]
 C[A[i]] + 1
// C[i] - liczba elementw i
for i 2 to k do C[i]
 C[i] + C[i-1]
for i n downto 1 do
B[C[A[i]]]  A[i]

// O(n)

C[A[i]]  C[A[i]] - 1

W wierszu rozpatrujemy kolejno wszystkie elementy


tablicy A. Warto A[i] stanowi indeks dla wektora C.
W C zliczane s wystpienia identycznych wartoci A[i] i
wpisywane na pozycj C[A[i]].

W wierszu dodaje si narastajco wartoci tablicy C,


otrzymujc dla i (1, k) ile elementw jest i.
Ostatnim elementem jest licznoci zbioru rdowego.

W wierszu warto A[i] stanowi adres dla tablicy C;


warto z tablicy C stanowi adres, pod ktrym w tablicy B
umiecimy element ze zbioru rdowego.
Zmniejszamy zawartoc komrki C[A[i]] o jeden, co
pozwala wstawia identyczne elementy rdowe na
waciwe miejsca tablicy wynikowej B.
Cakowity czas dziaania algorytmu: O( n + k )

W metodzie tej nie s wykonywane operacje


porwnywania dwch elementw.
Metoda jest stabilna, co oznacza, e liczby o tych samych
wartociach lokowane s w tablicy wynikowej w tej samej
kolejnoci, co w tablicy wejciowej. Jest to istotne tylko wtedy,
gdy z elementami sortowanymi zwizane s dodatkowe dane.
Metoda daje istotne korzyci, jeeli k = O(n).
Klucze tablicy C stanowi indeksy dla tablicy
wynikowej B, wg. ktrych umieszcza si elementy
rdowe z tablicy A.

Instytut Aparatw Elektrycznych


Algrm5
Dr J. Dokimuk

45

Algorytmy i Struktury Danych - wykad

5.6. Sortowanie pozycyjne (radix sort)


Algorytm wymaga pewnej wiedzy o sortowanych obiektach:
1. klucze obiektw s nieujemnymi liczbami cakowitymi (n liczba obiektw),
2. zapisane s w notacji dziesitnej (podstawa r = 10),
inline char Cyfra(long a, int k)
3. skadaj si z tej samej liczby cyfr (m liczba cyfr).
{ return (a/(long)pow10l(k)) % 10; }
Niech dana bdzie dodatnia liczba cakowita a zapisana w main()
// P5.1
systemie o podstawie r.
np. a = 8739
{ long a = 89624031; int m=8;
k
Cyfr o numerze k jest nastpujca liczba: a/r mod r .
for (int i = m-1; i >= 0; i--)
Jeeli liczba a naley do przedziau (0, 1) to k-t
printf(" %d,", Cyfra(a,i));
cyfr liczby okrela zaleno: ark mod r .
}
8, 9, 6, 2, 4, 0, 3, 1,
5.6.1. Przetwarzanie cyfr od lewej do prawej

Zbir Wejciowy

589 234 867 238 123 987 232 192 876 543 124

Etap 1
wg
skrajnie lewych
Nr pojemnika 0

Etap 2
wg
2-ich od lewej
Etap 3
wg
3-ich od lewej

12
24
19
92
12
23

23
32
23
38
23
34

54
43
58
89
3

123 124
4

232 234
2

238
4

87
76
86
67

98
87

543
3 589
9

192

234
4
238
8
232
2

123
3
124
4 192
2

R5.6
a

Sortowanie pozycyjne od lewej do prawej

876
6 867
7

543 589
3

876 867
6

Instytut Aparatw Elektrycznych


Algrm5
Dr J. Dokimuk

5.6.2. Przetwarzanie cyfr od prawej do lewej


Przetwarzanie w kolejnych krokach cyfr od prawej do lewej umoliwia sortowanie liczb
cakowitych, majcych rn liczb cyfr.
Sortowanie pozycyjne od prawej do lewej
Zbir Wejciowy

Nr pojemnika

Etap 1. Zbir Wejciowy dzielony jest na podzbiory wg skrajnie lewych kluczy.


Tworzy si 10 pojemnikw numerowanych od 0 9.
for i  0 to n -1 do
Liczby o identycznych skrajnych lewych cyfrach trafiaj
ci  Cyfra(We[i], m-1)
odpowiednio do pojemnikw numerowanych od 0 9.
Put(S[ci], We[i])
Cz pojemnikw moe by niewypeniona.
Etap 2. Obiekty kadego pojemnika z Etapu 1 przegldane s wg wartoci drugich cyfr od lewej i
lokowane w nowych pojemnikach, numerowanych od 0 9.
Rozdzia elementw z kadego pojemnika z poprzedniego etapu moe wymaga
utworzenia dodatkowych 10-ciu pojemnikw numerowanych od 0 9.
Etap 3 (i dalsze). Proces podziau podzbiorw z etapu poprzedniego kontynuowany jest wg
trzecich i dalszych cyfr od lewej a do zakoczenia analizy wszystkich cyfr.
Po przeanalizowaniu wszystkich cyfr (liczba etapw = liczbie cyfr w kluczu), klucze zawarte w pojemnikach utworzonych w ostatnim etapie s posortowane, wystarczy je odpowiednio zebra i scali.
Zbir wejciowy moe skada si z liczb cakowitych (PESEL 11 znakw) co daje 10 cyfr do
analizy i numeracj pojemnikw od 0 9 lub alfabetu angielskiego co moe wymaga analizy 26
znakw i utworzenia pojemnikw numerowanych 0 25.
Trudnoci w implementacji tej metody jest wystpowanie zmiennej liczby pojemnikw.
Metoda wymaga dotrzymania zaoenia (3), gdy dla zmiennej liczby cyfr jest nieskuteczna.
Zbir { 324 5 845 12 934 } po posortowaniu pozostanie niezmieniony.
Problem mona omin wyrwnujc krtkie liczby zerami.
Zbir {324 005 845 012 934} po posortowaniu przyjmie posta { 005 012 324 845 934 }.
Uproszczona metodyka implementacji:
a. Zapenij w 1-szym przebiegu 10 pojemnikw ponumerowanych od 0 9.
b. Posortuj zawarto kadego pojemnika indywidualnie.
c. Pocz zawartoci posortowanych pojemnikw w kolejnoci od 0 9.

522
232
12
0

234

876

197
987
867

628
238

129
589

12 23
32 52
22 23
34 5 87
76 86
67 98
87 19
97 23
38 62
28 58
89 12
29
Etap 2
wg
2-ich od prawej

Etap 3
wg
3-ich od prawej

589
9 234
4 867
7 238
8 12
2 987
7 232
2 197
7 876
6 5 129
9 628
8 522
2

Etap 1
wg
skrajnie prawych

987
7

987

46

Algorytmy i Struktury Danych - wykad

12

129
628
522

867

987

589
987

197

5 12 522 628 129 232 234 238 867 876 987 589 197
12
5
0

R5.6B

238
234
232

197
129

238
234
232

589
522

628

876
867
7

987

5 12 129 197 232 234 238 522 589 628 867 876 987

Etap 1. Utwrz 10 pojemnikw, numerowanych od 0 9, tak skonstruowanych aby mona byo


z jednej strony wkada za z drugiej wyjmowa.
Wstaw wszystkie liczby ze zbioru Wejciowego do pojemnikw o numerach rwnych
ostatniej cyfrze w liczbie.
Liczby naley wkada od gry.
Pocz zawarto pojemnikw w jedn list, wyjmujc liczby od spodu.

Cz pojemnikw moe pozosta niewypeniona.


Etapy dalsze. Powtarzaj proces rozdziau liczb z
nowej listy do odpowiednich pojemnikw
wg drugiej i dalszych cyfr od prawej.
Proces ulega zakoczeniu po przetworzeniu
wszystkich cyfr w najduszej liczbie.

RadixSort1(We)
//podstawa systemu liczbowego
r  10
for i  0 to r1 do P[i]Null // utwrz pojemniki

for k  m to 1 do
for i  0 to n - 1 do

We={5,234,867,238,123,98,232,192,876,543,124}
Etap 1: 5, 4, 7, 8, 3, 8, 2, 2, 6, 3, 4
Etap 2: 0, 3, 6, 3, 2, 9, 3, 9, 7, 4, 2
Etap 3: 0, 2, 8, 2, 1, 0, 2, 1, 8, 5, 1

ci  Cyfra(We[i], m - k)
Put(P[ci], We[i])
Pocz pojemniki w nowy zbir We

W sortowaniu pozycyjnym liczba kluczy n w zbiorze nie jest wystarczajcym miernikiem zoonoci,
liczba znakw do przeanalizowania w cyfrze moe by wiksza od liczby n.

Dla zbiorw o maej licznoci sortowanie pozycyjne nie jest zalecane.


Sortowanie pozycyjne nie realizuje porwna kluczy.

Instytut Aparatw Elektrycznych


Algrm5
Dr J. Dokimuk

47

Algorytmy i Struktury Danych - wykad

Algorytm sortowania traktuje liczb cakowit jako rekord, gdzie kluczem s cyfry na
kolejnych pozycjach poczynajc od najmniej znaczcej.

431
1

124
4

547
7

867
7

192
2

232
2

987
7

3
123

238
8

867
7

234
4

23
38

58
89

54
47

86
67

98
87

86
67

12
24

23
34

12
23

19
92

23
32

43
31

Wejcie

1 92

5 89

9 87

8 67

8 67

5 47

2 38

2 34

2 32

4 31

1 24

We

RadixSort2(We)
m  length(Liczba)
for k  1 to m do

for j  0 to n - 1 do
Klucz[j]  Cyfra(We[j], m - k)
SortujStabilnie(We.Klucz)

Etap 2

X 11
1000
P 10
0000
A 00
0001
R 10
0010
S 10
0011
T 10
0100
L 01
1100
E 00
0101
E 00
0101
M 01
1101
N 01
1110
G 00
0111
O 01
1111
Etap 3

P 10000
A 00001
R 10010
S 10011
T 10100
E 00101
E 00101
G 00111
X 11000
L 01100
M 01101
N 01110
O 01111
Etap 4

A 00001
E 00101
E 00101
G 00111
L 01100
M 01101
N 01110
O 01111
P 10000
R 10010
S 10011
T 10100
X 11000
Etap 5

// 0 do bytesword-1

Etap 1

T 101
100
X 110
000
P 100
000
L 011
100
E 001
101
A 000
001
E 001
101
M 011
101
N 011
110
R 100
010
S 100
011
G 001
111
O 011
111

return (a>>byte*(bytesword k -1)) & (r - 1);


}
a=0x1234abcd; Digit(a, 2)  ab

N 0111
10
10
R 1001
T 1010
00
X 1100
00
P 1000
00
L 0110
00
E 0010
01
A 0000
01
S 1001
11
G 0011
11
E 0010
01
M 0110
01
O 0111
11

int Digit(long a, int k)


{ // zwraca bajty sowa a numerowane od lewej do prawej,

WE

1
0
1
0
0
1
1
1
1
1
0
0
0

const int r = 1<< byte;

R5.6d

Binarne sortowanie pozycyjne


Rozwamy sortowanie zbioru DUYCH liter alfabetu angielskiego.
Znaki kodu ASCII traktowane s jako cigi 5-cio bitowe (rekordy znakw 0 1).
Operujemy wic na liczbach o podstawie r = 2.
Sortowaniu podlegaj rekordy z kluczami zawierajcymi 1 bit.
Zbir dzielony jest tak aby wszystkie rekordy z kluczami o wartoci 0 wystpiy przed rekordami
z kluczami o wartoci 1.
Sortowanie wymaga 5-ciu przej, przesuwajc si po kluczach od prawej do lewej.
Binarne sortowanie pozycyjne od prawej do lewej
E 00101
1
N 01110
0
1
A 00001
R 10010
0
T 10100
0
S 10011
1
G 00111
1
E 00101
1
M 01101
1
O 01111
1
X 11000
0
P 10000
0
L 01100
0

Etap 3
czenie

Mona zaimplementowa metod zliczania indeksowanego kluczami lecz musi by ona stabilna.

0.11
0.96
0.45
0.66
0.19
0.22
0.14
0.74
0.27
0.77

0.11
0.14 0.22
0.19 0.27

Etap 2
Sortowanie

987

867

867

589

547

431

238

234

232

Cyfry nale do przedziau 0 k, gdzie zazwyczaj k = 9.


Mona wic stosowa czstkowe sortowanie przez zliczanie.
Kady przebieg przez n liczb m-cyfrowych realizowany
jest w czasie O(n + k).
Wykonywanych jest m przebiegw, std cakowity czas
sortowania wynosi: O(mn + mk).
Jeeli m=const, za k=O(n) to sortowanie dziaa w czasie liniowym.

0.14
0.19 0.27
0.11 0.22
0

Zoono algorytmu zaley od wykorzystanej pomocniczej funkcji sortujcej.

3
4
5

0.77
0.66 0.74

0.45
3

0.45

0.74
0.66 0.77

0.96
8

0.14
0.19
0.11

0.27
0.22

0-0.1 0.
0.1-0.2 0.
0.2-0.3

0.96

0.11 0.14 0.19 0.22 0.27 0.45 0.66 0.74 0.77 0.96

B
0
1
2

R5.6d

0.11 0.96 0.45 0.66 0.19 0.22 0.14 0.74 0.27 0.77

Etap 1
Wstawianie

1 1 4 2 2 2 5 8 8 9 5 1
192

Etap 3
wg
3-ich od prawej

Sortowanie kubekowe

3 3 9 2 3 2 6 8 6 4 3 8

124

Etap 2
wg
2-ich od prawej

48

Algorytmy i Struktury Danych - wykad

5.7. Sortowanie kubekowe


Algorytm zakada, e dane wejciowe s liczbami rzeczywistymi z przedziau [0, 1)
o rozkadzie jednostajnym.
Podziel przedzia [0, 1) na n podprzedziaw o jednakowych rozmiarw, zwanych kubekami.
"Rozrzu" zbir wejciowy n liczb do kubekw, do ktrych nale.
Zakadaa si, e liczby s jednostajnie rozoone w przedziale [0, 1),
wic oczekuje si, e w kadym z kubekw nie bdzie ich zbyt wiele.
Posortuj liczby w kadym z kubekw i Wypisz je, przegldajc po kolei kubeki.

9 4 7 8 3 7 2 2 7 7 4 1

1 23

Etap 1
wg
skrajnie prawych

123

Zbir Wejciowy

589
9

Otrzymujemy wtedy tyle n-elementowych zbiorw, ile jest cyfr w liczbie.


Kady zbir moe by sortowany pomocnicz stabiln funkcj sortujc.
R5.6c
Sortowanie pozycyjne od prawej do lewej

Instytut Aparatw Elektrycznych


Algrm5
Dr J. Dokimuk

0.14
0.27

0.19
0.22

0.11

0.45

6
7
8

0.66
0.77

0.96

BUCKETSORT(We)
n  length[We]
for i  0 to n - 1 do
Wstaw We[i] do listy B[ i ]
for i  0 to n 1 do

Sortuj list B[i]


Pocz listy B[0], B[1], ..., B[n -1]
0.74
R5.6e

Zbir wejciowy stanowi n-elementowa tablica We,


ktrej elementy speniaj nierwnoci 0 We[i] < 1.
Algorytm korzysta z tablicy list B[0.. n - 1].

Czas dziaania algorytmu BucketSort


Pesymistyczny czas wykonywania wszystkich elementw funkcji oprcz sortowania wynosi O(n).
Niech sortowanie wszystkich list realizowane jest przez wstawianie.
Niech Ni bdzie zmienn losow oznaczajc liczb elementw umieszczonych w licie B[i].
Sortowanie przez wstawianie dziaa w czasie O(n2), wic oczekiwany czas posortowania
2
2
elementw na licie B[i] wynosi:
E[O(Ni )] = O(E[Ni ]).
Cakowity oczekiwany czas posortowania elementw na wszystkich listach wynosi:
n 1
n 1
2
2
(5.1)
O( E[ N i ]) = O E[ N i ]

i =0
i =0

Obliczenie w/wym sumy, wymaga okrelenia rozkadw zmiennych losowych Ni.


Mamy n elementw i n list. Prawdopodobiestwo (sukcesu), e dany element trafi do listy B[i]
wynosi 1/n. Prawdopodobiestwo sukcesu jest stae-umieszczenia elementu w licie- i wynosi p=1/n.
Zmienna losowa Ni ma rozkad dwumianowy (Bernoulliego), std prawdopodobiestwo e
zmienna przyjmie warto k wynosi P(Ni = k; n, p) (k sukcesw w cigu n bada).
Warto oczekiwana wynosi E(Ni) = np = 1;
wariancja V(Ni) = np(1 - p) = 1 - 1/n.
Korzystajc z zalenoci E(X2) = V(X) + E2(X), otrzymujemy:
2
E ( N i ) = V ( N i ) + E 2 ( N i ) = 1 1 + 12 = 2 1 O(1)
(5.2)
n
n
Podstawiajc obliczone oszacowanie O(1) do wzoru (5.1), otrzymujemy liniow zaleno
na oczekiwany czas dziaania sortowania kubekowego.

Instytut Aparatw Elektrycznych


Algrm6
Dr J. Dokimuk

49

Algorytmy i Struktury Danych - wykad

Instytut Aparatw Elektrycznych


Algrm6
Dr J. Dokimuk

50

Algorytmy i Struktury Danych - wykad

6. WYSZUKIWANIE WZORCA

6.2. Algorytm Knutha-Morrisa-Pratta

Wyszukiwanie dotyczy znajdowania wszystkich wystpie wzorca w tekcie.


Moe dotyczy wyszukiwania zadanych wzorcw w sekwencjach DNA.
Dany jest jednoznacznie zdefiniowany alfabet np. = { 0,1,2,3,4,5,6,7 }, = { a, b,,z }
Tekst rdowy zapisano w tablicy T[n] o dugoci n.
Wzorzec zawarto w tablicy W[m] o dugoci m.
Tekstami zawartymi w tablicach T i W (zwanymi sowami) s symbole nalece do alfabetu .
Wzorzec W wystpuje z przesuniciem s w tekcie T, gdy zachodz relacje:
0 s n - m oraz T[s+1, s+m] = W[1, m]

Dany jest tekst i wzorzec.


Rozpoczynajc porwnanie acuchw pierwsza rnica pojawia si na
W = 10101111
pozycji q+1, gdzie q=5 jest liczb zgodnych znakw wzorca i tekstu.
Informacje tego typu wykorzystywane s do poprawienia algorytmu naiwnego, poprzez uniknicie
zbytecznych testw i takie modyfikowanie wskanika j aby nie by zerowany za kad zmian s.
W algorytmie "naiwnym" wzorzec zawsze by przesuwany o jeden.
Czasami moliwe jest przesunicie wzorca o wiksz warto, wyznaczan na podstawie
informacji o liczbie q zgodnych znakw wzorca i tekstu.
Analiza wzorca pozwala na znalezienie optymalnego przesunicia s .
Badajc struktur wzorca, mona okreli sposb modyfikacji indeksu j w
przypadku stwierdzenia zgodnoci tekstu ze wzorcem na q pozycjach.

Wzorzec W wystpuje, poczwszy od pozycji s + j tzn. gdy T[s + j] = W[j] dla 1 j m.


s jest poprawnym przesuniciem jeeli W wystpuje z przesuniciem s w tekcie T.
Wyszukiwanie wzorca to znajdowanie w tekcie T 1 2 3 4 5 6 7
wszystkich poprawnych przesuni s w y s z u k i
dla danego wzorca W.
przesunicie s=7
6.1. Algorytm "naiwny" (Brute Force)

8
w

9
a

10 11 12
n i e

n i e

Istot algorytmu jest przeszukiwanie w ptli, okrelonej dugoci wzorca W[1, m].
Sprawdzany jest warunek W[1, m] = T[s+1, s+m] dla kadej z n m +1 moliwych
wartoci przesunicia s.
c e r c e r a
c e r c e r a
c e r c e r a

s=0 c e r a
s=1 c e r a
s=2 c e r a
Wzorzec W mona interpretowa jako okienko przesuwajce si sukcesywnie ( dla narastajcych
wartoci przesunicia s ) nad analizowanym tekstem.
Po kadym przesuniciu okienka (zmiana s) sprawdzane jest ponownie czy wszystkie symbole w
okienku zgodne s z odpowiadajcymi im symbolami w tekcie.
BruteForce(T, W)
int BruteSearch(char *W, char *T)
{
n length[T]
int i, j, N, M = strlen(W);
// j indeks dla wzorca
m length[W]
N = strlen(T);
// dugo tekstu
for s 0 to n m do
for (i = 0, j = 0; (j < M) && (i < N); i++, j++)
if W[1, m] = T[s+1, s+m]
while (W[j] != T[i]) {
then "znaleziono wzorzec"
i = i - (j - 1);
T = 1010100111 W = 1001
j = 0;
T: 1010100111
}
W: 1001
if (j == M) return (i - M); else return (i);
}
1001
n
1001
Rozwamy tekst T skadajcy si z cigu n symboli a (a ) i
1001
wzorzec W = am.
1001 Znaleziono dla s=4
Dla kadego z n m + 1 moliwych wartoci przesunicia s,
ptla for bdzie wykonywana m razy, aby sprawdzi
Czy ponisza koncepcja jest moliwa?
poprawno przesunicia.
c e r c e r a
Pesymistyczny czas dziaania wynosi (porwnania):

O((n - m + 1)m), za dla m = n/2  O(n2).
Algorytm wyszukiwania naiwnego nie jest optymalny, gdy s=0 c e r a
q = 3
informacja o strukturze tekstu dla danej wartoci S nie jest
brana pod uwag przy nastpnych poszukiwaniach.
c e r c e r a
Po kadej zmianie s nastpuje cofanie si o ca dugo
wzorca, zapominajc o wynikach testw wczeniejszych.
s=s+q = 3 c e r a

T = 10101001110

Niech oznacza zbir wszystkich sw utworzonych z alfabetu . Dugo sowa x oznaczmy |x|.
Konkatenacja (zoenie) dwch sw x oraz y (oznaczona xy) jest sowem o dugoci |x| + |y|.
Sowo w jest prefiksem sowa x (w x), gdy x = wy dla sowa y , |w| |x|.
Sowo w jest sufiksem sowa x (w x), gdy x = yw dla sowa y , zatem |w| |x|.
Dla sowa x = abcca: ab jest prefiksem (ab
abcca) za cca jest jego sufiksem (cca abcca)
Niech Wk oznacza ksymbolowy prefiks W[1, k] wzorca W[1, m]. Zatem W m = W = W[1, m].
Niech Tk oznacza ksymbolowy prefiks T[1, k] tekstu T[1, n].
Zatem Tn = T =T[1, n]
Wyszukiwanie wzorca jest problemem znajdowania wszystkich przesuni s w
przedziale 0 s n m takich, e W Tk+m.
Przesunito okienko ze wzorcem W = ALALAno wzgldem tekstu T na pozycj s = 4
Stwierdzono, e q = 5 symboli
wzorca pasuje do tekstu.

e s

A L A L A e f

g f

e f

s=4 A L A L A n o
q=5

Analiza aktualnej cze wspln W i T


Najduszym prefiksem czci wsplnej W i T, bdcym jednoczenie sufiksem jest W3.
Informacja o czci wsplnej zapamitywana jest w tablicy [q] = k.
W5 A L A L A
gdzie k = 3 jest dugoci wsplnego sufiksu i prefiksu fragmentu wzorca;
q = 5 jest wspln czci wzorca i tekstu. [5] = 3;
[3] = 1 sufiks W3 A L A
k=3
Poniewa q symboli wzorca W pasuje do tekstu T dla przesunicia s,
nowe
W3 A L A prefiks
to kolejne przesunicie okrela wzr: s
= s + (q [q])
j

e s t A L A L A e

s=6 A L A L
nowa cz wsplnaq=3
s=8 A L

f g f e f
j= [5] + 1
A n o

si = 4 + (5 3) = 6

A L A n o

si+1 = 6 + (3 1) = 8

Dla nowego przesunicia si nie trzeba sprawdza kpierwszych symboli wzorca W z


opowiadajcym im tekstem T, gdy prefix Wk by jednoczenie sufiksem czci wsplnej dla s.
Niech symbole wzorca W[1, q] pasuj do symboli tekstu T[s + 1, s + q].
Dla zadanego wzorca W[1, m] funkcja prefiksowa okrelona jest zalenoci:
(q) = max{ k: k < q i Wk Wq }
(q) jest maksymaln dugoci prefiksu wzorca W, bdcego sufiksem Wq.
Najlepszy przypadek to snowe = s + q , gdy na czci q nie ma wsplnego prefiksu i sufiksu.

Instytut Aparatw Elektrycznych


Algrm6
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

51

KMP_Search(W, T)

Prefix(W)

m length(W); n length(T)
Prefix(W)
q0
for i1 to n do
while q > 0 && W[q+1] T[i] do q [q]
if W[q+1] = T[i] then q q + 1
if q = m then s i m
// znaleziono
q [q]

mlength(W)
[1]0; k0
for q2 to m do
// q zakadana cz wsplna
while k>0 && W[k+1] W[q] do k [k]
if W[k+1] = W[q] then k k + 1

[q] k
q
1 2 3 4 5 6 7 8 9 10
Wq a b c d b a b c a b
return
(q) 0 0 0 0 0 1 2 3 1 2

// analiza wzorca

Podsumowanie:
1. Dla kolejnych podtablic[1..q] wzorca W[1..m] zbuduj tablic [q] zawierajc
hipotetyczne dugoci wsplnych prefiksw i sufiksw.
2. Przesuwaj wzorzec nad tekstem w poszukiwaniu czci wsplnych q wzorca i tekstu.
3. Nowe przesunicie ramki wzorca okrela wzr:
snowe = s + (q [q]).
4. Po wykonaniu nowego przesunicia rozpocznij porwnania od poz. (q)+1 wzorca.
T o B A T A i
B A T A i

B A T A m a m B A T

B A T A N

s=2 B A T A i

1 2 3 4 5 6 7 8 9 10
q
Wq B A T A i B A T A N
(g) 0 0 0 0 0 1 2 3 4 0

B A T A N
B A T A i

B A T A N

s=11 B A T A i

Algorytmy i Struktury Danych - wykad

52

6.3. Algorytm RabinaKarpa


Algorytm bazuje na pojciach z teorii liczb, interpretujc tekst zoony z ksymboli jako
liczb kcyfrow w ukadzie dziesitnym. Niech T = "2269538" za
W = "695".
2 2 6 9 5 3 8
s=0

6 9 5

2 2 6 9 5 3 8
s=1

6 9 5

2 2 6 9 5 3 8
s=2

6 9 5

Schemat pokazuje, e istot algorytmu jest umiejtno szybkiej zamiany tekstu w liczb.
Oglnie mona przyj, e kady symbol jest liczb w systemie o podstawie d, co
oznacza, e dysponujemy delementowym alfabetem = { 0, 1, 2, 3,, d-1 }.
Dany jest dowolny cig M znakw T[i], T[i+1],,T[i+M-1].
abcdefghlj
Niech d (podstawa systemu) bdzie liczb wszystkich moliwych znakw.
Cig znakw T moemy interpretowa jako liczb cakowit postaci:
(0)
M-1
M-2
x = d T[i]+ d T[i+1]+ + dT[i+M-2] + T[i+M-1]
abcdefghlj
Jeeli przesuniemy si w tekcie o jeden znak to otrzymamy now liczb postaci:
x(1) = dM-1T[i+1] + dM-2T[i+2] + + dT[i+M-1] + T[i+M]
abcdefghlj
Liczb x(1) mona wyznaczy iteracyjnie: x(1) = d(x(0) dM-1T[i]) + T[i + m]
lub x(1) = d(x(0) mod dM-1) + T[i + m]
Wemy alfabet, w ktrym symbole s cyframi dziesitnymi = {0,1,2,3,4,5,6,7,8,9} (d = 10).

j = [9] + 1
s=7

Instytut Aparatw Elektrycznych


Algrm6
Dr J. Dokimuk

si = 2 + (9 4) = 7
si+1 = 7 + (4 0) = 11

Dla zadanego wzorca W[1, m] moemy poda odpowiadajc mu liczb dziesitn p.


Dla tekstu T[1, n] wybieramy podsowo o dugoci m tzn. T[s+1, s+m] i przypisujemy
warto dziesitn ts , gdzie s przyjmuje odpowiednio wartoci s = 0, 1, ,n m.
Zgodno ts = p zachodzi wtedy i tylko wtedy, gdy T[s+1, s+m] = W[1, m].

T o B A T A i
B A T A i
s=2

B A T A i

B A T A N

B A T A N

B A T A i

B A T A N
j = [9] + 1

s=7 B A T A i

B A T A N

Warto s jest poprawnym przesuniciem wtedy i tylko wtedy gdy ts = p.


Funkcja Prefix() wykonuje analiz
wzorca w poszukiwaniu najduszego
wsplnego sufiksu i prefiksu, dla
hipotetycznie narastajcej zaoonej
czci wsplnej wzorca i tekstu.

Warto p (wzorzec) mona obliczy w czasie O(m) z reguy Hornera (2*103 +4*102 +3*101+6):
p = (((10W[1]+ W[2])10 + + W[m - 2])10 + W[m - 1])10 + W[m]
Dla tekstu T[1, n] odpowiadajc warto t0 mona obliczy wg tej samej reguy w czasie O(m).
Wartoci t1, t2, , tn - m mona obliczy w czasie O(n m) z zalenoci iteracyjnej:
ts+1 = 10(ts 10m 1T[s + 1]) + T[s + 1+m]

Tablica next[ ] (odpowiada ), reprezentuje


maksymaln dugo k sufiksu sowa W[j],
bdcego jednoczenie jego prefiksem i tak,
e W[k+1] W[j+1] jeeli 0 < j < m.

Najwikszy zysk osiga si w


przypadku tekstw o duym stopniu
samopowtarzalnoci.
W innych przypadkach zysk moe by sabo
zauwaalny.

int next[100];
// odpowiada tablicy (q)
void Prefix(char *W)
{ int j, q
// q zakadana dugo czci wsplnej
int m = strlen(W);
next[0] = -1;
for ( q=0, j=-1; q<m; q++, j++, next[q] = j )
while ((j>=0) && (W[q] != W[j])) j = next[j];
}
1 2 3 4 5 6 7 8 9 10
q
Wq a b a b a b a b c a
(q) 0 0 1 2 3 4 5 6 0 1

Czas dziaania funkcji Prefix(W) w najgorszym przypadku jest klasy O(m)


Czas dziaania funkcji KMP_Search(W, T) wynosi O(n).
Czas dziaania caego algorytmu KMP jest O(n + m), gdy zawiera jedno woanie funkcji Prefix.
Zalet algorytmu jest to, e wskanik i dla tekstu T[i] nie jest nigdy zmniejszany.
Oznacza to moliwo przegldania plik danych od pocztku do koca bez cofania si w nim.
Moe mie to znaczenie przy liniowym przegldaniu duych plikw bez ich buforowania,
gdzie charakter wykonywanych czynnoci nie zezwala na cofanie si w otwartym pliku.

T[s+1] gdy warto startowa s=0 , za


wektory numerowane s [1, n] lub [1, m]

m1

ts 10
T[s + 1] usuwa najbardziej znaczc cyfr z ts ,
10()
przesuwa cyfry liczby o jedn pozycj w lewo,
+ T[s +m +1]
wstawia najmniej znaczc cyfr.
Dugo wzorca m = 5, ts = 92345, za nastpny fragment tekstu ma posta T = 9234567 .
ts+1 = 10(92345 1049) + 6 = 23456 lub ts+1 = 10(92345 mod 104) + 6
m 1

Staa 10
jest obliczana raz, zatem kadorazowa iteracja ts wymaga wykonania staej liczby
operacji arytmetycznych.
Wartoci p oraz t0, t1, , tn -m mona obliczy w czasie O(n + m).
Algorytm umoliwia znalezienie wszystkich wystpie wzorca W w tekcie T w czasie O(n + m).
podstawa d = 64
={
= 0
a =1
b =2
c =3
d =4
e =5
...
z = 26

A = 27
B = 28
C = 29
D = 30
E = 31
...
Z = 52 }

W = Cabec
m=5
4
3
2
p = 2964 +164 +264 +564+3 = 486809923
p = (((C64+a)64+b)64+e)64+c
T=Gdzie jestnaszCabec
t0=(((3364 + 4)64 + 26)64 + 9 )64 +5 = 554803781
4
t1 =dzie= 64(t0 64 33) + 0 =
4
lub t1 = 64(t0 mod 64 ) + 0 =

Instytut Aparatw Elektrycznych


Algrm6
Dr J. Dokimuk

53

Algorytmy i Struktury Danych - wykad

Jeeli (a mod n) = (b mod n) to liczba a przystaje do liczby b modulo n


i zapisuje si: a b (mod n).
Zapis a b (mod n) oznacza, e a nie przystaje do b (mod n) .
Pojawiaj si trudnoci, gdy wzorzec W[1, m] jest dugi, co pociga due wartoci p oraz ts.
Problem dugiego wzorca W mona omin obliczajc wartoci p i ts mod q , gdzie warto q
jest odpowiednio dobrana.
Pozwala to utrzyma czas dziaania na poziomie O(m + n).
m = 5; W = "34567"; p=34567;
t0 = "23683", t0 mod q = 2;
1

q = 17; p mod q = 6
t1=36834, t1 mod q =12

10 11 12 14 14 15 16 17

2 3 6 8 3 4 5 6 7 3 8 6 2 8 3 8 7
ti mod q  2

12 4

6 11 9

prawidowe dla s=4

14 13 4

6 14

mod 17

NIEzgodne

Zazwyczaj za warto q przyjmuje si tak liczb pierwsz, e d*q zajmuje jedno sowo
komputerowe, co umoliwia realizacj operacji arytmetycznych z pojedyncz precyzj.
Dla delementowego alfabetu ={0, 1, , d-1} wzr iteracyjny na wartoci ts+1 przyjmuje posta:
m-1
ts + 1 = (d(ts hT[s + 1]) + T[s + m +1]) mod q
gdzie h = d
mod q.
Zauwamy, e ts p (mod q) nie implikuje rwnoci ts = p.
Zatem przesunicie s moe lecz nie musi by waciwe.
Zauwamy: jeeli ts p (mod q) to na pewno ts p i tym samym przesuniecie s jest niewaciwe.
W praktyce test ts p (mod q) uywany jest do eliminowania niepoprawnych przesuni.
Gdy przesunicie spenia powyszy warunek naley jeszcze zweryfikowa czy rzeczywicie jest poprawne.
Weryfikacj poprawnoci mona przeprowadzi bezporednio porwnujc W[1, m]=T[s+1, s+m].
Przyjmujc warto q dostatecznie du mona spodziewa si rzadkiej potrzeby dodatkowej weryfikacji.
RabinKarp(T,W, d, q)
n length [T]; m length [P]
h dm - 1 mod q
p 0;
t0 0
for i 1 to m do
p(dp + W[i]) mod q
t0(dt0 + T[i]) mod q

// p = W[1, m] mod q
// t0 = T[1, m] mod q

for s 0 to n m do // iteracja dla wszystkich przesuni


if p = ts then if W[1, m] = T[s+1, s+m]
then "Znaleziono dla s=", s
if s < n - m then ts+1(d(ts-T[s+1]h)+T[s+m+1]) mod q

Zmienna h okrela warto najbardziej


znaczcej cyfry w mcyfrowym okienku.
Przy zgodnoci p = ts , bada si
warunek W[1, m] = T[s+1, s + m] aby
wyelimino-wa niejednoznaczno.
Ostatni wiersz oblicza ts+1 mod q
na bazie znanej wartoci ts mod q.
Pesymistyczny
czas
dziaania
algorytmu RabinaKarpa wynosi:
O((n m + 1)m),
gdy algorytm sprawdza kade
poprawne przesuniecie w sposb
bezporedni (podobnie jak "naiwny").

Mona dowie, e liczba bdnych identyfikacji wynosi O(n/q), gdy prawdopodobiestwo


tego, e dowolny symbol T[i] bdzie przystawa do p mod q nie przekracza 1/q.
Oczekiwany czas dziaania algorytmu Rabina-Karpa wynosi O(n) + O(m(v + n/q)),
gdzie v jest liczb poprawnych przesuni.
Jeeli oczekiwana liczba poprawnych przesuni jest klasy O(1) (maa), za wybrana liczba
pierwsza q jest wiksza od dugoci wzorca m to algorytm dziaa w czasie O(n + m).
Podstawa systemu d powinna by potg liczby 2, nawet gdy jest to warto wiksz od
wielkoci alfabetu. Umoliwia to implementacj mnoenia poprzez operator przesunicia bitowego.

Instytut Aparatw Elektrycznych


Algrm6
Dr J. Dokimuk

#include <stdio.h>
#include <string.h>
#include <ctype.h>

54

Algorytmy i Struktury Danych - wykad

Alfabet:
= { ,a, b, c, ...,z, A, B, C,...,Z }
// zwraca numer litery w alfabecie oraz postaw alfabetu d = 64

int Index(char zn)


{
switch(zn)
{
case ' ': return 0;
default: if(islower(zn)) return zn - 'a' + 1;
else return zn - 'A' + 27;
}
}

// spacja=0

a=1
b=2
c=3
d=4
e=5
f=6
g=7

z = 26

A = 27
B = 28
C = 29
D = 30
E = 31
F = 32
G = 33

Z = 52

int RK_Search (char *W, char *T, int d, int q)


{
long int i, M, N, h = 1, p = 0, tm = 0;
M = strlen(W);
N = strlen(T);

for (i = 1; i < M; i++) h = (d*h) % q;

// oblicza wartoci h = dm - 1 mod q

for (i = 0; i < M; i++) {


p = (d*p + Index(W[i])) % q;
tm = (d*tm + Index(T[i])) % q;
}

// oblicza wartoci p (dla wzorca)


// oblicza wartoci t0 (dla 1-go podcigu)
(a+b+c) mod q = ((a+b) mod q + c) mod q

for (i = 0; p != tm; i++) {


tm = (tm + d * q - Index(T[i]) * h) % q;
tm = (tm * d + Index(T[i+M])) % q;
if (i > (N - M)) return (-1);
}
return (i);
}

// +d*q zabezpiecza przed wynikiem ujemnym


// nie znaleziono
p = 29 644+1 643+2 642+5 64+3 = 486809923
p = c + 64(e + 64(b + 64(a + 64C)))
p mod 121 = 61

int main()
// P63 RabinKarp
t0 = 5 + 64(9 + 64(26 + 64(4 + 64G)))= 554803781
{
t0 mod 121 = 26
int l;
char *t1 = "Gdzie jest nasz Cabec malowany",
*w = "Cabec";
l = RK_Search(w, t1, 64, 121);
if (l > 0) printf("\n Znaleziono na poz=%d", l);
else printf("\n Nie znaleziono ");
return 0;
}
Znaleziono na poz=16

Instytut Aparatw Elektrycznych


Algrm7
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

55

7. HASZOWANIE (MIESZANIE)
Problem dotyczy wyszukiwania informacji w tablicach wedug pewnej specyficznej metody.
Technika wyszukiwania sekwencyjnego realizuje si w czasie O(n), za binarnego O(lg(n)).
Dla struktury danych jak jest tablica z haszowaniem czas wyszukiwania
informacji mona sprowadzi do teoretycznego poziomu O(1).
Istot metody jest wyznaczenie pozycji klucza w tablicy na podstawie jego wartoci.
Warto klucza jest podstaw okrelenia pooenia elementu. Znajc klucz mona dosta si
bezporednio do dowolnego miejsca w tablicy, pomijajc kosztowne operacje przeszukiwania.
Naley znale odpowiedni funkcj h(KEY), ktra przeksztaci klucz KEY (liczba, rekord,
acuch) w indeks tablicy przechowujcej wartoci tego samego typu co klucz.
Funkcja h(key) przeksztacajca klucz w indeks nosi nazw funkcji haszujcej (hash function).
Idealna funkcja haszujc: jeeli przeksztaca rne klucze w rne liczby.
Mieszanie klucza: operacja zastosowania funkcji haszujcej dla konkretnego klucza.
Tablice z haszowaniem s wygodn struktur danych, reprezentujc sowniki, na ktrych
wykonywane s tylko trzy operacje: INSERT, SEARCH, DELETE.
Przykadem mog by kompilatory jzykw programowania, ktre generuj tablice symboli o
kluczach, bdcych identyfikatorami zmiennych.
Idealna funkcja haszujca wymaga, aby na tablic zarezerwowano tyle miejsca ile moe
wystpi rnych elementw. Liczba elementw nie zawsze jest znana. Nie jest np. moliwe
okrelenie pojemnoci tablicy symboli generowanych przez kompilator, gdy zaley to od
wielkoci programu. Przyjcie wielkoci maksymalnie moliwej, czsto jest nierealne fizycznie.
Zamy, e jzyk programowania (np. C) dopuszcza dugo zmiennych do 31 znakw jako
30

dowoln kombinacj 36 znakw podstawowych. Daje to liczb 26 36i (uwzgldniajc, e nazwa


i =0

zmiennej nie moe zaczyna si od cyfry), ktra fizycznie nie moe by podstaw do rezerwowania
takiego obszaru pamici, aby zapewni kadej zmiennej osobn pozycj.
W praktyce tworzone programy zawieraj z reguy nie wicej ni kilkaset rnych
zmiennych, tym samym zarezerwowanie tablicy o rozmiarze T[1000] jest na og
wystarczajce, jakkolwiek uniemoliwia to zbudowanie idealnej funkcji haszujcej.
Niech dla potrzeb testowania nowego kompilatora przyjto, e identyfikatory zmiennych bd
maksymalnie trzyznakowe i stanowi kombinacj 3 liter (a, b, c).
Otrzymujemy cig zmiennych: a, b, c, aa, bb, cc, ab, ba, ac,ca, bc, cb, aaa, aab, aac, abc, aba, baa, caa, cba,
2

bca, bbc, bba, ,ccc o licznoci 3 * 3i = 39.

index i nazwa adres

:
Poszczeglnym literom przypiszemy cyfry a  1, b  2, c  3.
:1008
11
aa
Wwczas cigowi zmiennych mona przypisa liczby typu integer

:
( ab12, aab112 ,, ccc333), ktre staj si indeksami
:2300
121 abc
komrek tablicy symboli, przechowujcych np. adresy.

333 ccc
:1204
Zmienna ab ulokowana zostanie w komrce 13, ccc w komrce 333.
Dostp przez program do dowolnej zmiennej realizowany jest w czasie O(1), gdy klucz
do konwersacji tekstu na liczb integer staje si generatorem adresu tekstu.
Wymagane jest zarezerwowanie tablicy o wymiarze T[333] mimo, e maksymalna liczba
identyfikatorw zmiennych nie przekroczy 39.
Mwimy, e funkcj haszujc h jest algorytm zamieniajcy cigu znakw ASCII w liczb.
Jeeli przyjmiemy za identyfikatory zmiennych symbole np. 11sto znakowe (a k) i
przypiszemy im odpowiedniki liczbowe (1 11), to stosujc identyczn funkcje haszujac
otrzymamy wyniki niejednoznaczne.
Przykadowo h("ka") = 111 oraz h("aaa") = 111.
Jeeli bdziemy dodawa kody wszystkich znakw w nazwie, za sumy uyjemy jako
indeksu to te nie unikniemy niejednoznacznoci.
Kolizja funkcja haszujca generuje identyczne wartoci liczbowe dla rnych kluczy.
Jako funkcji haszujcej zaley od skutecznego unikania przez ni kolizji.
i =0

Instytut Aparatw Elektrycznych


Algrm7
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

56

7.1. Haszowanie acuchowe


Wemy 4000 rekordw z danymi osobowymi pracownikw i 11-cyfrowe numery PESEL.
Tablica bezporednia miaaby pojemno 100 miliardw elementw, z czynnym wykorzystaniem 4000.
Funkcja mieszajca moe mie posta: h(key) = key mod 100, zwraca ostatnie dwie cyfry klucza.
Klucz mieszany jest do indeksu i, po czym umieszczany wraz z jego rekordem w tablicy S[i].
Ta strategia nie rozmieszcza kluczy w posortowanej sekwencji.
Dla duej liczby kluczy, przynajmniej dwa klucze zostan zmieszane do tego samego indeksu.

Metoda acuchowa jest jedn z najlepszych metod unikania kolizji.


Utworzy list dla kadego moliwego indeksu i Bucket[
9
Bucket[i]
h(key)
key) = key div 10

umieci wszystkie wartoci mieszane do tego 0


samego indeksu w powizan z tym indeksem list.
01123012345
01
1
Jeli mieszamy dwie pierwsze cyfry numeru PESEL, 2
02122123873
02
moemy stworzy tablic wskanikw Bucket[ ], ktra 3
bdzie indeksowana od 0 do 99.
04122123873
04
04110525434
04
4
.
Wszystkie klucze zmieszane do indeksu i zostan
wwczas umieszczone na licie jednokierunkowej, 50
50110923762
50081223741
50
50
.
wskazywanej przez element Bucket[i].
Jeli mieszamy 2-pierwsze cyfry liczby, musimy mie 98
100 list ( lecz moemy przechowywa np. 400 kluczy).
99111587654
99
99
R7.1
Liczba list nie musi by rwna liczbie kluczy
Jeli liczba kluczy jest wiksza od liczby list, moemy by pewni wystpienia kolizji.
Mamy 100 kluczy i 100 list oraz prawdopodobiestwo przydzielenia kadego klucza
do kadej listy jest rwne, to prawdopodobiestwo umieszczenia wszystkich kluczy w

1
jednej licie wynosi: 100

100

100

10 198 .

Efektem zastosowania funkcji mieszajcej jest moliwo stworzenia lepszego


algorytmu przeszukujcego ni algorytm przeszukiwania binarnego.
Analiza haszowania acuchowego
Szukanie pewnego klucza wymaga sekwencyjnego przeszukiwania listy jednokierunkowej.
Jeli klucze znajduj si w jednej licie, mamy przeszukiwanie sekwencyjne O(n)  fatalnie
Z najlepsz sytuacj mamy do czynienia przy rwnomiernym rozoeniu kluczy pomidzy listy.
Jeli istnieje n kluczy i m list, kada lista powinna zawiera = n/m kluczy ( -wsp. zapenienia).
Wszystkie listy mog przechowywa po n/m kluczy gdy n jest wielokrotnoci liczby m.
Tw. 7.1. Jeli n kluczy rozoonych jest rwnomiernie w m listach, liczba porwna wykonywanych podczas przeszukiwania zakoczonego niepowodzeniem wynosi .
Tw. 7.2. Jeli n kluczy rozoonych jest rwnomiernie w m listach i kady z kluczy jest z takim
samym prawdopodobiestwem poszukiwany, rednia liczba operacji porwnania
wykonywanych podczas przeszukiwania zakoczonego sukcesem wynosi: 0.5 (1 + ) .
Tw. 7.3. Jeli mamy n kluczy i m list, oraz zakadamy e prawdopodobiestwa umieszczenia
kluczy w poszczeglnych kubekach s rwne,
to prawdopodobiestwo tego, e przynajmniej jedna lista bdzie przechowywa
k 1
n 1
co najmniej k kluczy, jest mniejsze lub rwne wyraeniu:
.
k m
Niech liczba kluczy n jest rwna liczbie list, czyli n = m.
Obliczajc (Tw.7.3) grne ograniczenia dla prawdopodobiestw tego, e przynajmniej jeden
kubeek zawiera k = lg(n) kluczy moemy stwierdzi, e dla:
n = 128 szansa na to, e czas przeszukiwania przekroczy lg(n) jest mniejsza ni 0.021.
n = 1024 szansa na to, e czas przeszukiwania przekroczy lg(n) jest mniejsza ni 0.00027.

Dla duych n moemy by pewni, e zastosowanie metody mieszania bdzie


bardziej efektywne od algorytmu przeszukiwania binarnego.

Instytut Aparatw Elektrycznych


Algrm8
Dr J. Dokimuk

57

Algorytmy i Struktury Danych - wykad

Instytut Aparatw Elektrycznych


Algrm8
Dr J. Dokimuk

58

Algorytmy i Struktury Danych - wykad

8. PODSTAWOWE STRUKTURY DANYCH

8.1.1. Beznawiasowa algebra ukasiewicza Odwrotna Notacja Polsk (ONP)

Abstrakcyjny Typ Danych typ danych dostpny tylko za porednictwem stosownego interfejsu.

Zapisanie wyrae arytmetycznych bez uycia nawiasw zmieniajcych kolejno dziaa.


W ONP symbole operandw poprzedzaj symbol operatora.
Translacja wyrae arytmetycznych na zapis ONP wymaga
Operator
Priorytet
ustalenia priorytetw dla operatorw arytmetycznych.

8.1. Stos (stack)


Stos liniowa struktura danych, umoliwiajc zapis i odczyt informacji tylko z jednego koca.
Ze zbioru usuwany jest ten element, ktry zosta do niego dodany jako ostatni.
Jest to strategia Last-in First-out czyli LIFO. Przypomina stos kartek papieru.
Kartka moe zosta pobrana, gdy na stosie znajduj si inne kartki.
Kartk mona bezpiecznie pooy, gdy na stosie jest wolne miejsce.
Operacje interfejsu stosu:
inicjalizuje (oprnia) stos,
 Init(S)
 Empty(S)
testuje czy obszar stosu jest pusty,
 Full(S)
testuje czy obszar stosu jest zajty,
 Push(el, S) umieszcza element na szczycie stosu,
 Pop(S)
pobiera (i usuwa) element ze szczytu stosu (destrukcja stosu).
Naturaln implementacj stosu wydaje si tablica. W tablicy znajduj si zawsze jakie wartoci i
nigdy nie jest pusta.
Jak oznacza nieuywane komrki, umieszczajc 0 czy 32000 ?
Mona wprowadzi dodatkow zmienn, przechowujc informacje o 1szej wolnej pozycji.
Niech stos zawiera nelementw ulokowanych w tablicy S[1, n].
Wprowadmy dodatkowy obiekt wierzchoek stosu topS.
Init(S)
topS  0
Empty(S)
if topS =0 then return ok
else return !ok.
Full(S)
if topS = max then return ok
else return !ok.
Push(el, S)
if Full(S) then Error Stos peny
else S[topS]  el
topS  topS + 1
Pop(S)
if Empty(S) then Error Stos pusty
else topS  topS 1
return S[topS]

void Init(char *S)


{ topS = 0 }
3
int Empty(char *S)
2
{ return (topS == 0) ; }
1
4 0
int Full(char *S)
{ return { top == MAX) ; }
void Push(char zn, char *S)
{
if Full(S)) puts(Stos peny);
else S[topS++] = zn;
}
char Pop(char *S )
{
if Empty(S)) puts(Pusty);
else return S[--topS];
}

22 44 2 12
topS = 5
(a) Push(33, S), Push(54, S)
1

22 44 2 12 33 54
topS=7
(b) Pop(S), Pop(S), Pop(S)
1

22 44 2 12 33 54
topS = 4
Elementy 12, 33, 54 nie
nale ju do stosu.

Zmienna topS zwizana cile z okrelonym stosem, jak w przykadowej implementacji.


Uycie wicej ni jednego stosu wymaga pisania kolejnych pakietw procedur.
Istot implementacji jest jeden zestaw funkcji, umoliwiajcy prac z wieloma stosami.
Naiwnym rozwizaniem problemu byoby umieszczenie zmiennej top jako parametru kadej
funkcji, ktry to jako szczeg implementacyjny powinien by przed programem uytkownika ukryty.
Wskanik stosu mona umieci wewntrz stosu, a dokadnie w void Init(char *S)
zerowej komrce tablicy tzn. S[0]  top.
{ S[0] = 0 }
Implementacja taka ogranicza typ elementu wstawianego do void Push(char zn, char *S )
stosu. Moe to by tylko typ int lub char, gdy warto {
komrki S[0] jest modyfikowana przez funkcje Push() i Pop(). if Full(S)) puts(Stos peny);
W przypadku danych typy char rozmiar stosu ograniczony
else S[S[0]++] = zn;
jest do 255 elementw. Dla liczb rzeczywistych konieczna }
jest konwersji typw w funkcji Push np.: S[ (int) S[0]++].
struct STACK {
Struktura o 2-ch polach jest uniwersaln implementacj stosu.
int top;
Jedno z nich przechowuje informacje o wierzchoku stosu,
typS vec[maxStack];
drugie waciwe dane.
};

funkcja (sin, log,)


potgowanie ^
mnoenie, dzielenie
negacja ( * / neg )
dodawanie
+
odejmowanie -

Infix  Postfix Conversion (konwersja z lewej ):


5 + ((2 + 4) * (3 + 2))
 524+32+*+
((9 + (3*(8 3)))/4) 6
a*cos(b+c)^d e*f 
y := a+b*c 

9383*+4/6

abc + cos d ^ * ef *

0
1
2
3

yabc*+:=

Powszechne stosowanie ONP wynika z atwoci implementacji przy uyciu stosu.


Algorytm obliczania wartoci wyraenia postfiksowego
1. pobierz kolejno symbole wyraenia ONP w
kolejnoci od lewej do prawej;
2. jeeli symbol jest liczb (lub zmienn) to od
go na STOS;
3. jeeli jest operatorem to pobierz dwa
argumenty ze STOSU, wykonaj operacj,
wynik od na STOSIE.
Dla
operatorw
nieprzemiennych
(dzielenie, odejmowanie) naley ustali w
jakiej kolejnoci bd wykonywane dwie
operacje Pop().
4. czynnoci powtarzaj do wyczerpania danych,
wwczas na STOSIE znajdzie si obliczone
wyraenie.
2+3*(4+5)  2 3 4 5 + * +
2ga kolumna zawiera symbole
pojawiajce si na wejciu.
3cia zawarto stosu po kadym
obiegu ptli gwnej.
L.p. Wejcie Stos
1
2
2
2
3
2 3
3
4
2 3 4
4
5
2 3 4 5
5
+
2 3 9
6
2 27
*
7
29
+

Rys. 8.2. Obliczanie wartoci wyraenia w ONP

EvalPost(char *bufor)

// oblicza warto postfixa

typeStack S;
// definicja stosu
Init(&S);
// inicjalizacja stosu
typElemS zn;
int n = strlen(bufor), wrk, i;
for (i=0; i<=n; zn=bufor[i++]) {
if (zn == '+') Push( (int)Pop(&S) + (int)Pop(&S), &S);

if (zn == '') Push(-(int)Pop(&S) + (int)Pop(&S), &S);


if (zn == '*') Push( (int)Pop(&S) * (int)Pop(&S), &S);

if (zn == '/') { wrk = (int)Pop(&S);


Push((int)Pop(&S)/wrk, &S);
}
if ((zn>='0') && (zn <= '9')) Push(zn-48, &S);
}
2345+*+ = 29
return Pop(&S);
2345-*+ = -1
}
9383-*+4/6- =0

Instytut Aparatw Elektrycznych


Algrm8
Dr J. Dokimuk

#include <iostream.h>
int sA[80],

topA;

void InitStack()
{ topA=0; }
void Push(int data)
{ sA[topA++] = data;
}
int Pop()
{ return (sA[--topA]);
}

59

Algorytmy i Struktury Danych - wykad

main()
// P81 243+51+**
{ InitStack();
Push(2); Push(4); Push(3);
Push(Pop() + Pop());
Push(5); Push(1);
Push(Pop() + Pop());
Push(Pop() * Pop());
Push(Pop() * Pop());
cout <<"Wynik ="<<Pop()<<endl;
}
Wynik = 84

2*((4+3)*(5+1)) == 243+51+**
Stan stosu: 243+51+**
3
4 7
4
2 2
2
2
5
7
2

1
5
7
2

6
7
2

42
2

84

Przykad: (5*(((9 + 8)*(4*6)) + 7))  598+46**7+*


2 + 3*(4 + 5)
We STOS Wy
2
2
+
+
3
3
* +*
(
+*(
4
4
+ +*(+
5
5
)
+*
+
/0
*
+

#include "stos.h1d"

void Infix_Postfix(char *We, char *Wy)


{

// P8_3a

Stack S;
Init(&S);
// inicjalizacja stosu
typS zn;
int i, k = 0, n = strlen(We);
for (i=0; i <= n; zn = We[i++]) {
if (zn == ')') Wy[k++] = Pop(&S);
if ((zn == '+') || (zn == '*')) Push(zn, &S);
if ((zn >= '0') && (zn <= '9')) Wy[k++] = zn;
}
while (!Empty(S)) Wy[k++] = Pop(&S);
Wy[k] = '\0';
}

8.2. Kolejka (Queue)


Kolejka jest struktur, w ktrej element dodaje si (wstawia) na koniec kolejki (ogon),
za usuwa z pocztku (z gowy).
First-in First-out FIFO pierwszy wchodzi i pierwszy wychodzi.
Operacje interfejsu kolejki:
Init(Q)
inicjalizuje (oprnia) kolejk,
Empty(Q)
testuje czy obszar kolejki jest pusty,
Full(Q)
testuje czy obszar kolejki jest peny,
Enq(el, Q)
umieszcza el na kocu kolejki (w ogonie - Tail).
Deq(Q)
pobiera (i usuwa) element kolejki z gowy - Head.
2-ga implementacja kolejki
Tail wskazuje ostatnio wstawiony el.

Tail wskazuje na wolne pole


1

void Init(Stack *S)


{ *S = NULL; }

// void Init(NODES **S)

int Empty(Stack S)
{ return S == NULL; }

void Push(typS el, Stack *S)


{
Stack wrk = new(NODES);
if (wrk==NULL) puts("\n Stos pelny");
else { wrk->Data = el; wrk->top = *S;
*S=wrk;
}
}
typS Pop(Stack *S)
{
if (*S == NULL) { puts("\n Stos pusty"); return -1;}
else { Stack wrk = *S;
typS el = (*S)->Data;
*S = (*S)-> top;
delete wrk;
return el;
}
}

44

Head
Tail
Enq(33, Q), Enq(44, Q), Enq(55, Q)

Tail

Head
Enq(33, Q), Enq(44, Q)
1

44 55

6 33

Tail Head

struct NODES {
typS
Data;
NODES *top;
};
typedef NODES *Stack;

60

Algorytmy i Struktury Danych - wykad

1-sza implementacja kolejki

Algorytm Infix to Postfix Conversion wersja uproszczona


( tylko dla operatorw przemiennych * oraz + )
1. pobierz kolejno znaki od lewej do prawej,
2. jeeli operand to wylij go do Wyjcia,
3. jeeli lewy nawias ( to pomi go, / lub przelij na stos /
4. jeeli operator to umie go na STOSIE,
5. jeeli prawy nawias ) to pobierz operator ze STOSU i wylij do Wyjcia,
6. jeeli koniec zbioru We to kopiuj STOS do Wyjcia.
(a + b)*(d + e)
We STOS Wy
(
(
a
(
a
+
(+
b
(+
b
)
+
*
*
(
*(
d
*(
d
+
*(+
e
*(+
e
)
*
+
/0
*

Instytut Aparatw Elektrycznych


Algrm8
Dr J. Dokimuk

6 33

Tail Head

Kolejk mona implementowa jako tablic statyczn Q[1, n].


Zmienna head identyfikuje gow kolejki (pocztek).
Zmienna tail podaje nastpn woln pozycj do wstawienia, lub wskazuje na ostatnio
wstawiony obiekt.
Obiekty dostawia si na koniec kolejki za usuwa z pocztku pozostaj wolne miejsca.
Wolne miejsca w tablicy wykorzystuje si do dalszego wstawiania elementw, przez co koniec
kolejki moe znale si na pocztku tablicy.
Jest to ukad cyklicznej tablicy Q, implementowanej poprzez tablic jednowymiarow.
Cykliczno oznacza, e pozycja q1 jest bezporednim nastpnikiem qn.
Na starcie head = tail = -1 kolejka pusta.
Jeli tail + 1= head to kolejka jest pena.
Bd niedomiaru: prba usunicia elementu z kolejki pustej operacj Deq.
Bd przepenienia: prba wstawienia elementu do kolejki penej operacj Enq.
Full(Q) // tail wskazuje ostatnio wstawiony el.
if (head = tail + 1) or
(head=1 and (tail = length(Q)) return OK
else return !OK

Enq(el, Q)
// wstawienie do kolejki
if Full(Q) then Return(Przepenienie)
Q[tail]  el
if Q[tail] = length(Q) then tail  1
else tail  tail +1
Deq(Q)
// wyjcie z kolejki
wrk  Q[head]
if Q[head] = length(Q) then head  1
else head  head + 1
return wrk

head=3
struct
int
int
typ
};

QUEUE {
head,
tail;
vec[max];

(a)
1

18 33 54

tail = 7

Enq(10,Q), Enq(11,Q),
Enq(12,Q), Deq(Q)
2

12

18 33 54 10 11

tail=2 head = 4
(b)
1

Enq(13,Q)
2

12 13 2

18 33 54 10 11

tail=3 head =4

Instytut Aparatw Elektrycznych


Algrm8
Dr J. Dokimuk

61

Algorytmy i Struktury Danych - wykad

int main()
// P8.2a test kolejki
{
// program wpisuje do Q1 cig liczb losowych,
//
do Q cig kolejnych liczb integer
int i = 0;
Queue Q, Q1;
InitQ(&Q); InitQ(&Q1);

while (!Full(&Q1)) Enq(rand()%20, &Q1);


DisQ(Q1)

while (!Full(&Q)) Enq(10 + ++i, &Q);


Enq(111, &Q);
DisQht(Q); DisQ(Q);
Deq(&Q); Deq(&Q); Enq(21, &Q); Enq(22, &Q);
DisQht(Q);
DisQ(Q);

while (!Empty(&Q)) cout <<Deq(&Q)<<" ";


Deq(&Q);
return 0;
}
6 10 2 10 16 17 15 12
Kolejka pelna
Head=0 Tail=7
11 12 13 14 15 16 17 18
Head=2 Tail=1
13 14 15 16 17 18 21 22
13 14 15 16 17 18 21 22 Kolejka pusta

62

Algorytmy i Struktury Danych - wykad

8.3. Lista
// tail wskazuje ostatnio wstawiony el.

const int maxQ = 8;


// rozmiar kolejki
typedef int typ;
struct Queue {
int head, tail;
typ vec[maxQ];
};
void Init(Queue *Q)
{ Q -> head = Q -> tail = -1; }
int Full(Queue *Q)
{
return (Q->head==0 && Q->tail==maxQ-1 ||
Q->head == Q->tail+1);
}
int Empty(Queue *Q)
{ return (Q->head == -1); }
int Enq(typ el, Queue *Q)
{

Czsto maksymalny rozmiar struktury nie jest znany w trakcie jej projektowania.
Przy zmiennym zapotrzebowaniu programu na pami Operator new zwraca adres przydzielonego bloku.
mona stosowa dynamiczny przydzia pamici.
typData *newNode; newNode = new(typData);
Jzyk C++ udostpnia stosowne funkcje.
Przydzielon pami zwraca na stert operator delete.
Mechanizm dynamicznego przydziau pamici, umoliwia tworzenie wizanych struktur danych,
w ktrych nastpny element nie musi bezporedni przylega do poprzedniego.
Mamy niecig struktur danych, rn od tradycyjnych cigych struktur tablicowych.
Jest to istotne w procesie wyszukiwaniu i wstawianiu elementu do struktury.
Dowizanie jest dodatkow informacj przechowywan w kadym wle, wskazujc gdzie jest
przechowywany nastpny element. Wstawiajc nowy element do listy (gdziekolwiek w pamici),
naley zmieni warto dowizania, aby nowy element wskazywa na nastpny.
Lista z dowizaniem jest struktur, w ktrej elementy uoone s liniowo, wedug
porzdku okrelonego przez wskaniki dowizania a nie przez indeksy danych.
8.3.1. Lista jednokierunkowa (singly linked list)
Kady element listy stanowi struktur o dwch polach:
pole danych (Dane),
dowizanie (next) wskanik nastpnego elementu listy.
Ostatni element listy zawiera pusty wskanik NULL.

if (Full(Q)) { cout << "Kolejka pelna\n"; return -1 }

Head

if (Q -> tail==maxQ-1 || Q->tail==-1) {


Q->vec[0] = el;

Q->tail = 0;

if (Q->head==-1) Q -> head = 0;


}

else Q -> vec[++Q -> tail] = el;


return 0; }

typ Deq(Queue *Q)


{

typ wrk;
if (Empty(Q)) cout << "Kolejka pusta\n";

else {
wrk = Q->vec[Q->head];
if (Q -> head == Q -> tail) Init(Q);
else if (Q -> head==maxQ-1)
Q -> head = 0;
else Q -> head++;

}
return wrk;
}
//_____________________________________

void DisQ(Queue q)
{
if (Empty(&q)) cout<<"Kolejka pusta\n";

void DisQht(Queue q)
{
cout <<"Head="<<q.head<<" Tail="<< q.tail<< "\n";
}

Instytut Aparatw Elektrycznych


Algrm8
Dr J. Dokimuk

else {
for (int i=q.head; i != q.tail; i=(i+1) % maxQ)
cout <<q.vec[i]<<" ";
cout <<q.vec[i] << "\n";
}
}

next

s
dre

Dane
5

1-szy

next
Dane
12
poprzedni

next

NULL
Dane

Dane
2

biecy

ostatni

struct ListNode {
ListNode *next;
int numer;
float Data[1024];
};

Dostp (identyfikacja) do caej listy umoliwia


wskanik do jej pierwszego elementu L .
Elementy listy nie musz zajmowa przestrzeni
cigej i miejsce przydzielane jest w miar potrzeb.

R8.3

Przeszukiwanie listy zaczyna si od pocztku i przebiega kolejno po wszystkich elementach.


Aby znale element na licie naley i za wskanikiem w polu next.
Koniec listy sygnalizuje wskanik o wartoci NULL.
Przydatne jest pamitanie wskanika do elementu poprzedzajcego element biecy.
Mona uy np. zmiennej pomocniczej prior, ktrej pocztkowa warto wynosi NULL.
Wstawianie i usuwanie elementw listy wskazywanej przez wskanik L (Head).
Aby usun wze z listy naley zna: -wskanik do usuwanego wza (aby znale klucz),
-wskanik do wza poprzedzajcego wze usuwany.
W wle poprzedzajcym naley zmodyfikowa pole next aby nie wskazywao wza usunitego.
Jeeli usuwany element jest 1-szy na licie to wskanik prior = NULL.
Aby wstawi wze do listy naley:
-utworzy przestrze pamiciow np.: wrk = new(ListNode), gdzie wrk zwraca adres nowego wza.
-znale wze, za ktry wstawiamy nowy wze i zmieni jego pole next na warto wrk.
Nowy wze jest wstawiony gdy jego pole next zawiera warto pola next wza poprzedniego.
next

next

Dane
2

Dane
5

next

w1

w2

Del
12

nowe

next
Dane
22

w4
wn

nowe

next
Nowy
25

nowe

next

NULL

Dane
30

Dane
55

w5

ostatni

usuwanie wza w3
wrk = w2>next //adres w3
w2>next = wrk>next

delete wrk //operacja pomocnicza


adres
wn
R8.4
wrk adres w3
Wskanik next nowo wstawionego elementu musi wskazywa na wstawianie wn za w4
nastpny element (moe by NULL).
wn = new(ListNode)
Naley te zaktualizowa wskanik next poprzedniego elementu.
wn->next = w4->next
Element mona usun lub doda z/do listy w staym czasie.
w4->next = wn

Przykadowe Operacje na Licie


newList(L)
-return new list
emptyList(L)
-test if list is empty
head(L)
-return first element in list
DelFirst(L)
-return all but first element in list
AddBefore(e,L)
-add element to head/front of list
List = ( 5, 7, 4, 1, 3 )
head(List)
=5
DelFirst(List)
= ( 7, 4, 1, 3 )
head(DelFirst(list))
=7
DelFirst(DelFirst(List)) = (4, 1, 3)
AddBefore(0, List)
= ( 0, 5, 7, 4, 1, 3 )
head(newList()) = Error
DelFirst(AddBefore(3, newList())) = ( )

typedef int typData;


struct ListNode {
typData
Data;
ListNode *next;
};
typedef ListNode *List;
List newList( ) // initialize a new list
{ return ( NULL); }
Head
L
int emptyList(List L)
{ // test if list is empty
return (L == NULL);
}
ListNode *createNode(typData e)
{
ListNode *idn // idn points to the new node

idn = new(ListNode);
if (idn==NULL) { puts("Error memory"); exit(1); }
idn->Data = e;
Head
idn->next = NULL;
L
return idn;
}

Head

64

Algorytmy i Struktury Danych - wykad

Usuwanie elementu z pocztku listy


firstNode

Remove first element in list

Del
Old links

idn

New links

List DelFirstList(List L)
{ List idn
If (emptyList(L)) { puts("Empty List"); exit(-1); }
idn = L->next
// new head in idn
delete(L);
// release space
// return new head
return (idn);
}

Aby znale miejsce na wstawienia elementu lub jego usuniecie naley przejrze list.
Przegldanie listy zwraca adres wza lub NULL
List searchList(typData e, List L)
{ int OK = 0;
while (!emptyList(L)) && !OK) {
if (e==headList(L) OK = 1;
else L = pointNextNode(L);
}
if (OK) return L; else return NULL;
}

List pointNextNode(List L)
{
if (emptyList(L)) {
puts("Lista pusta"); exit(1);
}
return (L->next);
}

int main()
// List1
List readList(List L)
{
{
List L, r, t, f, prev;
typData e;
int i,n;
while(readElement(&e))
L = newList();
L = AddBeforeList(e, L);
puts("Podaj elementy listy: ");
return L;
L = readList(L);
}
printf("Lista ="); printList(L);
printf("Wartosc szukanego elementy: "); scanf("%d", &i);
f = searchList(i, L);
if (f) printf ("Znaleziono %d\n",headList(f)); else puts("Nie znaleziono");
printf("Ktory element usunac: "); scanf("%d",&i);
prev= searchList(i, L);
DelBehindNode(prev);
printf("Po usunieciu="); printList(L);
printf("Po ktorym elemencie co dodac: "); scanf("%d %d", &i, &n);
prev= searchList(i, L);
AddAfterNode(n, prev);
printf("Po dodaniu=");
printList(L);
return 0;
}

struct ListNode {
typData
Data;
ListNode *next;
ListNode(typData x, ListNode *p)
{ Data = x; next = p }
};
typedef ListNode *List;
List NewAdr = new ListNode(2.3, Adr);

int lengthList(List L)
{
int len =0;
while (! emptyList(L)) {
len = len + 1;
L = pointNextNode(L);
}
return len;
}

Po ktorym elemencie co dodac: 7 -77


Po dodaniu=(33 ,44 ,66 ,88 ,7 ,-77 ,5 ,3 ,1 )

Odwiedzanie wza: for (List w = L; w != NULL; w = w->next) visit(w->Dane);

Instytut Aparatw Elektrycznych


Algrm8
Dr J. Dokimuk

Ktory element usunac: 88


Po usunieciu=(33 ,44 ,66 ,88 ,7 ,5 ,3 ,1 )

Wze-atrapa (Head) czsto umieszczany jest na pocztku kadej listy.


Nie zawiera pola Dane, za pole next zawsze wskazuje na pierwszy, uyteczny wze listy.

63

Podaj elementy listy: 1 3 5 7 99 88 66 44 33


Lista =(33 ,44 ,66 ,88 ,99 ,7 ,5 ,3 ,1 )
Wartosc szukanego elementy: 66
Znaleziono 66

Algorytmy i Struktury Danych - wykad

R8_5d

Instytut Aparatw Elektrycznych


Algrm8
Dr J. Dokimuk

List NewAdr = new ListNode(2.3, Null);


Instrukcja zwraca wskanik do nowego wza, inicjalizujc
pole danych wartoci 2.3 za pole adresowe Null.

Konstruktor pozwala unikn bdw


zwizanych z niezainicjowanymi polami.
Bdy w przetwarzaniu list:
-odwoanie do niezdefiniowanego wskanika,
-uycie wskanika niewiadomie zmienionego.

Instytut Aparatw Elektrycznych


Algrm8
Dr J. Dokimuk

65

Algorytmy i Struktury Danych - wykad

8.3.2. Lista cykliczna


Lista jednokierunkowa uniemoliwia dotarcie do elementw poprzedzajcych element wybrany.
Lista cykliczna, umoliwia dostp z danego elementu do kadego innego.
W rozwizaniu tym pole next ostatniego elementu
wskazuje na pierwszy element listy.

Brak wyranie zaznaczonego 1-go


i ostatniego elementu.

next

next

next

next

Dane
5

Dane
12

Dane
44

Dane
48

Lidn

Wejcie do listy wymaga wskanika do dowolnego elementu, dostpnego na zewntrz (Lidn).


Warto Lidn = NULL zewntrznego wskanika wskazuje na list pust.
Przegldajc list naley zapewni rozpoznanie jej koca, gdy z braku wskanika NULL
powstanie ptla nieskoczona.
Kocem listy jest napotkanie wskanika, od ktrego rozpoczto przegldanie (Lidn).
W implementacji naley zwrci uwag na uycie ptli do zamiast while i niewykonywanie
adnych czynnoci, gdy lista jest pusta (konieczno testowania tego stanu).
Aby wstawi element do listy cyklicznej musi by znany wskanik do poprzedniego elementu.
Pozostae operacje wykonuje si podobne jak dla listy jednokierunkowej.
Wstawienie elementu na pocztek listy wymaga uaktualnienia wskanika do caej listy (Lidn).
Wstawiajc obiekt do pustej listy, tworzymy list z jednym rekordem, ktrego wskanik
next powinien wskazywa na niego samego.
Problem Josephusa
Niech n osb wybiera spord siebie przywdc, stosujc nastpujc strategi:
-wszyscy ustawiaj si w kole,
-stosujc m-sylabow wyliczank eliminuj za kadym razem m-t osob,
-ostatnia pozostaa osoba zostaje przywdc.
Problem: jak z gry wyznaczy, ktra osoba pozostanie w kole.
Modelem problemu Josephusa jest n wzowa lista cykliczna (kady wze zawiera cze
wskazujce na osob z prawej strony).
1. Najpierw tworzy si list jednoelementow (wze wskazuje sam na siebie).
2. Nastpnie wstawia si pozostae elementy czyli wzy (wstawianie nowego wza za wzem x).
3. Nastpuje odliczanie m 1 elementw od elementu wskazanego i usunicie m-go wza
(usunicie wza za wzem x).
Przypisujemy wzowi o numerze m-1 wskanik do wza stojcego za wzem m .
4. Odliczanie i usuwanie kontynuowane jest a pozostanie jeden wze (wskazuje sam na siebie).
typedef struct ListNode {
int
Data;
ListNode *next;
ListNode( int x, ListNode *p) { Data = x; next = p; }
} *CList;
int main ()
// P8_5 Problem Josephusa
{ int i, n = 9, m = 6;
CList First = new ListNode(1, First), x = First; // 1-szy wze
for (i = 2; i <= n; i++) x = (x->next = new ListNode(i, First));

while (x != x->next) {

// wyliczanie i usuwanie m-go


for (i=1; i < m; i++) x = x->next;
// wze m-1

cout << x->next->Data << ", ";


x->next = x->next->next; // wskanik z m+1 do wza m-1
}
cout << "Boss = "<< x->Data << endl;
return 0;
}

6, 3, 1, 9, 2, 5, 4, 8, Boss = 7

Instytut Aparatw Elektrycznych


Algrm8
Dr J. Dokimuk

66

Algorytmy i Struktury Danych - wykad

8.3.3. Lista dwukierunkowa (doubly linked list)


Lista dwukierunkowa umoliwia przegldanie w obu kierunkach i skada si z 3 pl.
Data, pole danych,
next, wskazuje adres do elementu nastpnego,
prev, wskazuje adres do elementu poprzedniego.
Jeeli a jest aktualnym kluczem to next[a] jest adresem elementu nastpnego,
za prev[a] poprzedniego.
Jeeli prev[a] = NULL to element a jest pierwszym na licie i stanowi gow danej listy L.
Jeeli next[a] = NULL to element a jest
ostatnim na licie L i stanowi jej ogon.
Zmienna wskanikowa FirstL wskazuje
na 1szy element listy L.
Jeeli FirstL = NULL to lista jest pusta.
Funkcja Szukaj() poszukuje pierwszego elementu o
wartoci el na licie L z wykorzystaniem algorytmu
liniowego przegldania. Zwraca wskanik do tego
elementu lub NULL jeeli elementu nie ma na licie.
Pesymistyczny czas szukania wynosi O(n).
Wstaw(el, L)
// na pocztek
next[el]  FirstL // wstaw adres poprzedniej gowy
if FirstL NULL then prev[FirstL]  el
FirstL  el // adres wza z kluczem el 
prev[el]  NULL //pole prev wza z kluczem el

Szukaj(el, L)
wrk  FirstL
while wrk NULL and key[wrk] el do
wrk  next[wrk]
return wrk

Funkcja Wstaw() docza element na pocztek listy.


Przed wstawieniem naley utworzy nowy wze
np. instrukcj new.
Wstaw dziaa w czasie O(1)

Funkcja Usun() usuwa element el z listy L, Usun(el, L)


przez modyfikowanie wartoci odpowiednich if prev[el] NULL then next[prev[el]]  next[el]
wskanikw. Wczeniej naley wykona
else FirstL  next[el]
funkcj Szukaj() aby wyznaczy i przekaza
if
next[el]

NULL
then prev[next[el]]  prev[el]
wskanika do usuwanego elementu.
Pesymistyczny czas usuwania elementu wynosi O(n) i determinowany jest czasem dziaania
procedury Szukaj.
Samo usuwanie realizowane jest w czasie O(1).
Usunicie wza z listy dwukierunkowej wymaga tylko wskanika do tego wza.
Wady: zwikszony rozmiar wza, podwojona liczby operacji na czach w kadym wle.
Wartownicy
Jeeli do listy dooymy dodatkowy wze WartL (bez pola Data) to mona wyeliminowa
operacje na zmiennej FirstL (wskazuje na pierwszy element listy).
Mamy cykliczn list dwukierunkow, w ktrej wze WartL znajduje si midzy gow a ogonem.
Pole next[WartL] wskazuje na gow
listy za pole prev[WartL] na ogon.
Lista pusta skada si tylko z wartownika i next[WartL] oraz prev[WartL] -wskazuj na NULL.
Wstaw(el, L)

Szukaj(el, L)

next[el]  next[WartL]
prev[next[WartL]]  el
next[WartL]  el
prev[el]  WartL

wrk  next[WartL]
while wrk WartL and key[wrk] el do
wrknext[wrk]
return wrk

Usun(el, L)
next[prev[el]]  next[el]
prev[next[el]]  prev[el]

Wartownik nie zmienia klasy zoonoci operacji na danych, lecz upraszcza warunki brzegowe.

Instytut Aparatw Elektrycznych


Algrm8
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

67

Instytut Aparatw Elektrycznych


Algrm8
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

68

8.3.4. Sortowanie listy jednokierunkowej


Sortowanie listy mona realizowa poprzez zamian:
-miejscami tylko zawartoci pl danych w wzach (jak w tablicach),
-wycznie czy w wzach.
Czasami wskaniki do wzw listy, przechowywane s w rnych czciach aplikacji.
Wzy mog by dostpne poprzez wskaniki spoza funkcji sortujcej.
Program powinien zmienia jedynie pola adresowe zapisane w wzach.
Nie powinien zmienia kluczy zapisanych w wzach gdy mogoby si okaza, e sigajc
do wza poprzez inne cze, trafimy na zmienion warto - niepodany skutek.

Sortowanie przez selekcj


(wstawianie nowego wza na pocztek listy)
Dane:
lista We z kluczami nieposortowanymi.
Wynik: lista Wy z kluczami posortowanymi.
Przegldaj list We aby znale element najwikszy spord tych, ktre jeszcze pozostay.
Pobierz go, usuwajc jednoczenie z listy We.
Wstaw ten element na pocztek listy Wy.
Operacje powysze skracaj list We o jeden wze i wyduaj list Wy o jeden wze.
Powtarzaj w/wym operacje do wyczerpania listy We i przeniesienia jej wzw do listy Wy.

Sortowanie przez wstawianie


(wstawianie nowego wza do wntrza listy)
Dane:
lista We z kluczami nieposortowanymi.
Wynik: lista Wy z kluczami posortowanymi.
Pobierz pierwszy wze listy We, pamitajc wskanik do niego w zmiennej t.
Znajd w licie Wy wze x, taki e x->next->Data > t->Data (lub x->next = NULL)
i wstaw t do tej listy za wzem x.
Operacje powysze skracaj list We o jeden wze i wyduaj list Wy o jeden wze.
Powtarzaj w/wym operacje do wyczerpania listy We i przeniesienia jej wzw do listy Wy.

Przegldaj list We tak aby zmienna


prev wskazywaa wze poprzedzajcy wze z wartoci najwiksz,
za zmienna max wskazywaa wze
z wartoci najwiksz.
Zmienna prev niezbdna jest do
usunicia wza wybranego.

Program SortLis1 definiuje dwie listy,


poprzez stworzenie wzw-Atrap,
inicjujc ich pola wartoci -1.
Dalej tworzy n-wzw listy We wypeniajc
je liczbami losowymi, poprzez konstruktor.
Cz sortujca:
1-sza ptla for pobiera kolejne pocztkowe wzy z listy We.
2-ga ptla for poszukuje w licie Wy
wartoci wikszej od aktualnie
pobranej z listy We.
Nastpnie realizowane jest wstawianie wza z listy We do listy Wy.
typedef struct ListNode {
int Data;
ListNode *next;
ListNode(int x, ListNode *t) { Data=x; next = t;}
} *List;
const int n = 11;

#include<iostream.h>
#include<stdlib.h>

void DispL(List L)
{
for (List w = L; w != NULL; w = w->next)
cout << w->Data <<" ";
cout << endl;
}

int main()
// SortLis1
{
ListNode We(-1, 0), Wy(-1, 0);
// wezly-Atrapy
List t = &We, x, u;
for (int i=0; i < n; i++) t = (t->next = new ListNode(rand() % 100, 0));
DispL(&We);

//---------------------------------------------------------------sortowanie
for (t = We.next; t != 0; t = u) {
u = t->next;
// nastpny wze z listy We czyli usunicie poprzedniego
for (x = &Wy; x->next != 0; x = x->next) if (x->next->Data > t->Data) break;
t->next = x->next; x->next = t;
// wstawianie zmiana adresw
}
DispL(&Wy);
return 0;
-1 46 30 82 90 56 17 95 15 48 26 4
}
-1 4 15 17 26 30 46 48 56 82 90 95

List MaxL(List L)
{ // zwraca adres wza poprzedzajcego wze max
typedef struct ListNode {
int max = L->Data; List prev;
int Data;
for (List x = L; x->next != 0; x = x->next)
ListNode *next;
if (x->next->Data > max)
ListNode(int x, ListNode *t)
{ max = x->next->Data; prev = x; }
return prev;
{ Data = x; next = t;}
}
}*List;
void DelNode(List prev)
void DisL(List);
{
void GenL(List, int);
List wrk;
void DelNode(List);
wrk = prev->next;
// wrk points to be deleted
List MaxL(List);
prev->next=wrk->next; // skip node to be deleted
const int n=11;
}
int main()
// SortLis2
void DisL(List L)
{
ListNode We(-1,NULL), Wy(-1,NULL); // wezly-Atrapy {
for (List w = L; w != NULL; w = w->next)
List in = &We, out = &Wy, prev, max, r;
cout << w->Data <<" "; cout << endl;
GenL(in, n);
}
DisL(&We);

while ( in->next) {
prev = MaxL(&We); max = prev->next;
DelNode(prev);
r = out->next;
out->next = max; max->next = r;
}
DisL(out);
return 0;
}

void GenL(List L, int n)


{
for (int i=0; i < n; i++)
L =(L->next = new ListNode(rand() % 100, 0));
}

-1 46 30 82 90 56 17 95 15 48 26 4
-1 4 15 17 26 30 46 48 56 82 90 95

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

69

Algorytmy i Struktury Danych wykad

Algorytmy i Struktury Danych wykad

70

Drzewo binarne drzewo uporzdkowane, w ktrym kady wze ma co najwyej dwch


synw, a kady syn jest opisany jako lewy lub prawy.

9. DRZEWA
Listy lub kolejki w niewielkim stopniu odzwierciedlaj
hierarchiczn struktur obiektu.
Uniemoliwia to ich liniowa i jednowymiarowa budowa.
Pokonanie tych ogranicze umoliwiaj struktury
zwane drzewami.

Drzewo binarne definiowane


rekurencyjnie to struktura zdefiniowana
na skoczonym zbiorze wzw, ktra
spenia zaoenia podane obok.

Drzewo skada si z wierzchokw (wzw), od ktrych odchodz krawdzie (gazie), zakoczone na dole limi.
Korze wze, ktry nie ma ojca (poprzednika), moe natomiast mie synw (nastpnikw).
Licie lub wzy kocowe wzy, ktre nie maj nastpnikw (synw).
Syn lub dzieci wzy znajdujce si bezporednio pod danym wzem.
Krawd linia, ktra czy dwa wierzchoki.
cieka jednoznacznie wyznaczony cig krawdzi, prowadzcy z korzenia do kadego wierzchoka.
Dugo cieki liczba krawdzi na ciece.
Poziom wza dugo cieki od korzenia do wza
Wysoko drzewa najwikszy poziom wzw w drzewie.
Wasno drzewa: dwa dowolne wzy moe czy dokadnie jedna cieka.
Drzewo uniwersalne ukorzenione, majce dowoln liczb synw, ulokowanych w dowolny sposb.
Drzewo uporzdkowane drzewo ukorzenione, w ktrym okrelona jest kolejno nastpnikw
kadego z wzw. Jeeli wze ma k nastpnikw to s to kolejno ponumerowane 1,2, .
Do kadego wza drzewa uporzdkowanego docza si jego synw w okrelonej kolejnoci.
Drzewo dokadnie wywaone jeeli dla kadego wza, liczba wzw w lewym i prawym
poddrzewie rni si co najwyej o 1.
Mdrzewo: kady wze posiada okrelon liczb
potomkw ( m), uporzdkowanych w
okrelony sposb.
Pene drzewo rzdu m wszystkie licie maj t sam
gboko a wszystkie wzy wewntrzne maj stopie m.
Liczba wzw wewntrznych o wysokoci h wynosi W w(m, h) =

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

mh 1
m 1

W w(3, 2) = 4

Niech drzewo ma wicej ni 2 nastpniki. Dla tego samego wza numerowane s one rnymi
liczbami cakowitymi. W drzewie brakuje itego nastpnika, jeeli nie ma nastpnika o etykiecie i.
Drzewo uporzdkowane moe by reprezentowane z wykorzystaniem list, zwizanych z wzami.
Lewe cze wza wskazuje na pierwszy wze listy jego synw (syna pierwszego z lewej).
Prawe cza wzw poprzez listy wskazuj na braci znajdujcych si po prawej stronie.

1.Nie zawiera adnych wzw.


2. Skada si z trzech rozcznych zbiorw wzw:
korzenia,
lewego drzewa binarnego,
prawego drzewa binarnego.

Pene drzewo binarne o wysokoci h ma 2 1 wzw wewntrznych.


Drzewo binarne zawierajce n wzw wewntrznych ma n+1 wzw zewntrznych.
Dla dowolnego drzewa binarnego, w ktrym wzy wewntrzne maj dokadnie po dwch
synw liczb lici n i liczb wzw wewntrznych k wie relacja: n = k + 1
Drzewo binarne zawierajce n wzw wewntrznych ma 2n czy, z ktrych
n-1 prowadzi do wzw wewntrznych, a n+1 do wzw zewntrznych.
Wysoko drzewa binarnego zawierajcego n wzw wewntrznych wynosi
co najmniej lg(n) a co najwyej (n-1).
Regularne drzewo binarne: kady z wzw ma stopie 2 lub jest liciem.

9.1. Implementacja drzew binarnych


Pozycje synw
Drzewa binarne mog by implementowane z wykorzystaniem
tradycyjnych tablic statycznych bd dynamicznych, jak te z uyciem ind Dane Lewy Prawy
dynamicznych struktur wizanych.
0
1
1
3
0 1
-1
1
2
2
Tablicowa implementacja wymaga przypisania kademu 1
3
-1
-1
2
8
wzowi struktury 3 polowej, zoonej z:
4
2
3
4
4
5
4
5
2
 pola danych,
8
6
5
-1
-1
4
6
 2 pl zawierajcych indeksy komrek, w ktrych
-1
5
5
6
umieszczono lewego i prawego syna.
6
9
-1
-1
6
R9.6
9
Korze tradycyjnie umieszcza si w komrce nr 0.

Dynamiczna implementacja drzewa binarnego wymaga zdefiniowania dla kadego wza:


-struktury skadajcej si z 3-ch pl,
-podania wskanika do korzenia.
struct TreeNode {
TreeNode *Left
typData Data
TreeNode *Right
};

Jeeli Left[W] = NULL to wze W nie


ma lewego syna.
Jeeli Right[W] = NULL to wze W nie
ma prawego syna.
RootD -wskanik do korzenia drzewa.
Drzewo puste: jeeli rootD = NULL .

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

Algorytmy i Struktury Danych wykad

71

9.2. Drzewa poszukiwa binarnych BST (Binary Search Trees)


Drzewo poszukiwa binarnych jest struktur drzewa binarnego, w ktrym klucze w wle
speniaj cile okrelone zalenoci.
Jeeli klucz wza k ma warto a to:
wszystkie wartoci przechowywane w lewym
poddrzewie s mniejsze od a,

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

72

Algorytmy i Struktury Danych wykad

9.2.1. Przechodzenie drzewa

Jest to proces odwiedzania kadego wza w drzewie tylko jeden raz.


Nie jest okrelona kolejno odwiedzania wzw.
Potencjalne moliwoci przejcia drzewa okrela liczba permutacji wzw.
Dla nwzowego drzewa, liczba moliwych drg wynosi n!.
Praktyczne zastosowanie znajduj dwie klasy przechodzenia: przechodzenie wszerz i w gb.

wszystkie wartoci przechowywane w prawym


poddrzewie s wiksze od a.
Niech w bdzie wzem drzewa BST, za pL i pR
jego lewym i prawym poddrzewem, wtedy
key[w] > key[pL] za key[w] < key[pR]

Wartoci kluczy w drzewie BST nie powinny si powtarza.


Zbir danych napywa w kolejnoci :
1

13

15

16

25

17

15

Naley utworzy drzewo BST.


Ten sam zbir wartoci mona przestawi za pomoc
wielu rnych drzew BST.
W wikszoci przypadkw pesymistyczny czas
wykonywania operacji na drzewach BST jest
proporcjonalny do ich wysokoci.
Naley dy do budowy niskich drzew.
W przykadzie (R9.10) drzewo (b) o wysokoci h =2 bdzie miao wiksz efektywno
analityczn ni drzewo (a) o wysokoci h = 5.
Wzy ze zdublowanymi kluczami nie musz ze sob ssiadowa w drzewie.
Wyszukiwanie kluczy w BST
Wyszukiwanie wza w drzewie BST o zadanym kluczu k mona zrealizowa, majc dany
wskanik do korzenia drzewa, poprzez funkcje rekurencyjne lub iteracyjne o czasie O(h).
SearchTree(wx, k)

SearchTreeIter(wx, k)

if wx = NULL or k = key[wx] then return wx

while wx NULL and k key[wx] do


if k<key[wz] then wx left[wx]
if k<key[wx] then return SearchTree(left[wx], k)
else wx right[wx]
else return SearchTree(right[wx], k)
return wx
Funkcja SearchTree zwraca wskanik do wza, zawierajcego poszukiwany klucz k lub warto
NULL, gdy takiego wze nie ma.
Proces poszukiwania rozpoczyna si od korzenia, schodzc stopniowo w d drzewa.
Jeeli w trakcie porwnywania klucza k z wartoci key[wx] okae si, e k < key[wx] to
dalsze poszukiwania realizowane s w lewym poddrzewie wza wx, gdy definicja drzewa
BST wyklucza moliwo wystpienia k w prawym.
Gdy pierwsze porwnanie daje relacj k>key[wx] to poszukuje si w prawym poddrzewie.
TreeNode SearchIter( TreeNode node, typData key)
Implementacja iteracyjna funkcji { while (node)
SearchTree jest czytelniejsza i
if (key == node ->key) return node;
zazwyczaj efektywniejsza.
else if (key < node ->key) node = node ->left;
else node = node ->right;
return NULL;
}

Przechodzenie wszerz (breadth-first traveral)


Odwiedzanie kadego wza, rozpoczyna si od korzenia, nastpnie przesuwa si w d na
kolejne poziomy, przegldajc je od lewej do prawej.
Breadth(TreeNode node)
{
15
if (node) {
Deq
Enq(node, Qt); //key[node]
10 25
while (!Empty(Qt) {
25 3 12
node = Deq(Qt);
Disp(key[node]);
20
35
3 12
Otrzymuje si cig: 15,10,
25, 3, 12, 20, 35, 1, 5,14, 30

12 20 35 1

Implementacja metody z wykorzystaniem kolejki


Po dojciu do wza na poziomie r jego synowe (na
poziomie r+1) umieszczani s na kocu kolejki i }
odwiedzany jest wze z pocztku kolejki.

if (left[node])
Enq(left[node], Qt);
if (right[node])
Enq(right[node], Qt);
}
}

Gwarantuje to, e synowie odwiedzeni zostan dopiero po przejciu wszystkich wzw z poziomu r.
W algorytmie Qt jest kolejk, przechowujc w polu danych adresy struktury typu drzewo.
Przechodzenie w gb (depth-first traversal) w celu odwiedzenia wszystkich wzw

Rozpoczynajc od korzenia przechodzi si maksymalnie w lewo (lub prawo),


nastpnie cofa si do najbliszego rozgazienia, potem jeden krok w prawo (lewo)
i znowu maksymalnie w lewo (prawo).
W zalenoci od tego, czy i ktre wzy zostan odwiedzone przed marszem w d czy te po
powrocie, istnieje 3! = 6 wariantw przechodzenia: vLR, LvR, LRv; vRL, RvL, RLv,
gdzie v odwiedzenie, L i R przejcie lewego lub prawego poddrzewa.
Praktycznie wykorzystuje si taktyk poruszania od lewej prawej nadajc standardowe nazwy.

inOrder LvR wze wizytowany jest po przejciu lewego poddrzewa a przed wejciem
do prawego.
preOrder vLR
wze wizytowany jest przed odwiedzeniem w obu poddrzewach.
postOrder LRv wze wizytowany jest po odwiedzeniu w obu poddrzewach.
Due znaczenie ma metoda InOrder, ktrej wywoanie InOrder(rootBST) wypisze
wszystkie elementy drzewa BST w porzdku rosncym.

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

73

Algorytmy i Struktury Danych wykad

W metodzie InOrder najpierw odwiedzane jest lewe poddrzewo biecego wza,


potem sam wze a na kocu prawe poddrzewo.

InOrder

15 7

(1)

R9.12a

L-v-R
13 5

(1)
2
(1)
1
(1)

Disp(5)

10

(2)

17 8
25 10

14 6
11 3

9 20

40 12
35 11

12 4

InOrder(node)

PreOrder(node)

PostOrder(node)

if node NULL then


InOrder(left[node])
Disp(key[node])
InOrder(right[node])

if node NULL then


Disp(key[node])
PreOrder(left[node])
PreOrder(right[node])

if node NULL then


PostOrder(left[node])
PostOrder(right[node])
Disp(key[node])

(1)
(2)

Nastpnik w drzewie BST


Nastpnik wza w:nastpny wze odwiedzany w porzdku inOrder.
Nastpnik mona wyznaczy nie wykonujc porwna kluczy.
Jeeli wszystkie klucze drzewa s rne to nastpnikiem(successor) wza w
jest wze o najmniejszym kluczu ze zbioru kluczy wikszych ni key[w].

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

74

Algorytmy i Struktury Danych wykad

9.2.2. Operacje na drzewie BST


Maksimum i minimum
Wze o najmniejszym kluczu mona znale idc od korzenia a do napotkania NULL wedug
wskanikw left, za wze o najwikszym kluczu wedug wskanikw right.
Jeeli wze wx nie ma lewego poddrzewa, to najmniejsza
warto w poddrzewie o korzeniu wx jest key[wx].
Jeeli wze wx nie ma prawego poddrzewa, to najwiksza
warto w poddrzewie o korzeniu wx jest key[wx].
MaximumTree(wx)
while right[wx] NULL do
wx right[wx]
return wx

MinimumTree(wx)
while left[wx] NULL do
wx left[wx]
return wx

Czas wykonania funkcji jest rzdu O(h), poniewa przegld nastpuje tylko w d drzewa.
Wstawianie

node key = a
Wstawianie elementu a polega na przekazaniu do stosownej

=
nw
node left = NULL
funkcji rekordu z nowym wzem nw o strukturze obok.

node right = NULL

Poszukiwanie miejsca do wstawienia rozpoczyna si od korzenia i przebiega wzdu cieek w


d drzewa, a do napotkania wza nie majcego odpowiedniego syna.
Jest to poszukiwane miejsce.

Ins(14) 15
10
3
5

10

25
13

20
14

R9.13

Ins(17) 15

35
30

25
13

20
17

35
30

Jeeli wze staje si prawym synem innego wza, to dziedziczy nastpnik po swoim nowym ojcu.
Jeeli wze staje si lewym synem innego wza, to jego nowy ojciec staje si jego nastpnikiem.
(a) Jeeli wza w ma prawe poddrzewo dla to nastpnikiem jest najbardziej na lewo
pooony wze w prawym poddrzewie (przykad nastpnik wza 15).
Nastpnik wza bez prawego syna znajduje si gdzie nad nim.
(b) Jeeli wze w nie ma prawego poddrzewa to nastpnikiem jest:
-najniszy przodek , ktrego lewy syn jest rwnie przodkiem wza w,

gdy wze w jest prawym synem.


Naley przej w gr drzewa, a do napotkania wza, ktry jest lewym synem
swego ojca (ojciec to nastpnik)
-ojciec wza w, gdy wze w jest jego lewym synem.
NastepnikBST(w)
if right[w] NULL then return Minimum(right[w])
y ojciec[w]
while y NULL and w = right[y] do
wy
y ojciec[y]
return y

// (a)

InsertTree(nw, BST)
// y, x wskaniki robocze
x root[BST]
while x NULL do
// wyszukiwanie
yx
if key[nw] < key[x] then x left[x] else x right[x]
y NULL

// --------------------------------------- operacja wstawiania


if y = NULL then root[BST] nw
else if key[nw] < key[y] then left[y] nw
else right[y] nw

W ptli while wskaniki x i y przesuwane s w d drzewa w lewo lub w prawo a do chwili gdy
napotkaj warto NULL.
Jest to miejsce, w ktre naley wstawi wskanik na nowy wze nw

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

75

Algorytmy i Struktury Danych wykad

Usuwanie
Moliwe s 3 przypadki usuwania wza uw
(1) jeeli wze uw nie ma syna to zostaje usunity i u jego ojca[uw] wstawiany jest wskanik
do uw rwny NULL,
(2) jeeli wze uw ma jednego syna to uw zostaje wycity przez uaktualnienie wskanikw
midzy jego ojcem a synem.

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

Algorytmy i Struktury Danych wykad

9.3. Rwnowaenie drzewa


Drzewa wyszukiwania binarnego nie daj gwarancji uzyskania drzewa
zrwnowaonego w przypadku dynamicznego dodawania i usuwania kluczy.
W kracowym przypadku moemy otrzyma drzewo pochylone, bdce w rzeczywistoci list
jednokierunkow. Ma to miejsce w przypadku, gdy klucze dodawane bd zgodnie z ich
kolejnoci w rosnco posortowanej sekwencji. W efekcie otrzymujemy szukanie sekwencyjne.
Jeeli klucze dodawane s w losowej kolejnoci, drzewo powinno by zblione do
struktury drzewa zrwnowaonego, zapewniajc efektywny redni czas przeszukiwania.

(3) jeeli uw ma dwch synw, to wyizolowany zostaje wze y, bdcy nastpnikiem uw,
nastpnie wze y zastpuje wze uw
Drzewo zrwnowaone: rnica wysokoci obu poddrzew kadego wza wynosi 0 lub 1.
Drzewo doskonale zrwnowaone:
0
drzewo zrwnowaone, w ktrym wszystkie licie znajduj si
+1
0
na jednym lub dwch poziomach.
9.3.1. Tablicowa metodyka rwnowaenia drzewa
Izolowany jest wze y = 70, bdcy nastpnikiem usuwanego wza 61.
Delete(uw, BST)

// dziaa w czasie O(h)

// -----------wyznaczenie wza poredniego y


if left[uw] = NULL or right[uw] = NULL then y uw else y Nastpnik(uw)
// do zmiennej x przypisuje si y lub NULL gdy y nie ma synw
if left[uw] NULL then x left[y] else x right[y]
if x NULL then ojciec[x] ojciec[y]
// operacja usuwania y
if ojciec[y] = NULL then root[BST] x
else if y = left[ojciec[y]] then left[ojciec[y]] x
else right[ojciec[y]] x

el
(3
5)

W procedurze Delete() wze poredni y staje si:


wzem usuwanym uw, gdy ma najwyej 1-go syna,
nastpnikiem uw, jeeli uw ma dwch synw.

// kopiowanie wszystkich pl y

if y wx then key[uw] key[y]

76

1. Umie napywajce dane w tablicy X[1, n].


2. Posortuj otrzyman tablic.
3. Wybierz jako korze rodkowy element tablicy X.
Powstaj dwie podtablice: X[1, k-1] oraz X[k+1, n].
4. Lewym synem korzenia jest rodek lewej podtablicy
Powstaj dwie kolejne lewe podtablice.
5. Prawy syn korzenia to rodek prawej podtablicy
Powstaj dwie kolejne prawe podtablice.
6. Powtarzaj czynnoci (3 5) dla nowych podtablic.
void Balance(int lo, int hi, int X[ ])
{
int k = (lo + hi )/2
// middle
if (lo <= h0) {
Insert(X[k], &node);
Balance(lo,k-1, X);
Balance(k+1, hi, X);
}
}

Jeeli dane napywaj sukcesywnie:


-ulokowa w roboczym drzewie niezrwnowaonym,
-przechodzc metod inOrder przenie je do tablicy (uporzdkowane),
-wywoa funkcj Balance() dla otrzymanej tablicy.

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

77

Algorytmy i Struktury Danych wykad

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

78

Algorytmy i Struktury Danych wykad

9.3.2. Algorytm DSW

Tworzenie drzewa zrwnowaonego - 2-gi etap

Operacja rotacji
Podstawow operacj przywracajc rwnowag w drzewach BST jest rotacja.
Rotacja polega na obrocie" wok krawdzi midzy wzami (O, S)  (S, O).

Przeksztacenie linii wzw w drzewo zrwnowaone realizuj operacje RotacjaLewa.


Lew rotacj (a) na wle O mona wykona tylko wtedy,
(a
a)
D
D (b
b)
gdy istnieje jego prawy syn S.
LeftRotate (D, O, S)
S
O
Jeeli O nie jest korzeniem drzewa (D NULL):
Ojciec wza Syn staje si Synem.
Lp1
Pp2

Praw rotacj na wle O mona wykona tylko wtedy, gdy istnieje jego lewy syn S.
Lew rotacj (b) na wle S mona wykona tylko wtedy, gdy istnieje jego prawy syn O.
Operacja RotateRight() zamienia konfiguracj wzw przez zmian wartoci wskanikw.
Dziadek

RightRotate(D, O, S)

Jeeli O nie jest korzeniem drzewa (D NULL):

Ojciec

Ojciec wza Syn staje si Synem.


1. prawe poddrzewo S staje si lewym poddrzewem
wza O;
2. wze O staje si prawym synem swego dotychczasowego lewego syna S;
3. Dziadek wza S(wnuk) staje si ojcem wnuka S

(a
a)

(b
b)
S

O
Lp2

Pp1

S Syn(wnuk)
Lp2

Pp2

Pp2 Pp1
Prawa Rotacja Syna wzgldem Ojca

Rotacja zachowuje porzdek inOrder kluczy.


Z konfiguracji po prawej stronie (b) mona przej do konfiguracji po lewej, stosujc RotateLeft().
Prostowanie drzewa - 1-szy etap
Pierwszym etapem algorytmu DSW jest przeksztacenie drzewa w lini.
Nastpuje to przez wykonanie RotacjiPrawej na wzach majcych lewych synw.

wrk
10

wrk

20
15

wrk

20

30
25

30

40

wrk

30

wrk

25

Kady przebieg skraca dugo linii o poow.


W pierwszym przebiegu wykonuje si n m rotacji.
W dalszych przebiegach rotacje wykonywane s o
gry do koca.

23

28
(a
a)

23

40
28

25
23

40
28

(b
b)

23
28

20
10

20
23

(c
c)

40
28

25
wrk

(d
d)

40

15

10

25

28

30

40
Zauwamy, e m = 2

20

15
20

20
15

23

25

25

28

28

30

30

30

(b
b)

40

(e
e)

40

n=9
m=7
1-szy przebieg

30

25
15

23

20
30

28

(ff)

40

10
40

23
15

3-ci przebieg

2-gi przebieg

floor (lg( n+1))

lg( n+1)
1 2
1 = n

Liczb rotacji okrela zaleno: n m +

lg( m ) 1

k =1

m
n+
2k

40

(c
c)

25

10
28

23

23

28

(e
e) 40

Niech drzewo ma n wzw.


Ptla while wykona si 2n-1 razy i wykona n -1 rotacji w najgorszym przypadku.
Zatem czas dziaanie 1-szej fazy wynosi O(n).

20

30

28

15

25

25
15

10

23

20
23

23

30

10

(a
a)

25

30

10

m = m/2;
LeftRotate(wza wzgldem jego Ojca);

(d
d)

25

while (m > 1)

15

20

20

20

Pp2
Lp1
Pp2 Pp2
Lewa Rotacja Syna wzgldem Ojca

1 jest liczb wzw w najbliszym penym drzewie.

Dokonujc ruch w d drzewa wykonywane s


LewaRotacja co 2-gi wze wzgldem jego ojca.

10

15

15

15

15

floor(lg(n+1))

5
10

10

10

10

Jeeli n jest liczb wzw to m = 2

Przeksztacanie(Root, n)
lg(n+1)
m=2
1
for 1 = 1 to n - m step 2 do LeftRotate;

Prostowanie(Root)
wrk = Root;
while (wrk NULL)
if wrk "ma lewego syna" RightRotate (tego syna wzgldem wrk);
else wrk nastpny wze, ktry by prawym synem wrk;
Uwaga: wykonanie Rotacji wymaga zachowania ojca wza wrk.

1. lewe poddrzewo S staje si prawym poddrzewem


wza O;
2. wze O staje si lewym synem swego dotychczasowego prawego syna S;
3. Dziadek wza S(wnuk) staje si ojcem wnuka S

lg( m ) 1

k =1

1
n
2k

czny koszt rwnowaenia drzewa algorytmem DSW jest klasy O(n).

dla duzych n

30
28
(g
g)

40

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

79

Algorytmy i Struktury Danych wykad

9.3.3. Drzewa AVL - Adelson Velskii, Landis (1962)


poddrzewa kadego wza rni si co najwyej o jeden.
Umoliwia lokalne rwnowaenie drzewa, jeli zmiany niezbdne po
wstawieniu lub usuniciu elementu dotycz tylko czci drzewa.
Wspczynnik wywaenia (liczby w wzach): rnica wysokoci lewego
i prawego poddrzewa. Wspczynniki powinny by rwne +1, 0 -1.

Gdy wspczynnik wywaenia w dowolnym wle AVL staje si


rny od (+1, 0 -1), to drzewo musi zosta zrwnowaone.
+1 8

drzewo AVL
-1

-1

Jeeli z powodu wstawienia wza, jedno z


poddrzew wza zwikszy wysoko o 1,
wtedy warunek rwnowagi moe zosta
naruszony. Jedna lub podwjna Rotacja
przywrci wze do rwnowagi.

18

+1
0

11

19
14

0
12

20

17

S 9 +2

6
7

18
15

19

22

16 20

12

18 0

18 +1
7

LewaRotacja (18)
wzgldem Ojca (9)

22

19 +1

15

16 20

12

19 +1
15

22

7 12

20

22

16

44

44

S PrawaRotacja (15)
18

6
2

15
12
11

LewaRotacja (15)
wzgldem Ojca (9)

wzgldem Ojca (18)

6
19

16 20

22

15
7

12
11

18
16

15 0
18 +1

9
6
19
20

12
7

11

16

19
20

inicjalizacja drzewa
testowanie czy drzewo puste
nowy wze drzewa
zwraca klucz wza drzewa
wstawia klucz do wza drzewa
zwraca lewe poddrzewo
zwraca prawe poddrzewo
wstawia lewe poddrzewo do nowego
wstawia prawe poddrzewo do nowego

22

22

Znale wze S, ktrego wspczynnik wywaenia sta si nieakceptowalny po wstawieniu


nowego wza do drzewa.
Jak? : idc w gr drzewa od miejsca wstawienia nowego wza, w kierunku korzenia i uaktualniajc wspczynniki wywaenia napotykanych wierzchokw.
Pierwszy wze, ktrego wspczynnik wywaenia zmieni si na 2, jest korzeniem
poddrzewa, ktrego rwnowag trzeba przywrci.
Dla doskonale zrwnowaonego drzewa binarnego h = lg(n+ 1).
W najgorszym przypadku wyszukiwanie w drzewie AVL wymaga 44% wicej porwna ni w
drzewie doskonaym. Eksperymenty pokazay, e rednia liczba porwna jest znacznie
lepsza ni wynikaoby to z najgorszego przypadku.
Dlatego z drzewa AVL mog by atrakcyjne w rnych implementacjach.

struct TreeNode {
TreeNode *left;
typData
Data;
TreeNode *right;
};
typedef TreeNode *Tree;

Boolean emptyTree(Tree T)
{ // return TRUE if empty,
return (T == NULL);
}

TreeNode *createTreeNode(typData e)
{
// return new tnode containing typData e
TreeNode *node;
node = new(TreeNode);
if (node == NULL) {
puts("Error in new"); exit(1);
}
node->left = NULL;
node->right = NULL;
node->data = e;
return node;
}
Element getData(Tree T)
{ // return data contained at current Tree node
if (emptyTree(T)) {
puts("empty Tree "); exit(1);
}
return T->data;
}

Wstawianiu wza do lewego poddrzewa prawego syna

+2

newTree()
emptyTree()
createTreeNode()
getData()
setData()
getLeft()
getRight()
setLeft()
setRight()

Tree newTree(Tree T)
{ // return new empty Tree T
return (T = NULL);
}

-1

Wstawienia wza do prawego poddrzewa prawego syna

+1 9

80

Algorytmy i Struktury Danych wykad

ANEX 9.1. Binary Tree Interface

Drzewo AVL to drzewo przeszukiwa binarnych, gdzie wysokoci lewego i prawego

Wysoko h drzewa AVL:


lg(n + 1) < h< 1.44 lg(n + 2) 0.328
co oznacza, e wyszukiwanie w najgorszym
przypadku jest klasy O(lg(n)).

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

Tree setData(typData e, Tree T)


{ // return Tree T with root data set to typData e
if (emptyTree(T)) { puts("empty Tree "); exit(1); }
T->data = e;
return T;
}

Tree getLeft(Tree T)
{
//return left child Tree of Tree T
if (emptyTree(t)) {
puts("empty Tree "); exit(1);
}
return T->left;
}
Tree getRight(Tree T)
{
// return reft child Tree of Tree T
if (emptyTree(t)) { puts("empty Tree ");exit(1); }
return T->right;
}
Tree setLeft(Tree newT, Tree T)
{ // set left child Tree of Tree T to Tree newT
T->left = newT;
return T;
}
Tree setRight(Tree newT, Tree T)
{ // set right child Tree of Tree T to Tree newT
T->right = newT;
return T;
}

Tree InsertTree(typData e, Tree T)


{
if (emptyTree(T)) return createTreeNode(e);
if (e < getData(T)) T = setLeft(InsertTree(e, getLeft(T)), T);
else if (e > getData(T)) T = setRight(InsertTree(e, getRight(T)),T);
return T;
}

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

Algorytmy i Struktury Danych wykad

81

Instytut Aparatw Elektrycznych


Algrm9A
Dr J. Dokimuk

Algorytmy i Struktury Danych wykad

82

ANEX 9.2.
...................

Struktura stosu podczas realizacji funkcji InOrder() [2]

int main()
// P8.4a
Tree
{
Tree root = NULL;
int liczba;
puts("Wprowadz wartosci:");
while(scanf("%d",&liczba))
root = InsertTree(liczba, root);
puts("breadthFirst"); breadthFirst(root);
puts("InOrder");

InOrder(root);

printf("\nElement do usuniecia: ");


fflush(stdin);
scanf("%d",&liczba);
deleteTree(liczba, root);
puts("Po usunieciu(InOrder)");
InOrder(root);
return 0;
}
Wprowadz wartosci:
11 32 45 65 67 654 1 2 3 q
breadthFirst
11 1 32 2 45 3 65 67 654
InOrder
1 2 3 11 32 45 65 67 654
Element do usuniecia: 11
Po usunieciu (InOrder)
1 2 3 32 45 65 67 654

void BreadthFirst(Tree T)
{
typeQueue Qt; // zmienna robocza-kolejka
InitQ(&Qt);
if (T) {
Enq(T, &Qt);
while (!EmptyQ(Qt)) {
T = Deq(&Qt);

NULL

printf("%3d",T->data);
if (T->left) Enq(T->left, &Qt);
if (T->right) Enq(T->right, &Qt);
}
} puts("");
}
void InOrder(Tree t)
{
if (! emptyTree(t)) {
InOrder(getLeft(t));
printf("%3d", getData(t));
InOrder(getRight(t));
}
}

Tree deleteTree(typData e, Tree t)


{
Tree wrk;
int newe;
if (EmptyT(t)) { puts( Brak drzewa); exit(); }
if (e == getData(t)) {
if (EmptyT(getLeft(t)) && EmptyT(getRight(t)))
{ wrk=t; delete wrk; t=newTree(t); }
else if(EmptyT(getLeft(t)) && !EmptyT(getRight(t))) { wrk=t; t=getRight(t); delete wrk; }
else if(EmptyT(getRight(t)) && !EmptyT(getLeft(t))) { wrk=t; t=getLeft(t); delete wrk; }
else { t = setRight(Successor(&newe, getRight(t)), t); t = setData(newe,t); }
}
else if (e < getData(t)) t = setLeft(deleteTree(e, getLeft(t)), t);
else t = setRight(deleteTree(e, getRight(t)), t);
return t;
}

NULL

<102>
<104>
NULL
1
1
1

1
1
4
<102> <102> <102> <102> <102>
<104>
4
4
4
4
4
4
4

4
4
20
<102> <102> <102> <102> <102> <102> <102> <102> <102>
<104>
15
15
15
15
15
15
15
15
15
15
15

15
<adr> <adr> <adr> <adr> <adr> <adr> <adr> <adr> <adr> <adr> <adr> <adr>
a
b
c
d
e
f
g
h
i
j
k
l

NULL

NULL

<102>
<104>
16
16
16

16
<102> <102> <102> <102>
20
20
20
20
<102> <102> <102> <102>
15
15
15
15
<adr> <adr> <adr> <adr>
m
n
o
p

L-v-R

InOrder
3 15
2 4
1 1

5 20
4 16

6 25

InOrder(typeTree node)
{
if (node) {
InOrder(node->left); <101>
Disp(node);
<102>
InOrder(node->right); <103>
}
<104>
}

(a) Pierwsze woanie wkada na stos adres powrotu do InOrder() <adr> oraz warto key=15.
Drzewo nie jest puste, nastpuje realizacja instrukcji if.
Funkcja InOrder() wywoywana jest dla node.key=4.
(b) Na stos trafia adres powrotu <102> oraz warto key=4.
Wze nie jest pusty, zatem InOrder() wywoywana jest dla lewego syna node.key=1.
(c) Na stos trafia adres powrotu <102> oraz warto zmiennej key=1.
InOrder() jest wywoywana dla lewego syna node.key=1.
(d) Na stos trafia adres<102> oraz warto NULL.
NULL natychmiast koczy wywoanie InOrder().
Automatycznie zdejmowany jest ze stosu rekord wywoania.
(e) System odtwarza warto zmiennej node.key=1.
Wykonuje instrukcj pod adresem<102>, co odpowiada wydrukowaniu wartoci 1.
Warto node.key=1 i adres <102> pozostaj na stosie, gdy przetwarzanie wza nie zostao
zakoczone.
(f) Rozpoczyna si wykonywanie instrukcji po adresem <103>, co odpowiada wywoaniu funkcji
InOrder() dla prawego syna node.key=1.
Zatem na stos trafia adres <104> oraz bieca warto node=NULL.
NULL koczy dziaanie InOrder(), usuwajc rekord wywoania.
(g) System odtwarza poprzedni warto zmiennej node.key=1 i wykonuje instrukcj <104>.
Jest to koniec wywoania InOrder().
(h) System odtwarza ze stosu warto node.key=4.
Wykonuje instrukcj <102>, co daje wydruk wartoci 4.
Nastpnie wywouje InOrder() dla prawego syna wza warto NULL.

Instytut Aparatw Elektrycznych


Algrm9B
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

83

Instytut Aparatw Elektrycznych


Algrm9B
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

9.3. Kopiec (Heap)

Usuwanie elementu z kopca

Kopiec jest drzewem binarnym o nastpujcych wasnociach:


1. warto klucza w kadym wle jest nie mniejsza ni klucze u jego potomkach,
2. wszystkie licie drzewa le na co najwyej dwch ssiednich poziomach,
3. licie na ostatnim poziomie szczelnie wypeniaj lew cz drzewa.

Usuwanie elementu z kopca, to usunicie elementu o maksymalnym kluczu.


Usuwany jest korze i w jego miejsce wstawiany jest ostatni li.

Kopiec tworzony jest na bazie penego drzewa binarnego, std jego wysoko jest rzdu O(lg(n)).
Kopiec moe reprezentowa tablica K[1n], w ktrej kady wze drzewa
odpowiada elementowi tablicy o parametrach:
K[i] K[ 2i ] oraz K[i] K[ 2i + 1], gdzie 0 i < n/2.
Korzeniem drzewa jest K[1].
dla 60

Grne ograniczenie indeksu i wynika z definicji (2).

dla 58

dla 54

K[i] 60 58 54 52 51 53 47 46 48 45
1
2
3
4
5
6
7
8
9 10
i
Atrybutami tablicy K reprezentujcej kopiec s:
n = length(K)
dugo tablicy
nK
liczba elementw kopca w tablicy K.
aden element tablicy K[1n], wystpujcy po indeksie nK nie jest elementem kopca K.
Dla itego wza kopca mona obliczy indeksy ojca oraz lewego i prawego syna.
Ojciec(i)

Lewy(i)

return i/2

return 2i

i/2

2i + 1

Prawy(i)

return 2i + 1

2i + 2

2i

2i+1

Wstawianie elementu do kopca


dodaj nowy li z kluczem w do drzewa,

Wze ma wasno kopca jeeli dla


kadego wza i, ktry nie jest korzeniem
zachodzi: K[Ojciec(i)] K[Potomek(i)].

InsertHeap(w, K)
nK  nK + 1 // miejsce na wstawienie
przesuwaj klucz w w gr po ciece, tak dugo K[nK]  w
dopki nie dojdzie do korzenia lub nie natrafi na i  nK
ojca o wartoci nie mniejszej od w,
while i > 1 and w > K[Ojciec(i)] do
przechodzc przez kolejne wzy, zamie nowy
Swap(K[i] ,K[Ojciec(i)])
wze z jego ojcem.
i  Ojciec(i)

84

Powoduje to destrukcj kopca.


W celu przywrcenia wasnoci kopca naley dokona przestawie idc od korzenia w d.
DeleteHeap(K)
if nK < 1 then Kopiec pusty
max  K[1]
K[1]  K[nK]
nK  nK - 1
HeapDown(1, K)
return max
Przywracanie wasnoci kopca

Po operacji na kopcu czsto w jakim wle warto klucza ojca jest mniejsza od
kluczy jego synw.
Drzewo binarne utracio wasno kopca.
Funkcja HeapDown przywraca j, powodujc spynicie klucza K[i] w d kopca,
tak aby poddrzewo zaczepione w wle i stao si kopcem.
HeapDown(i, K)
l  Left(i);
r  Right(i)
if l nk and K[l] > K[i] then Max  l else Max  i
if r nk and K[r] > K[Max] then Max  r
if Max i then Swap(K[i], K[Max] )
HeapDown(Max, K)
W kadym kroku dziaania HeapDown() poszukiwana jest warto maksymalna pord
dzieci wza i.
Indeks wartoci maksymalnej pamitany jest w zmiennej Max.
Jeeli K[i] jest najwiksze to jest OK.
Jeeli nie to zamienia si K[i] z K[Max].
Teraz bada si czy poddrzewo doczepione do K[Max] spenia wasno kopca.
Jeeli nie to funkcja HeapDown() wykonywana jest rekurencyjnie na tym poddrzewie.

HeapDown() dziaa poprawnie przy zaoeniu, e poddrzewa podczepione do synw


wza i s kopcami.
Czas dziaania dla kopca nwzowego T(n) T(2n/3) + O(1) = O(lg(n)),
gdzie O(1) czas poprawiania w wle i relacji miedzy ojcem(i) i jego synami oraz
rekurencyjne wywoywania.

Instytut Aparatw Elektrycznych


Algrm9B
Dr J. Dokimuk

85

Algorytmy i Struktury Danych - wykad

Budowanie kopca
Tablic K[1n] niebdc kopcem mona przeksztaci BuildH(K)
n  length(K);
w kopiec, wykorzystujc funkcj HeapDown.
nK  n
Podstaw dziaania jest fakt, e wszystkie elementy
for
i  n/2 downto 1 do
podtablicy K[(n/2 + 1) n] s limi drzewa, a tym
HeapDown(i, K)
samym 1elementowym kopcem.
Funkcja BuildH, przechodzc przez wzy wewntrzne, wywouje funkcj HeapDown.
Zachodzi wstpujce (bottom-up) przeksztacenie tablicy K.
21 22 23 24 25 26 27 28 29 33
1

9 10

Instytut Aparatw Elektrycznych


Algrm9B
Dr J. Dokimuk

86

Algorytmy i Struktury Danych - wykad

Sortowanie przez kopcowanie


Istota algorytmu to sukcesywna zamiana wierzchoka kopca (warto maksymalna) z jego
ostatnim elementem i przywracanie wasnoci kopca nowemu drzewu binarnemu.
Pierwszy krok to budowa kopca na tablicy wejciowej K[1n].
HeapSort(K)
Aktualny wierzchoek kopca zamieniany jest z ostatni pozycja BuildH(K)
tablicy K, oraz zmniejszony zostaje rozmiaru kopca (nk = nk - 1).
for i  length(K) downto 2 do
Zmniejszonej tablicy K[1nk-1] przywraca si wasno kopca
Swap(K[1], K[i] )
poprzez wykonanie HeapDown(1, K).
nK  nK 1
Proces powtarza si a dojdzie si do kopca o rozmiarze 2,
HeapDown(1, K)
wwczas tablica K zawiera posortowane klucze.

Sortowanie przez kopcowanie


10 9 8 7 6
(a1)
(a) 1
Swap(10,1)
HeapDown(a1)
BuildH
10
1 1
2

8
5

6
9

10

9
4

9
2 10

8
5

nK=nK-1

9
2 10

Swap(8,1)

(c)
1 8
7

(c1)

1 1 1

HeapDown(c1)

Swap(2,9) (b1) HeapDown(b1)


2 1
2

3
(b)
1 9

3
6

9 10 nK=nK-1

Wywoanie HeapDown realizowane jest w czasie O(lg(n)). Liczba wywoa moe sign O(n).
Pesymistyczny czas budowania kopca mona szacowa na O(nlg(n)).

(d)
7

Kopiec nelementowy zawiera co najwyej n/2h+1 wzw o wysokoci h


Czas dziaania funkcji HeapDown, wywoanej w wle o wysokoci h wynosi O(h).
Asymptotyczny czas dziaania funkcji BuildH jest klasy O(n).

8 9

10

10

10

Swap(7,4) (d1)
HeapDown(d1)
1 4

1
9

3
8

1
9

10

5
5

nK=nK-1

Poz. a1, b1, po wykonaniu przestawienia korzenia z ostatnim elementem;


poz. b, c, ... po wykonaniu HeapDown
6 4 5

(e)
1 6

7
8
3

nK=nK-1

1
9

10

10

Sortowanie przez kopcowanie wykonywane jest w czasie T(n) = O(nlg(n))


Wynika to z czasu budowania kopca na dowolnej tablicy, wynoszcy T(n)=O(n) oraz wykonywanych n 1 wywoa funkcji HeapDown(), ktrej czas jednego wykonania wynosi O(lg(n)).
Dokadna analiza pozwala na stwierdzenie, e sortowanie przez kopcowanie wymaga mniej ni
2nlg(n) porwna.

Sortowanie przez kopcowanie jest niestabilne.


Zalety sortowania przez kopcowanie:
gwarantuje posortowanie nelementw w miejscu,
czas sortowania nie zaley od struktury danych wejciowych (brak najgorszego przypadku),
efektywne w przypadku wybierania k najwikszych elementw w zbiorze nelementowym.
(dla maych k czas wyboru jest proporcjonalny do n).

Instytut Aparatw Elektrycznych


Algrm9B
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

87

9.3.1. Przykady zastosowania kopca


Jednym z istotnych i najbardziej naturalnych zastosowa kopca s kolejki priorytetowe.
Kolejka priorytetowa to struktura danych, suc do przechowywania zbioru R rekordw.
Kady rekord ma przyporzdkowany klucz, identyfikujcy go jednoznacznie.
Kolejka priorytetowa (ATD) realizuje funkcje:
struct Record {
int key; // priorytet
Umieszcza elementy o podanym priorytecie, w kolejce
typP AdresProgramu;
Wyszukuje w kolejce elementy o najwyszym priorytecie
bla.....bla bla
Usuwa elementy o najwyszym priorytecie.
Znajduje zastosowanie w sytuacji, gdy rejestrowane s sukcesywnie }
napywajce zgoszenia, za do obsugi konieczne jest wybranie
zgoszenia o najwyszym priorytecie, niezalenie od kolejnoci, w jakiej napywaj.
Po obsudze zgoszenia jest ono usuwane z kolejki.
Obsuga elementw o rwnym priorytecie moe by dowolna lub chronologiczna.
Funkcje udostpniane przez kolejk priorytetow:
Insert(xr, R) wstawia nowy rekord do zbioru R
Max(R) zwraca rekord (adres) o najwikszym kluczu.
DelMax(R) zwraca rekord o najwikszym kluczy a
nastpnie usuwa go ze zbioru R.
Empty(R) zwraca zero gdy kolejka jest pusta
void HeapUp(int k, typData X[ ])
{
// k -start od tego elementu kopca
while (k > 0 && X[k] > X[(k-1)/2]) {
swap(&X[k], &X[(k-1)/2]);
k = (k - 1)/2;
}
}

typData *PQ = new typData[maxN];


n = 0;
int Empty()
{ return n == 0; }
void Insert(typData el)
{
PQ[n++] = el;
HeapUp(n-1, PQ);
}
typData GetMax()
{
swap(PQ[0], PQ[n-1]);
HeapDown(0, n-1, PQ);
return PQ[--n] ;
}

Praca wsadowa

Ustalanie kolejnoci wykonywania napywajcych programw w systemie wspbienym.


Kolejka priorytetowa przechowuje zadania do wykonania oraz ich priorytety wzgldem siebie.
Zakoczenie realizacji zadania powoduje pobranie przez funkcje DelMax nowego zadania o
najwyszym priorytecie z pord oczekujcych na realizacje.
Napywajce zadania mog by doczone do kolejki w dowolnej chwili przez funkcj Insert.
Symulowanie zdarze

Kolejka zawiera zdarzenia do symulacji, ktrych kluczem jest czas ich wystpowania.
Zdarzenia symulowane s w kolejnoci ich zajcia.
Wygodnie jest operowa funkcj DelMin, ktra wykorzystywana
jest przez stosowny program do wybierania zdarze do symulacji, w
poczeniu z funkcj Min.
Mamy wic do czynienia z kolejk o odwrconym liniowym porzdku.
Jeeli zachodz nowe zdarzenia to s dodawane do kolejki przez
funkcj Insert.

Instytut Aparatw Elektrycznych


Algrm10
Dr J. Dokimuk

88

Algorytmy i Struktury Danych - wykad

Algorytmy i Struktury Danych - wykad

89

10.1. Szukanie w Bdrzewie

10. BDRZEWA
Realizuj obsug duych struktur danych, dziaajcych na pamiciach masowych (dyskowych).

Jednostk danych na dysku jest blok (cluster), ktrego lokalizacja na


powierzchni moe by dowolna.
Aby zapisa/odczyta wze (cluster) naley zlokalizowa go na
powierzchni nonika, przed wykonaniem operacji.
Czas dostpu do wza mona okreli zalenoci:
czas szukania + bezwadno obrotowa + czas transferu
Algorytmy odsugujce drzewa BST, wydajnie dziaajce w
PAO komputera, s absolutnie nieprzydatne w kontekcie
wsppracy z nonikami zewntrznymi.
Bdrzewa redukuj obcienia wynikajce z czasu dostpu do danych w strukturach pamici
masowej gdy pozwalaj na dopasowanie wza do rozmiaru bloku danych.
Liczba kluczy w wle jest zmienna i zaley od rozmiaru klucza, jak te od struktury danych.
W wle mog by przechowywane tylko klucze lub te dodatkowo cae rekordy danych.
Rozmiar bloku zaley od systemu operacyjnego ( 16kB, 32kB, ).
W jednym wle mona przechowywa duo informacji.
Rozmiar wza w Bdrzewie zazwyczaj okrela wielko
bloku danych na dysku, co z kolei limituje liczb synw
przypitych do jednego wza, ktra waha si midzy
50 ) 1000 (zaley od rozmiaru wza).
Z reguy korze Bdrzewa jest stale trzymany w PAO.
Wwczas znalezienie dowolnego klucza(wza) w drzewie o wysokoci h wymaga maksimum
h odwoa do operacji dyskowych; liczba odwoa jest niezalena od rzdu m drzewa.
Mechanizm przetwarzania informacji w strukturach Bdrzewa:
 Jeeli poszukiwany obiekt x znajduje si w PAO to odwoanie do niego nastpuje w
sposb tradycyjny, w przeciwnym razie zostaje wczytany blok z dysku do PAO.
 Jeeli bloki znajdujce si w PAO s aktualnie niepotrzebne, zostan automatycznie
usunite, po uprzednim zapisaniu na dysk, jeeli dokonywane byy zmiany w rekordach.
Bdrzewo rzdu m to drzewo poszukiwa binarnych rzdu m o wasnociach:
1. korze ma co najmniej dwa poddrzewa o ile nie jest liciem;
2. wze rny od korzenia zawiera p-1 kluczy i p wskanikw do poddrzew (psynw) lub
maksimum 2p-1 kluczy i 2p wskanikw do poddrzew (2psynw), gdzie m/2 p m;
11 22 33 44 55
3. klucze w kadym wle s uporzdkowane rosnco;
4. licie s na jednym poziomie, zawieraj p-1 kluczy lub maksimum 2p-1. p1 p2 p3 p4 p5 p6
B-drzewo jest zawsze przynajmniej w poowie zapenione i z natury swojej niskie.
N +1
Wysoko Bdrzewa spenia zaleno: h log
+ 1 , N cakowita liczba kluczy.
p 2
Dla dostatecznie duego rzdu m, wysoko Bdrzewa jest maa, przy duej liczbie kluczy.
Liczba operacji dyskowych dla Bdrzewa jest proporcjonalna do jego wysokoci.

Struktura wza Bdrzewa:

Instytut Aparatw Elektrycznych


Algrm10
Dr J. Dokimuk

B-drzewo root[B] 60
rzdu m=5

n liczba kluczy w wle,


key<60
leaf zm. logiczna o wartoci TRUE
jeeli wze jest liciem,
m -1 kluczy 1020
K[m-1] tablica zawierajca klucze,
P[m] tablica zawierajca wskaniki
k<10 10<k<20
do wzw (wze wewntrzny).
2 4
121416

Kady wze moe


generowa m potomkw

W kadym wle naley dokona wyboru poddrzewa, w ktrym bdzie kontynuowane poszukiwanie.
jeeli nx jest aktualn liczb kluczy w wle x,
to nx + 1 oznacza liczb moliwych poddrzew w wle.

W drzewie BST wybiera si tylko jedno poddrzewo z dwch moliwych.


DANE: -wskanik do wza x
-poszukiwany klucz key, znajdujcy si w poddrzewie o korzeniu w x.
WYNIK: para (y, i) zawierajca wze y oraz indeks i speniajcy: keyi[y] = key lub NULL.
Rozpoczcie poszukiwania w Bdrzewie powoduje wywoanie SearchB(root(B), key)
SearchB(x, key)
i1
while i n[x] and key > keyi[x] do i  i + 1
if i n[x] and key = keyi(x) then return (x, i)
if leaf[x] then return NULL else DiskRead(ci[x])
return SearchB(ci[x]), key)
Ptla while poszukuje w wle x najmniejszej wartoci i dla ktrej key keyi[x].
Jeeli nie znajdzie to i = n[x] + 1.
Nastpnie sprawdza si czy znaleziono poszukiwany klucz.
Jeeli znaleziono to funkcja zwraca parametry wza,
w przeciwnym razie nastpuje negatywne zakoczenie (gdy wze jest liciem) lub pobranie z
dysku odpowiedniego syna i ponowne rekurencyjne szukanie.
Czas dostpu do stron dyskowych wynosi: O(h) = O(logp(N)).
Czas przegldania wza wynosi O(p), gdy n[x] < 2p.
czny czas pracy procesora wynosi O(ph) = O(plogp(N)) .

10.2. Tworzenie pustego Bdrzewa


Utworzy pusty wzekorze przy pomocy funkcji CreatB(B).
Funkcja InitNode() przydziela pojedyncz stron na dysku.
Funkcj Insert(key) wypenia stopniowo drzewo.

CreateB(B)

x  InitNode()
leaf(x)  TRUE
n[x]  0
Funkcja CreateB dziaa w czasie O(1) zarwno dla operacji DiskWrite(x)
dyskowych jak i CPU.
root[B]  x

key>60
7080

6163

Metodyka poszukiwania klucza w Bdrzewie jest podobna jak w BST (z definicji Bdrzewa).

7274

Instytut Aparatw Elektrycznych


Algrm10
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

90

10.3. Wstawianie klucza do Bdrzewa


10.3.1. Li nie jest peny
Wstawianie klucza do Bdrzewa rozpoczyna
si od umieszczenia go w liciu.
10.3.2. Li peny
Tworzony jest nowy li a klucze dzielone s po poowie midzy stary i nowy.
a) Nowy klucz wstawiany jest do waciwej poowy rozbitego licia.
b) Ostatni klucz starego licia przenoszony zostaje do ojca (jeeli jest wolne miejsce).

Podobny proces moe dotyczy wza wewntrznego, zwikszajc liczb wzw o jeden.

Instytut Aparatw Elektrycznych


Algrm10
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

91

10.4. Usuwanie klucza z Bdrzewa


Usuwajc naley zwraca uwag, aby kady wze by wypeniony co najmniej w poowie.

Implikuje to czasami konieczno sklejania wzw.


10.4.1. Usuwanie klucza z licia
10.4.1a Usunicie klucza bez niedoboru
Jeeli po usuniciu klucza k, li jest wypeniony co najmniej w poowie,
to naley jedynie przesun w lewo klucze wiksze ni k .

10.4.1b Usunicie klucza powoduje niedobr (niedobr to mniej ni poowa wypenienia)


Jeeli li ma lewego lub prawego Brata o wypenieniu wikszym ni poowa, to nastpuje:
a) przeniesienie klucza od Ojca do licia,
b) od Brata do Ojca.

10.3.3. Ojciec jest peny


Proces podziau wza kontynuowany jest a do korzenia.
Jeeli w korzeniu nie ma miejsca to jest on rozbijany i tworzony jest nowy korze.

10.4.1c Usunicie klucza w liciu powoduje niedobr, a liczba kluczy u jego Braci jest nie
wiksza ni poowa moliwoci to:
li i Brat s sklejane (
Brat ulega zniszczeniu) .
rozdzielajcy je klucz u Ojca jest przesuwany do licia.
Jeeli teraz u Ojca wystpi niedobr to jest on taktowany jak li i czynno
powtarza si a do usunicie niedoboru poprzez scalanie.

Nastpuje dodanie dwch nowych wzw do Bdrzewa oraz wzrost jego wysokoci.

Instytut Aparatw Elektrycznych


Algrm10
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

92

10.4.2. Usuwanie klucza z wza wewntrznego

Moe implikowa konieczno przebudowy drzewa.


Usuwany klucz zastpuje si nastpnikiem lub poprzednikiem (musi znajdowa si w liciu).
Nastpnik/Poprzednik usuwany jest z licia zgodnie ze wczeniejsz procedur.

Instytut Aparatw Elektrycznych


Algrm10
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

Mechanizm rozbicia penego wza y o 2p - 1 kluczach na dwa wzy p - 1 kluczach.

Rozbicie nastpuje wzgldem klucza rodkowego keyp[y], ktry zostaje


przeniesiony do Ojca wza y.
Jeeli y nie ma ojca, tworzony jest nowy ojcieckorze.
Funkcja SplitB() realizuje proces rozbicia.

W przypadku usuwania klucza z wza wewntrznego, zachodzi czasami potrzeba rekonstrukcja


caego drzewa, idca w gr drzewa, i realizowana jak dla usuwania klucza z licia (10.4.1b c).

x niepeny wze bdcy Ojcem,


i wskanik itego syna wza x,
y wze dzielony, peny syn wza x (y = ci[x]).
y = ci[x]  y jest i-tym dzieckiem wza x.
SplitB(x, i, y)
// Podzia wza Bdrzewa
z  InitNode()
leaf[z]  leaf[y]
n[z]  p 1
// wze z przejmuje p-1 najwiekszych kluczy od y
for j  1 to p 1 do keyj[z]  keyj+p[y]
// wze z przejmuje p synw od wza y
if not leaf[y] then for j  1 to p do cj[z]  cj+k[y]
n[y] p 1

// aktualizacja licznika synw wza y

for j  n[x] + 1 downto i+1 do cj+1[x]  cj[x]


ci+1[x]  z
for j  n[x] downto i do
keyi[x]  keyp[y]

keyj+1[x]  keyj[x]

// wze z zostaje synem, klucz rodkowy z wza y przeniesiony zosta do wza-ojca x


n[x]  n[x] + 1 //aktualizacja licznika kluczy wza x
Czsto w Bdrzewach, wikszo kluczy znajduje si w liciach a tym samym usuwanie
realizowane jest w jednym przebiegu od korzenia do licia, bez powracania w gr drzewa.

// zapis na dysku zmodyfkowanych stron


WriteDisk(y); WriteDisk(z); WriteDisk(x)

Usuwanie wymaga O(h) operacji dyskowych oraz O(ph) = O(plogp(N)) czasu procesora.
Bdrzewo jest wypenione, co najmniej w 50%, za prawie nigdy w 100% pojemnoci.
redni poziom wypenienia przy losowych wstawieniach i usuniciach wynosi ok. 70%.

93

ANEX 10.1. ROZBICIE WZA w B-drzewie

Czas dziaania procedury SplitB jest rzdu O(p) i determinowany jest dziaaniem 1-szej ptli for.

Instytut Aparatw Elektrycznych


Algrm11
Dr J. Dokimuk

89

Algorytmy i Struktury Danych wykad

Instytut Aparatw Elektrycznych


Algrm11
Dr J. Dokimuk

90

Algorytmy i Struktury Danych wykad

Cykl: droga zaczynajca si i koczca na tym samym wierzchoku.

11. GRAFY
Graf definiuj wierzchoki V (vertices) i krawdzie E (edges), przy czym cieka midzy
dwoma wierzchokami nie musi by jednoznaczna, za sposb rysowania jest nieistotny.
Graf G = (V, E) skada si ze skoczonego zbioru wierzchokw oraz zbioru krawdzi.
Kad krawd E stanowi para wierzchokw, zatem E jest zbiorem par (u, v),
za (u),(v) stanowi elementy zbioru V.
Do oznaczania krawdzi E mona uywa zapisu (u, v) lub <u, v>.
Mwimy, e wierzchoek v jest ssiedni (adjacent) do wierzchoka u.
Krawd (u, v) jest incydentna (incident) wzgldem wierzchokw u i v, czyli
krawd czca dwa wierzchoki.

R11.2
Cykl w grafie skierowanym tworzy cieka, jeeli v0 = vk (a)
cykle
(b)
oraz graf zawiera co najmniej jedn krawd.
(c)
1
2
2
1
1
Cykl jest prosty, jeeli v1, v2,, vk s rne.
Ptla stanowi cykl o dugoci 1.
Cykl w grafie nieskierowanym tworzy cieka jeeli v0 = vk
4
3
4
3
4
oraz v1, v2,, vk s rne i k 2.
Spjny graf skierowany: kade dwa wierzchoki osigalne s jeden z drugiego (R11.2b).
Graf acykliczny: graf nie zawierajcy cykli.
Acykliczny graf skierowany(directed acyclic graph -DAG)-nie posiada cyklu skierowanego.

Graf skierowany(digraph): kada krawd jest uporzdkowan par wierzchokw.


Krawd <u, v> jest wychodzca z wierzchoka u i wchodzca do wierzchokw v.
Ptla wasna to krawd czce wierzchoek z samym sob.
Graf nieskierowany: kada krawd jest nieuporzdkowan par wierzchokw.
Nie mog wystpi ptle, kada krawd zawiera dwa rne wierzchoki.
Krawdzie incydentne z wierzchokiem 33 : <33, 31> oraz <33, 52>.

Spjny graf nieskierowany: kada para wierzchokw poczona jest ciek (R11.3a).
Kady wierzchoek dostpny jest z innego.

Peny graf nieskierowany: kada para wierzchokw poczona jest krawdzi.

Graf skierowany [a] ma parametry:

Graf nieskierowany [c] ma parametry:


V = {31, 33, 52, 35, 58, 8}
E = {(31,35), (31,33), (33,52), (52,35), (35,58), (35,8)}.
Stopie (degree) wierzchoka w gafie nieskierowanym: liczba krawdzi incydentnych do niego.
Stopie wierzchoka w gafie skierowanym: suma jego stopni wejciowych i wyjciowych.
stopie wejciowy/wyjciowy wierzchoka: liczba krawdzi wchodzcych/wychodzcych.
2

Graf rzadki: dla ktrego |V| >> |E| niewielka liczba krawdzi
Graf gsty: gdy |E| jest bliskie |V|2
wikszo par wzw poczona jest krawdzi
Graf regularny: kady wierzchoek ma taki sam stopie.
Graf planarny: tak przedstawiony na paszczynie, e adne dwie krawdzie nie przecinaj si.
k-graf: graf w ktrym stopie wierzchoka nie moe by wikszy ni k.
Niezmiennik grafu: cig liczb, zaleny tylko od struktury grafu a nie od sposobu jego etykietowania (np. liczba wierzchokw, liczba krawdzi).
Liczba chromatyczna grafu: najmniejsza liczba kolorw potrzebna do kolorowania wierzchokw
grafu tak, by adne dwa przylege wierzchoki nie byy tego samego koloru.
cieka dugoci k z wierzchoka u do wierzchoka ur jest cigiem wierzchokw <v0, v1,, vk>
takich, e u = v0, ur = vk oraz (vi-1, vi) E dla i = 1, 2,, k.
Dugo cieki to liczba krawdzi cieki.
r

Osigalny wze: u jest osigalny z u po ciece p, jeeli istnieje cieka p z u do u .


cieka prosta: jeeli wszystkie jej wierzchoki s rne.
Podcieka cieki p jest cigiem kolejnych wierzchokw <vi, vi+1,, vj> dla 0 i j k.
cieki bezporednie (direct paths) : { <1,2> <1,3> <2,3> <3,4> <5,1> }
cieki porednie (indirect):

<1,4> przez 3 lub przez 2 i 3


<2,4> przez 3
<5,2> przez 1
<5,3> przez 1
<5,4> przez 1 i 3 lub 1,2 i 3.

(b)

7
3

Multigraf: graf zawierajcy zdublowane krawdzie, zwane take wielokrotnymi.

Cykl w grafie nieskierowanym, ktry przechodzi


przez kady wierzchoek dokadnie raz.
Algorytm znajdujcy cykl Hamiltona w grafie jest zoony
czasowo, gdy nie istnieje rozwizanie problemu w czasie
wielomianowym.

Cykl Eulera - problem mostw krlewieckich


Przez Krlewiec przepywa rzeka, w rozwidleniu ktrej znajduje si wyspa.
Na rzece znajduje si 7 mostw. Szwajcarski matematyk L. Euler udowodni,
e nie jest moliwe przebycie wszystkich mostw dokadnie raz, a to z
powodu nieparzystej liczby wej na mosty.
Cykl Eulera: cykl, ktry zawiera kad krawd dokadnie raz.
Droga w cyklu Eulera moe przechodzi przez ten sam wze wielokrotnie.
Warunek istnienia cyklu Eulera:
-graf jest spjny (istnieje droga czca kad par wierzchokw).
-dla nieskierowanego liczba wychodzcych krawdzi z
kadego wierzchoka musi by parzysta.
-dla skierowanego do kadego wierzchoka musi wchodzi
i wychodzi tyle samo krawdzi.

Cyklu Eulera w grafie mona wyznaczy w czasie


liniowym do E.
Graf de Bruijna
Graf de Bruijna rzdu n posiada 2n wierzchokw.
Liczba krawdzi wynika z metodyki:
krawd czca wierzchoek i z wierzchokami (2i) mod 2n
oraz wierzchokami (2i + 1) mod 2n, dla kadego i.
Graf stosowany w problemach wykorzystujcych przesuwanie rejestru o
sta dugo. Przesuwanie wszystkich bitw o jedn pozycj w lewo,
usuwajc bit skrajny lewy, i przypisujc nowemu bitowi pojawiajcemu si
na prawej pozycji warto 0 lub 1.

6
7

Cykl Hamiltona

V = { 1, 7, 10, 11, 13, 18 }


E = { <11,13>, <13,18>, <18,1>, <1,7>, <7,1>, <7,7>,
<7,10>, <10,11>, <10,18> }.

(a)

R11.
3

Instytut Aparatw Elektrycznych


Algrm11
Dr J. Dokimuk

91

Algorytmy i Struktury Danych wykad

11.1. Implementacja Grafu


1. Macierzy ssiedztwa: macierz kwadratowa o wymiarze okrelonym liczb wierzchokw V*V.
Element macierzy przyjmuje warto 1 jeeli istnieje krawd od wierzchoka w
kolumnie do wierzchokw wierszu, w przeciwnym razie warto 0.
Zoono pamiciowa O(V2).
2. List ssiedztwa: przechowywane s listy ssiadw kadego wierzchoka, jako zwyke listy
wizane, z uyciem tablic, bd acuchw tekstowych.
Lista ssiedztwa jest tablic list, po jednej dla kadego wierzchoka.
0
1
2
3
4
5

0
0
0
0
0
1

1
0
0
0
0
0

0
1
0
0
0
0

1
0
1
0
0
0

0
0
0
1
0
1

0
0
0
0
1
1

0
1
2
3
4
5

92

Generowanie grafw losowych


Modele grafw losowych:
Wsplnymi danymi wejciowymi jest V liczba wierzchokw.
G(V, p) : -p prawdopodobiestwo krawdziowe, okrelone dla kadej krawdzi;
okrela prawdopodobiestwo, e dana krawd znajdzie si w grafie
G(V, k) : -ze zbioru wszystkich moliwych krawdzi s losowane kolejne krawdzie,
z jednakowym prawdopodobiestwem.
G(V, f) : - f oznacza maksymalny (nie przekraczalny) stopie wierzchoka.

0
1
0
1
0
0

1
0
1
1
1
0

0
1
0
0
0
0

1
1
0
0
0
1

0
1
0
0
0
1

0
0
0
1
1
0

Dla gafu nieskierowanego macierz ssiedztwa jest symetryczna wzgldem przektnej.


Dla grafu nieskierowanego G2 suma dugoci wszystkich list ssiedztwa wynosi 2|E|, poniewa
wierzchoek u wystpuje na licie ssiedztwa v i odwrotnie.
Dla grafu nieskierowanego kada krawd (u, v) reprezentowana jest dwukrotnie:
- przez wierzchoek v na licie Lista(u),
- przez wierzchoek u na licie Lista(v).
Implementacj grafu w postaci lisy ssiedztwa zaleca si dla grafw rzadkich.
Macierz ssiedztwa udostpnia informacj o poczeniu midzy dwoma wierzchokami w staym czasie.
Reprezentacja listowa przetwarza wszystkie krawdzie grafu w czasie proporcjonalnym do N + E.
Macierz incydencji
Tablica o rozmiarach E*V, skadajca si z E wierszy i V kolumn.
Jeli krawd wychodzi z danego wierzchoka w odpowiedniej kolumnie wstawiamy -1,
jeli do niego wchodzi to wstawiamy +1,
jeli wierzchoek nie naley do krawdzi wstawiamy 0,
0
1
2
3
4
jeli jest to ptla wasna wstawiamy 2.
0-1 -1 1
0 0 0
0-3 -1 0
0 1 0
0-5 1
0 0 0 0
1-2 0
-1 1 0 0
2-3 0
0 -1 1 0
3-4 0
0 0 -1 1
4-5 0
0 0 0 -1
5-4 0
0 0 0 1
5-5 0
0 0 0 0

Algorytmy i Struktury Danych wykad

Generowanie grafw obejmuje szereg czynnoci:


wybr odpowiedniego generatora.

Dla grafu skierowanego G1 suma dugoci wszystkich list ssiedztwa wynosi |E|, gdy
krawd (u, v) jest reprezentowana przez wystpienia v w tablicy zawierajcej |N| list.
0: 1,3
1: 0,2,3,4
2: 1
3: 0,1,5
4: 1,5
5: 3,4

Instytut Aparatw Elektrycznych


Algrm11
Dr J. Dokimuk

0
0
-1
0
0
0
1
-1
2

wygenerowany graf jest weryfikowany, czy spenia zaoenia wybranego modelu, grafy
ktre ich nie speniaj s odrzucane.
grafy speniajce zaoenia modelu sprawdza si dodatkowo czy s rne, tzn. czy nie
ma wrd nich grafw izomorficznych.

Graf izomorficzny: Dwa grafy G1(V1, E1) i G2(V2, E2) s izomorficzne, jeeli mona przenumerowa wierzchoki grafu G1 tak, aby stay si wierzchokami grafu G2,
zachowujc odpowiednie krawdzie w G1 i G2.
Przykad implementacji tablicowej
#define MAXN 10
struct Graph {
int TabG[MAXN][MAXN];
};
Graph NewG(Graph g);
Graph JoinG(Graph g, int a, int b);
Graph RemoveG(Graph g, int a, int b);
int AdjacentG(Graph g, int a, int b);
Graph newG(Graph g)
{
// Initialise and return graph g
int x, y;
for(x=0; x < MAXN; x++)
for(y=0; y < MAXN; y++)
g.TabG[x][y] = 0;
return g;
}

Graph JoinG(Graph g, int a, int b)


{ // add edge between nodes a and b
g.TabG[a][b] = 1;
return g;
}
Graph RemoveG(Graph g, int a, int b)
{ // remove edge between nodes a and b
g.TabG[a][b] = 0;
return g;
}
int AdjacentG(Graph g, int a, int b)
{ // test if edge exists between nodes a and b
return g.TabG[a][b];
}

Instytut Aparatw Elektrycznych


Algrm11
Dr J. Dokimuk

93

Algorytmy i Struktury Danych wykad

11.2. Przeszukiwanie wszerz BFS (Breadth First Search)


Wyrnia si wierzchoek pocztkowy zwany rdem.
Nastpnie bada si systematyczne krawdzie grafu w celu
odwiedzenia kadego wierzchoka, ktry jest osigalny ze rda.
Wierzchoki w odlegoci k od rda odwiedzane s przed
wierzchokami w odlegoci k+1.
Najpierw dociera si do wszystkich wierzchokw lecych o jedn
krawd od wierzchoka rdowego, nastpnie do wszystkich
wierzchokw odlegych od niego o dwie krawdzie i tak dalej.
Jeeli w trakcie przeszukiwania grafu pojawi si wze, z ktrego wychodzi wicej ni jedna
krawd, wwczas wybiera si jedn z nich, a pozostae zostawia si na pniej.
Krawdzie do pniejszego odwiedzania pamitane s dziki uyciu kolejki.
Obliczane s odlegoci od rda do wszystkich osigalnych wierzchokw.
Algorytm BFS tworzy drzewo przeszukiwania wszerz o korzeniu w rdle,
zawierajce wszystkie osigalne wierzchoki.
Dla kadego wierzchoka v osigalnego ze rda (S), cieka w drzewie
BFS od S do v odpowiada najkrtszej ciece od S do v w grafie G.

Niech Graf bdzie reprezentowany przez listy ssiedztwa pamitane w tablicy G[u].
Tablica G umoliwia dostp do wszystkich
wierzchokw ssiadujcych z u.
Na pocztku wszystkie wierzchoki s biae,
potem zmieniaj kolor na szary lub czarny.
Szary: wierzchoek odwiedzony, ktrego lista ssiedztwa
nie zostaa w caoci przejrzana.
W kolejce Q, pamitane s kolorowane na szaro,
odwiedzone wierzchoki.
Czarny: wierzchoek, ktrego lista ssiedztwa zostaa w caoci odwiedzona.
Jeeli wierzchoek u jest czarny, to wierzchoek v jest albo szary albo czarny.
Wierzchoki szare mog mie biaych ssiadw, tworz granic midzy odwiedzanymi i nieodwiedzanymi.
W kolejce umieszcza si rdo S.
Z kolejki pobiera si wierzchoek S, odwiedza si go,
i umieszcza w kolejce wierzchoki znajdujce si na jego licie ssiedztwa czyli: e, a.
Z kolejki pobiera si wierzchoek e, odwiedza si go, i umieszcza w kolejce wierzchoki z jego
listy ssiedztwa czyli: b, f (wierzchoek s nie jest pobierany, gdy by ju odwiedzony).
Z kolejki pobiera si wierzchoek a, odwiedza si go, i umieszcza w kolejce wierzchoki z jego
listy ssiedztwa czyli: d.
itd...

Instytut Aparatw Elektrycznych


Algrm11
Dr J. Dokimuk

94

Algorytmy i Struktury Danych wykad

D[u] -odlegoci (liczba krawdzi) wierzchoka u od rda S


C[u] -kolor wierzchoka.
P[u] -zawiera poprzednika (ojca) wierzchoka u; drzewo BFS.
Jeeli u nie ma poprzednika to P[u] = NULL.
Gwna ptla algorytmu BFS while wykonywana jest
tak dugo jak istniej szare wierzchoki.
1. Na pocztku pobierany jest szary wierzchoek u z kolejki Q.
2. W ptli for analizowany jest kady wierzchoek v z listy
ssiedztwa u.
2a. Jeeli v jest biay to nie by odwiedzany, zostaje odwiedzony i pokolorowany na szaro za D[v] = D[u] + 1.
2b. Wierzchoek u jest pamitany jako ojciec wierzchoka v
(w wektorze P), sam v jest umieszczany w kolejce Q.
Uwaga: wierzchoek v wstawiany jest do kolejki raz, gdy jest
jednoczenie kolorowany, za ciao instrukcji if wykonywane jest tylko dla biaych wierzchokw.
3. Po zbadaniu wszystkich wierzchokw z listy ssiedztwa u,
sam u jest usuwany z kolejki i kolorowany na czarno.
Uwaga: wierzchoek z pocztku kolejki jest wierzchokiem u,
ktrego lista ssiedztwa jest wanie przegldana.

BFS(G, s) // Breadth First Search


for u G do
// inicjalizacja
C[u] BIAY
D[u]0
P[u] NULL
C[s]Szary;
// [1]
P[s] NULL; // korze nie ma Ojca
Q{s}
//inicjalizacja kolejki

while (!Empty(Q)) do
u head[Q] // pobieranie
for v G[u] do
if C[v] = BIAY then
C[v] Szary
D[v]D[u] + 1
P[v] u
Enq(Q, v)
Deq(Q); C[u] Czarny

Wynikiem dziaania algorytmu BFS jest drzewo, ktre w stadium


pocztkowym skada si z korzenia (wierzchoek rdowy).
Drzewo jest rozbudowywane w trakcie przechodzenia grafu.
Wchodzc od wierzchoka u, w licie ssiedztwa szukany
jest nie odwiedzony (biay) wierzchoek v; wierzchoek ten
i krawd (u, v) dodawane s do drzewa.
Wektor P reprezentuje drzewo BFS, w ktrym kady wierzchoek
wskazuje na swojego poprzednika (z wyjtkiem korzenia).
s
kolejka Q
e a
Zawarte w nim informacje pozwalaj na znalezienie najkrtszej cieki
a b f
z wierzchoka rdowego s do docelowego v wg:
b f d
cieka z s do P(v) + krawd (P(v), v).
f d c
v
s
e a b f d c g
u s e a b
f d c g
d c g
0 1 1 D[e] De Da Db Df
P(v) null s s e e a b f
D(u)
c g
+1
+1 +1 +1 +1
c  P[c]  P[P[c]]  P[P[P[c]]]
g
0 1 1 2
2 2 3 3
c b  e

s
MinPathG(s, v)
Czas dziaania BFS
if P[v] = NULL then
Wierzchoki kolorowane s na BIAO tylko w trakcie inicjalizacji,
Print(" brak scieki s-v ")
ktra kosztuje O(V). Kady wierzchoek wstawiany jest do else if v = s then Print(s)
kolejki i wyjmowany co najwyej raz (instrukcja if ).
else MinPathG(s, P[v])
Operacje wstawiania do kolejki i usuwania s klasy O(1).
Print (v)
czny czas wykonywania operacji na kolejce wynosi O(V).
Lista ssiedztwa kadego wierzchoka przegldana jest co najwyej raz, gdy przegldana jest
tylko wtedy, gdy wierzchoek zostanie usunity z kolejki. Sumaryczny czas przegldania list
ssiedztwa wynosi O(E).
czny czas dziaania procedury BFS wynosi O(V + E).
Najkrtsze cieki czce kad par wzw grafu

Q=0

Naley wykona algorytm BFS dla kadego wierzchoka grafu.

R11.9

u
a: d,s
s: e,a
b: c,f,e
c: b,g
d: a
e: b,f,s
f: g,b,e
g: f,c

Dla kadego wierzchoka naley pamita dugoci cieek i reprezentacj drzewa.

Instytut Aparatw Elektrycznych


Algrm11
Dr J. Dokimuk

95

Algorytmy i Struktury Danych wykad

11.3. Przeszukiwanie w gb DFS (Depth First Search)


Wybieramy dowolny wierzchoek u, z ktrego przechodzi si do wierzchoka v.
Bada si rekurencyjnie wszystkich nie zbadanych ssiadw wierzchoka v.
Po zbadaniu ssiadw v, powraca si do wierzchoka, z ktrego v zosta odwiedzony (u).
Kontynuowane jest przeszukiwanie z wierzchoka startowego u we wszystkich kierunkach .
Jeeli wierzchoek v osigany jest po raz pierwszy z u to (u, v) wstawiamy do drzewa Tree.
W przeciwnym razie (u, v) wstawiana jest do zbioru krawdzi powrotnych.

Wierzchoek nie odwiedzony staje si nowym rdem i proces powtarza si.


Drzewo rozpinajce

u1

u4 (3)

u1
(1)

u5

u2
u2 (1)
u6

u3 (2)

(2)

u3

u5

(3)

u4

u6

Lista
u1: u2,u3,u4,u5,u6
u2: u3,u4,u1
u3: u1,u2
u4: u2,u1
u5: u6,u1
u6: u5,u1

Startujemy oznaczajc wszystkie wierzchoki jako nowe.

Wykonujemy VisitDFS1(u1) i z Listy wybieramy v = u2.


Wierzchoek u2 jest nowy, dodajemy (u1, u2) do Tree.
Wywoujemy VisitDFS1(u2) i z Listy wybieramy v = u3.
Wierzchoek u3 jest nowy, dodajemy (u2, u3) do Tree.
Wywoujemy VisitDFS1(u3) i z Listy wybieramy v = u3.
Wierzchoek u1 i u2 by odwiedzony (stary), zatem powrt.

DFS1(G)
Tree NULL
for u V do u nowy
for u V do
if u = nowy then
VisitDFS1(u)
VisitDFS1(u)
u stary
for v Listy[u] do
if v = nowy then
Tree (u, v)
VisitDFS1(v)

Powrt do VisitDFS1(u2), v = u4 i krawd (u2, u4) dodawana jest do Tree.


Powrt do VisitDFS1(u1) i poszukiwanie rozpoczyna w nowym kierunku v = u5.
Do pamitania wzw, ktre maj zosta odwiedzone algorytm rekurencyjny wykorzystuje stos programu.
Krawd powrotna: krawd grafu nie zawarta w lesie DFS, mog jedynie prowadzi od
wierzchoka do jednego z przodkw w jego drzewie DFS. Ptla traktowana jest jak krawd powrotna.

Kolejno przeszukiwania wierzchokw


zaley nie tylko od samego grafu ale
take od kolejnoci umieszczenia
ssiadw na listach ssiedztwa.

Podgraf poprzednikw nazywany jest lasem przeszukiwa w gb, zoonym z jednego lub
kilku drzew przeszukiwa w gb, gdy przeszukiwanie moe by wykonywane z kilku rde
Dla grafu skierowanego na wierzchoku u wybieramy tylko krawdzie skierowane od u. Po wyczerpaniu tych krawdzi,
powracamy do u mimo, e mog istnie inne krawdzie skierowane do v, ktre nie s jeszcze przeszukane.

Instytut Aparatw Elektrycznych


Algrm11
Dr J. Dokimuk

96

Algorytmy i Struktury Danych wykad

Algorytm kolorujcy wierzchoki na: -Biao w stanie pocztkowym;


-Szaro, gdy s odwiedzane po raz pierwszy;
-Czarn
Czarno
Czarno gdy lista ssiedztwa zostanie cakowicie zbadana.
Daje to gwarantuj, e kady wierzchoek bdzie nalea do dokadnie jednego drzewa DFS.
Funkcja DFS2(G) w pierwszej ptli for koloruje wierzchoki DFS2(G)
for u V do
na Biao oraz inicjuje zmienne.
Druga ptla for bada kady wierzchoek i w przypadku
C[u] Biay
wykrycia Biaego odwiedza go funkcj VisitDFS2(u).
T[u] NULL
Wywoanie funkcji VisitDFS2(u) nadaje wierzchokowi u krok 0
(nieprzetworzony) statut korzenia w nowym drzewie w lesie for u V do
przeszukiwa w gb (wierzchoek u staje si nowym rdem).
if C[u] = Bialy then VisitDFS2(u)
Funkcja VisitDFS2(u) w ptli for bada kady
wierzchoek v ssiadujcy z u; jeeli jest
Biay to zostaje odwiedzony rekurencyjnie.
Po zbadaniu kadej krawdzi wychodzcej
z u, sam u jest kolorowany na Czarno.
W wektorze F[u] zapisywany jest czas
przetworzenia wierzchoka u.

Zmienna krok jest globaln zmienn cakowit.

VisitDFS2(u)
C[u] Szary
D[u] krok krok + 1
for v Listy[u] do // badanie z listy ssiadw u
if C[v] = Biay then P[v] u
VisitDFS2(v)
C[u] Czarny
F[u] krok krok + 1

P[v] pamita poprzednika wierzchoka nie odwiedzonego v, nalecego do listy ssiedztwa odwiedzonego u.
Podgraf poprzednikw: GP = ( N, (T(v), v) )
G(u) Lista
a: b, d
b: c
c: d
d: b
e: f, c
f: f
b c d f
v
P(v) a b c e
u=a u=b u=c
u1=e

Etykiety czasowe -dodatkowe informacje udostpniane przez algorytm DFS:


D[u] -numer kroku oblicze od momentu gdy u zosta odwiedzony po raz pierwszy.
F[u] -numer kroku zakoczenia badania listy ssiedztwa wierzchoka u ( u na czarno).
Oznaczenia wewntrz wierzchokw: czas odwiedzenia/czas przetworzenia
Czasy odwiedzania i przetworzenia maj struktur nawiasow w przeszukiwaniu w gb.
Oznaczmy za pomoc nawiasu otwierajcego (u" chwil odwiedzenia wierzchoka u a za
pomoc nawiasu zamykajcego chwil jego przetworzenia u)".
Historia odwiedzania i przetwarzania wierzchokw jest poprawnie zbudowanym
wyraeniem nawiasowym - nawiasy s waciwie zagniedone.

Instytut Aparatw Elektrycznych


Algrm11
Dr J. Dokimuk

97

Algorytmy i Struktury Danych wykad

Instytut Aparatw Elektrycznych


Algrm11
Dr J. Dokimuk

98

Algorytmy i Struktury Danych wykad

11.4.1. Algorytm Kruskala

11.4. Grafy z wagami


Graf, w ktrym do kadej krawdzi przywizana jest waga,
bdca liczb cakowit lub rzeczywist.
Wagi reprezentuj zazwyczaj obiekty o okrelonych cechach
fizycznych jak dugo, czas przejazdu, koszt i inne, ktre narastaj
liniowo wzdu cieki grafu, a ktre staramy si minimalizowa.

Dla prezentacji grafu wagowego w postaci list ssiedztwa,


elementy listy staj si strukturami, o co najmniej dwch polach
zawierajcych numer wza i wag krawdzi.
Problem najkrtszej cieki
Dany jest waony graf skierowany G = (V, E) z funkcj wagow w: E
R, przyporzdkowujc
krawdziom wagi.
Dany jest wyrniony wierzchoek s V, zwany rdem.
Dla dowolnego wierzchoka v V naley znale najkrtsz ciek z s do v.
k

Waga cieki p = < v0, v1, ..., vk > -suma wag tworzcych j krawdzi: w( p ) = w( vi 1 , vi )
i =1

Wag najkrtszej cieki z wierzchoka u do wierzchoka v okrela zaleno:


p
min{ w( p ) : u

v } jezeli istnieje sciezka z u do v


(u ) =
w przeciwnym razie

Najkrtsza cieka z wierzchoka u do v: -kada cieka p z u do v, dla ktrej w(p) = (u, v).
Warianty problemu najkrtszej cieki dla grafu spjnego:
1. Dla dwch dowolnych wzw A i B znale najkrtsza ciek od A do B.
2. Dla wza A znale najkrtsze cieki do pozostaych wzw w grafie.
3. Pomidzy kad par wzw w grafie znale najkrtsz ciek.

Rozwizuje problem minimalnego drzewa rozpinajcego dla waonego grafu nieskierowanego.


Tworzy si rozczne podzbiory zbioru V (kady podzbir zawiera jeden wze).
Krawdzie badane s zgodnie z niemalejc wartoci ich wag (wartoci rwne dowolnie).
Tworzony jest nowy zbir F wierzchokw i krawdzi.
Krawd jest dodawana do F jeeli czy dwa wierzchoki z rnych zbiorw rozcznych,
a podzbiory zostaj scalone w jeden zbir.
Krawd istniejca ju w nowym podzbiorze F jest opuszczana.
Proces kontynuuje si do momentu scalenia wszystkich podzbiorw w jeden zbir.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

w
1
2
2
4
4
7
7
8
8
9
9
10
11
14

Krawd

(w6, w7)
(w2, w9)
(w5, w6)
(w2, w5)
(w1, w8)
(w2, w3)
(w7, w9)
(w7, w8)
(w1, w2)
(w3, w4)
(w6, w9)
(w4, w5)
(w1, w7)
(w3, w5)

Podzbiory
{w1}, {w2}, {w3}, {w4}, {w5},{w6, w7}, {w8}, {w9}
{w1}, {w2, w9}, {w3}, {w4}, {w5},{w6, w7}, {w8}
{w1}, {w2, w9}, {w3}, {w4},{w5, w6, w7}, {w8}
{w1}, {w2, w5, w6, w7w9}, {w3}, {w4}, {w8},
{w1, w8}, {w2, w5, w6, w7,w9}, {w3}, {w4}
{w1, w8}, {w2, w3, w5, w6, w7, w9}, {w4}
krawd istnieje - nie jest wstawiana

{w1, w2, w3, w5, w6, w7, w8, w9}, {w4}


krawd istnieje - nie jest wstawiana

{w1, w2, w3, w4, w5, w6, w7, w8, w9}


KONIEC

Mog pojawi si krawdzie z ujemnymi wagami.


Jeeli ze rda s nie jest osigalny aden cykl o ujemnej
wadze, to waga najkrtszej cieki (s, v) jest dobrze
zdefiniowana, nawet jeeli przyjmuje ujemne wartoci.
Jeeli ze rda s osigalny jest cykl o ujemnej wadze to wagi
najkrtszych cieek nie s dobrze zdefiniowane. adna cieka ze rda s
do wierzchoka, przechodzc przez ujemny cykl nie jest najkrtsza
(mona znale ciek krtsz, rozszerzajc j o ujemny cykl).
Problem najkrtszej cieki z jednym rdem rozwizuje algorytm Dijkstry dla wag
nieujemnych, bd algorytm BellmamaForda gdy wagi s ujemne.
Problem minimalnego drzewa rozpinajcego w grafie spjnym
Konstrukcja drzewa T czcego wszystkie wierzchoki, ktrego czna waga jest najmniejsza.
czenie kocwek ukadw elektronicznych, minimalizujce dugo cieek przewodzcych.
Problem modeluje spjny graf nieskierowany G = (V, E), w ktrym V jest zbiorem kocwek,
za E jest zbiorem moliwych pocze midzy parami kocwek.
Do kadej krawdzi (u, v) przypisana jest waga w(u, v), okrelajca dugo potrzebnego
przewodu do poczenia wierzchokw u i v.
Problem rozwizuje znalezienie acyklicznego podzbioru T E, ktry czy wszystkie
wierzchoki i ktrego czna waga okrelona zalenoci: w(T ) = w( u, v ) jest najmniejsza.
( u , v ) T

Acykliczno podzbioru T czcego wszystkie wierzchoki


grafu sprawia, e T jest drzewem rozpinajcym graf G.
Przedstawiony problem rozwizuj algorytmy Kruskala i Prima.
S to algorytmy realizujce strategi zachann, podejmujce
decyzje najlepsze w danej chwili. Wybrane strategie
zachanne pozwalaj otrzyma drzewo o minimalnej wadze.

F = 0;
// inicjalizacja pustego zbioru krawdzi
Utwrz V rozcznych podzbiorw wzw
Sortuj(krawdzie E w porzdku niemalejcym)
while (liczba krawdzi w F < V - 1)
Wybierz kolejn krawd
if (krawd czy 2 wzy ze zbiorw rozcznych)
Scal(podzbiory)
Dodaj(krawd do F)

F = 0;
Wstaw krawdzie do Kolejki priorytetowej
while (liczba krawdzi w F < V - 1)
Pobierz krawd z Kolejki
if (krawd czy 2 wzy ze zbiorw rozcznych)
Scal(podzbiory)
Dodaj(krawd do F)

Zoono czasowa (instrukcja porwnania)


1. Zoono czasowa sortowania krawdzi: W(E) O(E lg(E)).
2. Czas realizacji ptli while to gwnie dziaania na zbiorach rozcznych; W(E) O(E lg(E)).
W najgorszym przypadku zostaje rozpatrzona kada krawd, co oznacza wykonanie E
przebiegw ptli, ktra zawiera sta liczb wywoa stosownych podprogramw.
3. Czas inicjalizacji V zbiorw rozcznych moe okrela zaleno: T(V) O(V)
Poniewa E > V-1, sortowanie i wykonywanie operacji na zbiorach rozcznych jest dominujc
skadow czasu inicjalizacji, co oznacza, e W(E, V) O(E lg(E))
W najgorszym przypadku kady wze moe by poczony z kadym innym: E = 0.5*(V(V-1)) O(V2).
Zatem najgorszy przypadek: W(E, V) O(V2 lg(V2)) = O(V2 2 lg(V)) = O(V2 lg(V)).

Instytut Aparatw Elektrycznych


Algrm11
Dr J. Dokimuk

Algorytmy i Struktury Danych wykad

99

11.4.2. Algorytm Dijkstry

Dla wza S znale najkrtsze cieki od S do


pozostaych wzw grafu skierowanego, gdy wagi
wszystkich krawdzi s nieujemne.
Algorytm tworzy skierowane drzewo najkrtszych cieek
(Shortest Paths Tree SPT) z korzeniem w rdle S, tak e
kada cieka w drzewie idca ze rda jest najkrtsza.
Moe by wiele cieek tej samej dugoci czc dan par wzw.
Zwalnianie (relaxation)
Na pocztku znane s tylko krawdzie grafu i ich wagi. Przetwarzajc uzyskujemy informacje o
aktualnie najkrtszych ciekach w grafie. Algorytmy uaktualniaj te informacje stopniowo, tworzc
nowe wnioski o najkrtszych ciekach na podstawie dotychczas uzyskanych informacji.
W kadym kroku testuj moliwo znalezienia cieki krtszej od dotychczas znanej.
Relaksacja krawdzi: sprawdzanie czy przesuwajc si wzdu innej krawdzi (u, v), znajdziesz now,
krtsz od dotychczas najkrtszej cieki do wza v.
Pamitamy najkrtsze znane cieki ze rda s do wszystkich
wzw (w chwili ti) i pytamy, czy w chwili nastpnej krawd (u, v)
da jeszcze krtsz ciek do v.
Jeeli nie to pomijamy j.
Jeeli tak to bierzemy krawd (u, v), uaktualniamy dane, gdy
najlepsza droga z s do v wiedzie teraz przez wze u.

Najpierw odwiedzamy wze najbliszy wza S, potem 2-gi w kolejnoci i tak dalej (v1, v2,...).
Wze x1 najbliszy S musi by ssiadem. Wze v2 (2-gi) musi by ssiadem S lub v1.
Kiedy wze zosta ju odwiedzony, znamy dugo najkrtszej cieki od niego do S.
Obwdka -zbir nie odwiedzonych krawdzi (wzw), ssiadujcych z wzami odwiedzonymi.
Nastpny do odwiedzenia wybieramy wze z obwdki, ktrego cieka do S jest najkrtsza.

Instytut Aparatw Elektrycznych


Algrm11
Dr J. Dokimuk

11.5. Przykady implementacji


// Przeszukiwanie w gb - DFS;
// "nowy" = 0; "stary" = 1;
#include<iostream.h>

const int V = 10;


char G[V] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };
char *ListG[V] = { "DBHE", "ACE", "BJG", "HA", "AHIFB",
"E", "CJ", "DAE", "HEJ", "ICG" };
int Stary[V];
// zerowanie (nowy) wszystkich wzw
inline int Ind(char zn) { return zn 'A' }
void Visit(char u)
{
char *jL;
Stary[Ind(u)] = 1;
cout << u;

ADHEIJCBGF

for (jL = ListG[Ind(u)]; *jL; jL++)


if (!(Stary[Ind(*jL)])) Visit(*jL);
}
void DFS()
{
for (int i=0; i < V; i++)
//start od G[0] czyli A
if (!(Stary[Ind(G[i])])) Visit(G[i]);
}
int main()
{
DFS();
return 0;
}

Grube krawdzie to krawdzie drzewa SPT, za szare s krawdziami obwdki.


Etap 1: dodanie W1 do drzewa, za opuszczajcych go krawdzi (1, 2) i (1, 6) do obwdki.
Etap 2: przesuwamy krawd (1, 6) z obwdki do drzewa i sprawdzamy krawdzie z wza W6.
Krawd (6, 5) dodajemy do obwdki.
Krawd (6, 2) odrzucamy, poniewa nie jest czci cieki z W1 do W2 krtszej ni
znana w obwdce cieka (1, 2) (odrzucenie w procesie relaksacji).
Etap 3: przenosimy (1,2) z obwdki do drzewa, dodajemy (2,3) do obwdki i odrzucamy (2,5).
Etap 4: przenosimy (6,5) z obwdki do drzewa, dodajemy (5,4) do obwdki.
Zamieniamy (2, 3) na (5, 3), poniewa 1653 jest krtsz ciek ni 123.
Etap 5, 6: przenosimy z obwdki do drzewa krawdzie (5, 3), a potem (5, 4).

100

Algorytmy i Struktury Danych wykad

// Graf1DFS

0
1
2
3
4
5
6
7
8
9

A: DBHE
B: ACE
C: BJG
D: HA
E: AHIFB
F: E
G: CJ
H: DAE
I: HEJ
J: ICG

Instytut Aparatw Elektrycznych


Algrm12
Dr J. Dokimuk

101

Algorytmy i Struktury Danych - wykad

Instytut Aparatw Elektrycznych


Algrm12
Dr J. Dokimuk

102

Algorytmy i Struktury Danych - wykad

12. KOMPRESJA DANYCH

12.1. Metoda Huffmana

Pewne litery alfabetu wystpuj w tekstach czciej ni inne.


Badania pokazay, e w jzyku angielskim najczciej wystpuj litery: e, t; najrzadziej: q, j.
Zgodnie z alfabetem Morsea: e . t q --.- j ---

Rozwamy plik o dugoci 100000 znakw, zawierajcy wycznie treci skadajce si z alfabetu
= {a, b, c, d, e, f}. Czstotliwo wystpie poszczeglnych znakw (w tys.) i przyjte sowa
kodowe dla kadego znaku zawiera tabela.
znak Liczba kod
Kod o zmiennej dugoci gwarantuje, e czciej wystpujce znaki bd
znakw
kodowane za pomoc krtszych sw kodowych
a
45
0
ni znaki o mniejszej czstoci wystpowania.
b
13
101

Morse uzyska zmniejszenie dugoci przesyanych tekstw poprzez przypisanie


czciej wystpujcym znakom krtszych cigw kodowych.
Algorytm Run Length Encoding - RLE
Efektywny przy kompresji blokw danych, w ktrych powtarza si wiele znakw obok siebie.
Niech blok 20 znakw ma posta:
AABBBBBCCCBBDDDDDDDD
Blok mona skompresowa do 13 znakw: AA#5B#3CBB#8D
nX oznacza n-krotne wystpienie znaku X,
# jest separatorem pomidzy danymi niekodowanymi i kodowanymi.

Cel kompresji: zmniejszy rozmiar bloku danych bez utraty jego zawartoci.
Metoda sownikowa.
Kolejno analizowane cigi symboli koduje si za pomoc pojedynczych odwoa do sownika,
w ktrym przechowywane s czsto powtarzajce si sekwencje znakw.
W strumieniowych metodach sownikowych budowane s dwa sowniki:
-jeden wykorzystywany jest dla kodowania czsto wystpujcych wzorcw,
-drugi dla pozostaych. Zysk metody zaley od tego, jak duo cigw kodowych
zostanie rozpoznanych jako czsto wystpujce.
BACKABWACKACACKA = 16 znakw 8 bitw = 128 bitw
Rozpoczyna si od zebrania statystyk wystpowania poszczeglnych znak Liczba kod
znakw
elementw w zbiorze. Przypisuje si kody o zmiennej liczbie bitw
6
0
(krtszy, gdy znak wystpuje czciej) poszczeglnym elementom na A
podstawie czstoci ich wystpowania w zbiorze.
4
11
C
Budowane jest drzewo binarne, w ktrym elementy zbioru K
3
100
umieszczane s w liciach. Kod kadego znaku jest wynikiem B
2
1011
przejcia od korzenia drzewa do odpowiedniego licia.

Algorytm Huffmana

1010

Po kompresji: 10110111000101110100111000110111000 = 35 bitw


Dynamiczny algorytm Huffmana stosowany jest do dekompresji strumienia danych.
W miar napywu informacji, co zadan liczb znakw, na budowane drzewo binarne
nanoszone s poprawki.

Komunikat zawiera tym wicej informacji, im mniejsze jest prawdopodobiestwo jego wystpienia
jest podstawowym zaoeniem teorii informacji, ktr stworzy Claude Shannon w 1948-1949.
Niech bdzie skoczonym zbiorem wszystkich moliwych wysanych komunikatw.
Odbiorca nie wie, ktry z moliwych komunikatw ze zbioru = {k1, k2, ... , kn} otrzyma.
Komunikaty o zdarzeniu pewnym (ktrych zajcia jest pewien) nie przeka odbiorcy adnej
informacji, gdy nie zmieni stanu jego wiedzy.
Komunikat, ktrego prawdopodobiestwo wystpienia wynosi p I ( p ) = log ( p )
2
zawiera I(p) jednostek informacji.
n
Entropia H rda informacji: rednia (waona) ilo informacji w
H ( p) = pk log2 ( pk )
komunikatach ze rda, ktre nadaje n rnych komunik =1
katw z prawdopodobiestwem wystpienia pk (k=1,2,...,n).
Sowo kodowe: kod komunikatu. Dugo sowa kodowego: liczba jego elementw (znakw).

rednia dugo Lave sowa kodowego (waona dugo cieki):


gdzie Ni dugoci sw kodowych komunikatw rda.
p1
n

N1

I p1 = 1.42

6
16
1

p2
N2

I p2 = 2

4
16
2

p3
N3

I p3 = 2.42

3
16
3

p4
N4
I p4 = 3

2
16
4

p5
N5
I p5 = 4

Lave = pk N k
k =1

1
16
4

H ( p , n ) = 2.11
L ave ( p , n , N ) = 2.19

p1

0.45

p2

0.13

p3

0.12

p4

0.16

p5

0.09

p6

0.05

N1

N2

N3

N4

N5

N6

I p1 = 1.15

I p2 = 2.94

Entropia: H ( p , n ) = 2.22

I p3 = 3.06

I p4 = 2.64

I p5 = 3.47

I p6 = 4.32

rednia dugo sowa kodowego: L ( p , n , N ) = 2.24

c
d
e
f

12
16
9
5

100
111
1101
1100

Po dokonaniu kompresji plik o dugoci 100000 znakw czyli 800 000 bitw zajmowa bdzie
(451 + (13 + 12 + 16)3 + (9 + 5 ) 4) 1000 = 224 000 bitw.
Kod prefiksowy: kod kadego znaku nie jest prefiksem innego znaku.
Pozwala uzyska maksymalny stopie kompresji.
Kodowanie prefiksowe wymaga tylko skonkatenowania kodw kolejnych znakw w pliku.
Na przykad plik zawierajcy znaki abcdef reprezentowany bdzie za pomoc cigu bitw:
010110011111011100 = 010110011111011100, znak " oznacza operacj konkatenacji.
Dekodowanie dla kodw prefiksowych jest stosunkowo proste.
Pierwszy kod znaku jest wyznaczony jednoznacznie, bo aden kod nie jest prefiksem innego.
Naley: -wyznaczy pierwszy kod w pliku, -przetumaczy go na znak,
-usun z zakodowanego pliku;
-powtrzy procedur dekodujc dla reszty pliku.
Cig 1111101101010011011100 rozkada si jednoznacznie na
111-1101-101-0-100-1101-1100, co daje sowo debacef.

Kod prefiksowy reprezentowany jest przez regularne drzewo


binarne, ktrego licie odpowiadaj zakodowanym znakom.
Kady wze wewntrzny ma dwch synw.
Kady li etykietowany jest znakiem i liczb wystpie znaku.
Kady wze wewntrzny etykietowany jest sum wag lici w
poddrzewie, ktrego jest korzeniem.
Sowo kodowe jest ciek od korzenia do znaku przyjmujc, e 0
oznacza przejcie do lewego syna", a 1 przejcie do
prawego syna" w drzewie.
a 0, b 101, c 100, d 111, e 1101, f 1100
Tylko regularne drzewo binarne zapewnia optymalny kod.
Kod o staej dugoci: a 000, b 001, c 010, d 011, e 100, f 101
nie jest optymalny gdy s kody rozpoczynajce si od 10..., nie ma za od 11....
Dla alfabetu prefiksowe drzewo kodowe ma || lici oraz || - 1 wzw wewntrznych.
Koszt kodowego drzewa prefiksowego T to liczba bitw potrzebnych do
B(T ) = Lc d c
zakodowania pliku, okrelona jest wzorem B(T)
c
gdzie Lc liczba wystpie znaku c w alfabecie; dc dugo kodu znaku c.
Nadawca i odbiorca musz uywa tego samego sposobu kodowania - tego samego drzewa Huffmana.
W jaki sposb nadawca moe poinformowa odbiorc, ktrego kodu uy?
1. Nadawca i odbiorca uzgadniaj na wstpie wybr konkretnego drzewa Huffmana i obydwaj
uywaj go przy przesyaniu wszelkich informacji.
2. Nadawca buduje drzewo Huffmana na nowo przy przesyaniu kadej nowej wiadomoci, a
wraz z sam wiadomoci przesya tabel konwersji. Odbiorca wykorzystuje tabel do
rekonstrukcji drzewa Huffmana i dopiero za jego pomoc dokonuje tumaczenia.
Druga strategia jest bardziej uniwersalna, jej zalety s widoczne przy kodowaniu duych plikw.

Instytut Aparatw Elektrycznych


Algrm12
Dr J. Dokimuk

Algorytmy i Struktury Danych - wykad

103

Huffman()
Utwrz
jednowzowe drzewo dla kadego symbolu.
Uporzdkuj
wszystkie drzewa ze wzgldu na czsto wystpie symboli.
while zostao wicej ni jedno drzewo
we dwa drzewa T1 i T2 o najmniejszych czstociach f1 i f2 (f1 f2) wystpowania
symboli i utwrz drzewo o synach T1 i T2 i czstoci w korzeniu rwnej f1 + f2
Oznacz kad krawd skierowan w lewo jako 0, a skierowan w prawo jako 1.
Utwrz kod dla kadego symbolu, przechodzc drzewo od korzenia do licia odpowiadajcego
temu symbolowi i czc napotykane zera i jedynki.
W korzeniu otrzymanego drzewa czsto wystpie wynosi 1.
Budowanie drzewa algorytm kodowania Huffmana
Algorytm buduje drzewo w sposb wstpujcy rozpoczynajc od zbioru lici ||.
Kolejny etap to || - 1 operacji scalania, prowadzcych do powstania jednego drzewa.

Kademu znakowi c odpowiada jego liczba wystpie f(c).


Kolejk priorytetow Q zrealizowano jako kopiec z kluczami f i HUFFMAN()
uyto do wyznaczania dwch obiektw o najmniejszej liczbie
n  ||
wystpie, ktre w kolejnym etapie s scalane.
// budowanie kopca
Wynikiem scalenia jest nowy obiekt (wze drzewa), ktrego Q 
for i  1 to n-1 do
wartoci jest sum liczby wystpie jego skadowych.
z  CreateNode()
W ptli for cyklicznie usuwane s dwa wzy o najmniejszej
x  left[z]  MIN(Q)
liczbie wystpie, a nastpnie zastpowane w kolejce Q przez
y  right[z]  MIN(Q)
wze z, powstay przez ich scalenie.
Wzy x i y staj si odpowiednio lewym i prawym synem
f(z)  f(x) + f(y)
wza z (zamiana lewego i prawego syna daje inny kod o tym
INSERT(Q, z)
samym koszcie).
return
MlN(Q)
Po n - 1 scaleniach w kolejce pozostaje korze drzewa kodu.
Zoono obliczeniowa wynosi O(nlg(n)) i limitowana jest wykonaniem n-1 operacji na kopcu
(kada operacja na kopcu ma zoono O(lg(n)) ).
C. Shannon wykaza, e entropia H rda informacji daje najlepsz dugo kodu.
aden algorytm kompresji nie daje lepszego wyniku ni wynika to z entropi E.

Instytut Aparatw Elektrycznych


Dr J. Dokimuk
Algrm13

Algorytmy i Struktury Danych - wykad

104

13. PROBLEMY NP ZUPENE


Problem plecakowy 0-1, komiwojaera, oraz setki innych s trudne w realizacji. Gdyby udao si
znale efektywny algorytm dla ktregokolwiek z nich to dysponowalibymy efektywnymi
algorytmami dla wszystkich problemw tej grupy. Takiego algorytmu nie wynaleziono lecz nie
udowodniono, e nie jest to moliwe. Jest to tematyka problemw NP-zupenych.
Algorytm wielomianowy: jego pesymistyczna zoono czasowa ograniczona jest z gry przez
funkcj wielomianow, zalen od rozmiaru danych wejciowych n.
Istnieje taki wielomian g(n), e: W(n) O(g(n)).
Uwaga: -algorytmy zoonoci o czasowej 2n, 2n/100,n! nie s algorytmami wielomianowymi.
-nlg(n) nie jest wielomianem, jednak speniona jest nierwno: nlg(n) < n2, zatem
algorytm o takiej zoonoci czasowej spenia kryterium dla algorytmw wielomianowych.
Problem trudny: jeeli nie mona rozwiza go za pomoc algorytmu wielomianowego.
Trudno jest wasnoci problemu, nie za algorytmw go rozwizujcych.
Nie moe istnie aden rozwizujcy go algorytm wielomianowy.
Wiele algorytmw, o nie wielomianowej pesymistycznej zoono czasowej, charakteryzuje si
dobr efektywnoci dla wielu praktycznych danych wejciowych.
Znalezienie algorytmu o wielomianowej zoonoci czasowej dla pewnych danych
wejciowych nie oznacza, e problem jest atwy do rozwizania dla wszystkich danych
wejciowych (dla ktrych znalezienie algorytmu wielomianowego moe okaza si niemoliwe).

Gwne kategorie problemw ze wzgldu na ich trudno:


1. dla ktrych wynaleziono algorytmy wielomianowe,
2. ktrych trudno zostaa udowodniona,
3. ktrych trudno nie zostaa udowodniona, jednak nie udao si wynale
algorytmw wielomianowych.
Problem optymalizacyjny: jego wynikiem jest optymalne rozwizanie problemu.
Problem decyzyjny: jego wynikiem jest odpowied tak" lub nie" dla danego problemu.
Problem plecakowy 0-1: znana jest waga i warto przedmiotw oraz pojemno W plecaka.
Optymalizacyjny: wyznaczy maksymaln wartoci przedmiotw, ktre mona upchn w plecaku.
Decyzyjny: dana jest wartoci P, okreli, czy istnieje moliwo takiego spakowania plecaka, by
czna waga zapakowanych przedmiotw nie przekraczaa W, a czna warto tych
przedmiotw wynosia co najmniej P.
Problem komiwojaera: tras w waony grafie skierowanym jest droga rozpoczynajca si i
koczca w tym samym wierzchoku, przechodzca raz przez
wszystkie pozostae wierzchoki grafu.
Optymalizacyjny: znale tras o minimalnej cznej wadze nalecych do niej krawdzi.
Decyzyjny: dana jest dodatniej liczba cakowita d, okreli czy w badanym grafie istnieje trasa o
cznej wadze nalecych do niej krawdzi nie wikszej od d.
Gdyby mona byo znale algorytm wielomianowy dla problemw optymalizacyjnych,
mielibymy take algorytm wielomianowy dla odpowiedniego problemw decyzyjnych.
Rozwizanie problemu optymalizacyjnego daje rozwizanie stosownego problemu decyzyjnego.
Zbir P: zbir problemw decyzyjnych, ktre mona rozwiza algorytmami wielomianowymi.
Teoretycznie problem plecakowy 0-1 moe nalee do zbioru P.
Nikomu nie udao si stworzy algorytmu wielomianowego rozwizujcego ten problem,
lecz nikt jeszcze nie udowodni, e nie da si go rozwiza w czasie wielomianowym.
Z ca pewnoci dany problem decyzyjny nie naley do zbioru P jeeli udowodnimy, e
opracowanie odpowiedniego algorytmu wielomianowego jest niemoliwe.
Algorytm niedeterministyczny: odpowiada tylko za etap "przypuszczania", poniewa nie
mona dla niego wyznaczy unikalnej sekwencji kolejnych instrukcji.
Podczas realizacji zada komputer moe generowa dowolny (losowy) cig dziaa.
Wprowadzenie pojcia niedeterministycznego jest formalnym zabiegiem, majcym na celu
uzyskanie definicji pojcia sprawdzalnoci w czasie wielomianowym.

W praktyce nie korzysta si z algorytmw niedeterministycznych do rozwizywania problemw decyzyjnych.


Mwimy, e niedeterministyczny algorytm rozwizuje" problem decyzyjny, jeli:
1. Dla dowolnego przypadku, dla ktrego odpowiedzi jest tak", istnieje pewien cig dziaa,
dla ktrego na etapie weryfikacji otrzymamy wynik prawda".
2. Dla dowolnego przypadku, dla ktrego odpowiedzi jest nie", nie istnieje aden cig dziaa,
dla ktrego na etapie weryfikacji otrzymamy wynik prawda".

Instytut Aparatw Elektrycznych


Dr J. Dokimuk
Algrm13

105

Algorytmy i Struktury Danych - wykad

Algorytm wielomianowy niedeterministyczny: algorytm niedeterministyczny (zgadujcy), ktrego


etap weryfikacji jest algorytmem wielomianowym.
Zbir NP (Nondeterministic Polynomial): zbir wszystkich problemw decyzyjnych, ktre mona
rozwiza za pomoc niedeterministycznych algorytmw wielomianowych.
Problem decyzyjny naley do zbioru NP jeeli istnieje dla niego algorytm weryfikujcy w czasie wielomianowym.
Nie oznacza to, e musi istnie algorytm wielomianowy rozwizujcy ten problem decyzyjny.
Decyzyjny problem komiwojaera naley do zbioru NP, gdy istnieje weryfikujcy go algorytm w
czasie wielomianowym, mino e nie wynaleziono takiego algorytmu rozwizujcego ten problem.
Istnieje mnstwo problemw, dla ktrych nie udao si stworzy algorytmu rozwizujcego je w
czasie wielomianowym, ale udowodniono, e nale one do zbioru NP, poniewa opracowano
dla nich niedeterministyczne algorytmy wielomianowe .

Kady problem nalecy do zbioru P naley take do zbioru NP.


Kady problem nalecy do zbioru P mona rozwiza za pomoc algorytmu wielomianowego,
mona wic wygenerowa dowolny cig na etapie niedeterministycznym i uruchomi algorytm
wielomianowy na etapie deterministycznym. Wynikiem weryfikacji dla danego cigu
wejciowego bdzie odpowied tak", jeli jest rozwizanie dla konkretnego przypadku.

Problemy decyzyjne, dla ktrych udowodniono, e nie nale do zbioru NP, s


dokadnie tymi samymi problemami, dla ktrych udowodniono, e s trudne.
Problem CNF-spenialnoci
Zmienna logiczn (boolowsk), x jest prawdziwe wtedy i tylko wtedy, gdy x jest faszywe.
Litera jest logiczn zmienn lub negacj logicznej zmiennej.
Klauzula jest sekwencj literaw, oddzielonych za pomoc operatora logicznego OR (v).
Koniunkcyjna posta normalna (Conjunctive Normal Form - CNF) logicznego wyraenia jest
sekwencj klauzul, oddzielonych za pomoc logicznego operatora AND (
).
Przykad wyraenia logicznego w postaci CNF: ( x 1 x2 x 3 ) ( x 2 x1 x 4 ) ( x1 x3 ) .
Decyzyjny problem CNF-spenialnoci: okreli dla logicznego wyraenia CNF, czy istnieje
takie przyporzdkowanie wartoci zmiennych (zbir przyporzdkowa wartoci prawda" i
fasz" do zmiennych uytych w wyraeniu), dla ktrego cae wyraenie bdzie prawdziwe.
Dla wyraenia CNF ( x1 x2 ) x1 x2 nie istniej przypisania, dla ktrych bdzie ono
prawdziwe, dla problemu CNF-spenialnoci odpowied jest NIE.
Dla wyraenia ( x1 x2 ) ( x2 x3 ) x2 istniej przypisania, dla ktrych bdzie ono
prawdziwe, dla problemu CNF-spenialnoci odpowied jest TAK. (x1=P, x2=x3=F)
Istniej algorytmy wielomianowe, ktre - dla pobranego wyraenia logicznego CNF i zbioru
przyporzdkowa wartoci logicznych do zmiennych -sprawdzaj, czy wyraenie jest logiczne.
Nie istnieje algorytm wielomianowy rozwizujcy ten problem, lecz nie udowodniono,
e tego problemu nie da si rozwiza w czasie wielomianowym
W roku 1971 S. Cook udowodni, e jeli problem CNF-spenialnoci naley do zbioru P, to P=NP.
Rysunek przedstawia zbir wszystkich problemw decyzyjnych, gdzie P
problemy
jest podzbiorem zbioru NP. Nie ma jednak pewnoci, e tak faktycznie jest.
Niepewno wynika z faktu, e nikomu nie udao si dowie, e
decyzyjne
istnieje problem w zbiorze NP, ktry nie naley do zbioru P.
Pytanie czy zbiory P i NP s sobie rwne, jest jedn z wanych kwestii w
informatyce, poniewa dua grupa problemw decyzyjnych naley do
zbioru NP.
Gdyby okazao si, e P = NP, moglibymy opracowa algorytmy
wielomianowe dla wikszoci znanych dzisiaj problemw decyzyjnych.
Aby udowodni, e P NP naley znale problem nalecy do zbioru
NP, ktry nie naleaby do zbioru P.
Aby udowodni, e P = NP, naley znale algorytm wielomianowy dla kadego z problemw
nalecych do zbioru NP. To zadanie mona uproci, gdy wykazano, e konieczne jest
znalezienie wielomianowego algorytmu tylko dla jednej z ogromnych klas problemw.

NP

Instytut Aparatw Elektrycznych


Dr J. Dokimuk
Algrm13

106

Algorytmy i Struktury Danych - wykad

Naley rozwiza problem decyzyjny A, dysponujc algorytmem rozwizujcym problem B.


Zamy, e utworzymy algorytm dajcy tak realizacj y problemu B na podstawie kadej
moliwej realizacji x problemu A, e algorytm dla realizacji y problemu B zwrci odpowied
tak" wtedy i tylko wtedy, gdy odpowied dla realizacji x problemu A take brzmi tak".
Taki algorytm nazywany jest algorytmem transformacji
A
Algorytm tak
i ma posta funkcji y = Trans(x), odwzorowujcej
dla
x
Trans
dowolne realizacje problemu A w odpowiednie
y problemu B nie
realizacje problemu B.
Trans jest algorytmem transformacji, odwzorowujcym kad realizacj x problemu
decyzyjnego A w realizacj y problemu decyzyjnego B. W poczeniu z
algorytmem dla problemu B daje algorytm rozwizujcy problem decyzyjny A.
Mamy dane wejciowymi x dla problemu A i chcemy odpowiedzi tak" lub nie", to zastosujemy
algorytm Trans do przeksztacenia danych x w dane wejciowe y dla problemu B w taki sposb, eby
odpowied do problemu B dla danych y bya dokadnie odpowiedzi do problemu A dla danych x.

Problem A jest wielomianowo redukowalny do problemu B, jeli istnieje wielomianowy


algorytm transformacji z problemu decyzyjnego A do problemu decyzyjnego B : A B.
Jeli zoono czasowa algorytmu transformacji jest wielomianowa i istnieje wielomianowy
algorytm rozwizujcy problem B, to algorytm dla problemu A musi by wielomianowy.
Twierdzenie 2.1. Jeli problem decyzyjny B naley do zbioru P oraz A B to problem
decyzyjny A take naley do zbioru P.

Problem B nazywamy NP-zupenym, jeli spenione s dwa warunki:


1. Problem B naley do zbioru NP.
2. Dla kadego innego problemu A nalecego do zbioru NP prawdziwe jest wyraenie: A B.
Twierdzenie 2.2. (Cooka, 1971r.): Problem CNF-spenialnoci jest problemem NP-zupenym.
Twierdzenie 2.3. Problem C jest problemem NP-zupenym, jeli spenione s dwa warunki:
1. Problem C naley do zbioru NP. (weryfikowany wielomianowo)
2. Dla innego problemu NP-zupenego B prawdziwe jest wyraenie: B C.
W oparciu o Tw. Cooka i Tw. 2.3 mona wykaza, e wybrany problem decyzyjny jest NP-zupeny,
dowodzc jedynie e:
1. problem ten naley do zbioru NP,
2. CNF-spenialno wybrany problem (problem CNF-spenialnoci redukuje si do naszego problemu).

Problemy decyzyjne nie nalece do zbioru NP nie mog by


problemami NP-zupenymi.
Jeli P NP to: P NP-zupene =

NP

NP
- zu
pe
ne

Zbir problemw NP-zupenych jest podzbiorem zbioru NP, zgodne z definicj.

(brak wsplnych elementw)


Powysza zaleno wynika z faktu, e gdyby jaki problem w zbiorze P
by NP-zupeny, to na podstawie Tw.2.1 moglibymy uzna, moliwo
rozwizania problemu ze zbioru NP w czasie wielomianowym.
P
Uwaga: nie jest wykluczone, e P i NP to ten sam zbir.
____________________________________________________________
Zbir P problemw decyzyjnych rozwizywanych w czasie wielomianowym.
Zbir NP problemw decyzyjnych zgadywanych i weryfikowanych w czasie wielomianowym.
Zbir NP-zupeny: wszystko albo nic. Jeliby dla jakiegokolwiek problemu NP-zupenego
znaleziono algorytm wielomianowy, byby to algorytm dla wszystkich z nich.
Kady problem NP-zupeny redukuje si w czasie wielomianowym do kadego innego;
trudno rozwizania jednego pociga za sob trudno rozwizania wszystkich.
Aby wykaza, e problem jest NP-zupeny, wystarczy udowodni, e problem redukuje
si (w czasie wielomianowym) do co najmniej jednego problemu Q NP-zupenego i e co
najmniej jeden problem R NP-zupeny, redukuje si do .

Pokazanie, e jaki problem jest NP-zupeny, jest sygnalizacj moliwych trudnoci w jego rozwizaniu.

You might also like