Vous êtes sur la page 1sur 45

Algoritmi i strukture podataka

Ilija Lalovic
0.1 Asimptotske oznake
O - notacija je korisna za analizu programa, posto obuhvata asimptotski rast funkcija i ignorise konstantne mnozitelje.
Konstantni mnozitelji su ionako van nase kontrole kada prevedemo algoritme u programe. Mi koristimo sledece
denicije, mada postoje i alternativne:
Neka f,g: N N :
g(n) = O(f(n)) akko (K R), tako da za dovoljno veliko n
0
za svako n n
0
imamo g(n) K f(n)
Primer 0.1. 1. (1000n
2
+ 100n + 1000) = O(n
3
)
2. n
2
= O(n
3
100n
2
2n)
3. n
i
= O(poly(n)), gde je deg(p) i , a vodeci koecijent p(n) je pozitivan.
f(n) = (g(n)) akko g(n) = O(f(n))
g(n) = (f(n)) akko (g(n)=O(f(n)) i f(n)=O(g(n))
Primer 0.2. Razmotriti sledece funkcije:

n, n, 2n, nlogn, n n
3
+ 7n
5
, n
2
+logn, n
2
, n
3
, logn, n
1/3
+logn, (logn)
2
, n!, lnn,
n
logn
, loglogn, (1/3)
n
, (3/2)
n
, 6.
Grupisati ove funckije tako da su f(n) i g(n) u istoj grupi akko g(n) =O(f(n)) i ispitati grupe u rastucem poretku.
0.2 Primer programa koji ispisuje sopstveni kod
U inzinjerstvu samorepliciranje bi moglo omoguciti snizenje cena proizvodnje. Sledeci C++ program replicira samog
sebe:
# i nc l ude <i os t r eam . h>
main ( )

char s= # i nc l ude <i os t r eam . h> %c


main ( )

char s=%c%s%c ;
count . form( s , 10 , 34 , s , 3 4 , 1 0 ) ;
%c ;
count . form( s , 10 , 34 , s , 3 4 , 1 0 ) ;
Autor je lapinski@utexas.edu.
Sledeci C program velicine 800bitova, objavljen u casopisu Byte, Avgust 1980.g. 74.strana, takodje replicira samog
sebe.
main ( )

char q=34, n=10,


a=main ( ) char q=34, n=10, a= %c%s%c ;
pr i nt f ( a , q , a , q , n ) ; %c ;
pr i nt f ( a , q , a , q , n ) ;
Neki drugi samoreplicirajuci mehanizmi su puno slozeniji. Za poredjenje, Morisov internet crv ima oko 500 000
bitova, bakterija Esherichia coli ima 8 000 000 bitova, Drekslerov assembler ima 100 000 000 bitova, a covek oko 64
000 000 000 bitova.
Gornji primeri samoreproducirajucih programa daju nadu da ce u buducnosti biti moguce napraviti jednostavne
samoreproducirajuce masine koje ce pomagati u procesu proizvodnje u nanotehnologijama. Za vise detalja i reference
vd. N.Mitic, Osnovi racunarskih sistema, CET, Beograd 2003.
0.3 Hijerarhije slozenosti algoritama
Vremenska slozenost(kompleksnost) algoritma se odredjuje kao asimptotska slozenost funkcije koja predstavlja broj
koraka (jedinica vremena) algoritma u odnosu na duzinu ulaza(ne u odnosu na partikularni ulaz). Prostotna slozenost
algoritma odredjuje se kao asimptotska slozenost funkcije koja predstavlja prostorne resurse(memoriju) potrebnu al-
goritmu u odnosu na duzinu ulaza. Razlikujemo worst case, best case i awerage case slozenosti algoritma. Algoritmi
mogu biti polinomijalni, nepolinomijalni, potpuno eksponencijalni i subeksponencijalni.
Izvodljivi( eng. Feasible) algoritmi imaju polinomijalnu slozenost.
Ovde ne razmatramo artimeticke i analiticke hijerarhije slozenosti. Samo napominjemo da se jedan od najvaznijih
problema teorijskih kompjuterskih nauka kratko formulise P=NP (?!).
0.4 Poredjenje algoritama polinomijalne, logaritamske i eksponencijalne
slozenosti
Slozenost algoritama zavisi od modela komputacije. Dimenzija problema je mera ulaznih podataka. Npr. Dimenzija
problema mnozenja matrica moze biti najveca dimenzija matrice faktora. Kada govorimo o vremenskoj slozenosti mis-
limo na asimptotsku vremensku slozenost, a kada govorimo o prostornoj slozenosti mislimo na asimptotsku prostornu
slozenost. Poredjenje algoritama dajemo u sledecoj tabeli:
Maksimalna dimenzija problema
Algoritam Vremenska slozenost 1s 1min 1h
A1 n 1000 6 10
4
3.6 10
6
A2 nlogn 140 4893 2 10
5
A3 n
2
31 244 1897
A4 n
3
10 39 153
A5 2
n
9 15 21
0.5 Uticaj povecanja brzine procesora na kompleksnost algoritma
Maksimalna dimenzija problema
Algoritam Vremenska slozenost Do ubrzanja Nakon 10x ubrzanja
A1 n s1 10s1
A2 nlogn s2 10s2 za veliko s2
A3 n
2
s3 3.16 s3
A4 n
3
s4 2.15 s4
A5 2
n
s5 s5+3.3
Pitanje:
Moze li eksponencijalni algoritam biti bolji od polinomijalnog?
Odgovor:
Razmotrimo algoritme.
Algoritam A1 A2 A3 A4 A5
Slozenost 100n 100nlogn 10n
2
n
3
2
n
Nije tesko izracunati da:
A5 je najbolji za 2 n 9;
A3 je najbolji za 10 n 58;
A2 je najbolji za 59 n 1024;
A1 je najbolji za n > 1024.
0.6 Worst case, best case i awerage case slozenost algoritama
Mi se najcesce koncentrisemo na nalazenje worst case(najgori slucaj) vremena izvodjenja algoritama. Za ovakav pristup
imamo najmanje tri razloga:
Worst case vreme izvodjenja je gornja granica vremena izvodjenja za svaki ulaz. Znanje te granice garantuje da
algoritam nece nikada raditi duze, sto nam je u praksi vazno.
Neki algoritmi cesto rade u worst case vremene. Npr. Kod trazenja u bazi podataka neke partikularne informacije,
algoritam pretrazivanja ce cesto raditi u worst case vremenu, ako ta informacija ne postoji u bazi. Pri tome je trazenje
nepostojece informacije cest slucaj.
Awerage case (statisticka slozenost, matematicko ocekivanje) je cesto lose kao i worst case. Npr. kod sortiranja
umetanjem(insert sort) awerage case je O(n
2
), kao i worst case. Kod Quick Sort-a to nije slucaj. Awerage case
slozenost ili ocekivano vreme za jedan algoritam je T(n)=

n
i=1
p
i
T(i), gde je p
i
verovatnoca slozenosti T(i).
Insert sort
Primer 0.3. 1. Worst case slozenost T(n)=O(n
2
)=0+1+. . . +(n-1).
2. Best case slozenost. Ako u svakom koraku element koji umecemo dolazi na prvo mesto imamo T(n)=0+1+. . . +1
=

n1
i=0
i=n-1=O(n).
3. Awerage case slozenost.
Lema 0.1. . Srednji broj inverzija u jednom nizu od n elemenata je
n(n1)
4
.
Dokaz 0.1. Posmatrajmo listu L i njen reverz Lr. Npr. L=(8,34,64,51,32,21), Lr=(21,32,51,64,34,8). (x,y) prave
inverziju ako je y > x. Tacno u jednoj L ili Lr je (x,y) inverzija I=
n(n1)
4
.
Teorema 0.1.. Awerage case slozenost za insert sort je T(n)=O(n
2
).
Dokaz 0.2. Svaki korak u sortiranju eliminise samo jednu inverziju.
0.7 Racionalizacija mnozenja velikog broja kompleksnih brojeva
Mnozenje kompleksnih brojeva (a u odnosu na polje realnih brojeva) moze se posmatrati kao izracunavanje izraza ac-
bd i ad+bc tako da je (a,b)(c,d)=(ac-bd, ad+bc). U ovom slucaju imamo cetiri mnozenja i dva sabiranja/oduzimanja
(+/-). Slozenost algoritama je T(n)=O(n
2
). Do brzeg resenja dolazimo ako za kompleksne brojeve (a,b) i (c,d)
izracunamo:
1. (a+b)(c+d)=ac+ad+bc+bd;
2. ac;
3. bd.
Proizvod dobijamo do shemi (2-3,1-2-3). Ukupno imamo tri mnozenja i pet sabiranja/oduzimanja. Moze se pokazati
da je dobijeni algoritam brzi. Takodje se moze dokazati da su tri mnozenja neophodna i dovoljna.
0.8 Hornerova shema. Kompleksnost izracunavanja vrednosri polinoma.
Posmatramo izracunavanje vrednosti polinoma u tacki X. p(x) = a
n
x
n
+a
n1
x
n1
+. . . +a
1
x +a
0
Ulaz: a
0
, a
1
, a
2
, . . . , a
n1
, a
n
, x
Izlaz: p(x)
Pravilo Hornera:
1. a
1
x +a
0
, za n=1
2. (a
2
x +a
1
)x +a
0
, za n=2
3. ((a
3
x +a
2
)x +a
1
)x +a
0
, za n=3,itd.
Uopste a
0
+ x[a
1
+ x[a
2
+ . . . + a
n
x]. . . ] Za izracunavanje p(x) po Hornerovoj shemi, trebamo n operacija mnozenja
i ne operacija sabiranja. Moze se pokazati da Hornerova shema daje optimalan algoritam za izracunavanje vrednosti
polinoma u datoj tacki x (u odnosu na broj operacija sabiranja i mnozenja).
0.9 Elementarne metode sortiranja: bubble sort, sort izborom i sort
umetanjem. Dizajn i analiza slozenosti.
Neka je niz koji treba sortirati sastavljen od a[i] S, i=1,2,. . . ,n, pri cemu je S linearno uredjen skup. Sortiramo u
rastucem poretku.
Bubble sort(sort mehuricima)
Poredimo a[j] sa a[j+1], j=1,2,...,n-1, i=1,2,...,n-1. Ukoliko je a[j]a[j+1] tada elementima razmenjujemo mesta. Na
taj nacin ce u prvom prolazu najveci element doci na zadnje mesto, u drugom prolazu ce drugi po velicini element
doci na pretposlednje mesto itd. U i-tom prolazu dovodimo i-ti element na odgovarajuce mesto. Nakon nekog broja
prolaza, najvise n-1, svi ce elementi biti sortirani. Napominjemo da uvodjenjem indikatora(zastavice) mozemo uciniti
da algoritam prekine rad cim su brojevi sortirani. Naime, cim u nekom prolazu nema izmena postavljamo indikatori
na 1, a onda izlazimo iz petlje, jer je provera indikatora postavljena u uslovu petlje.
Bubble sort
templ ate <cl assT>1
voi d s or t (Ta , i nt n)

f o r ( i nt i =1; i <n ; i ++)


f o r ( i nt j =1; j<=n ; j ++)
i f ( a [ j 1]<a [ j ] ) swap( a [ j 1] , a [ j ] ) ;
// i nva r i j a nt a : i t i po v e l i c i n i el ement i su na i spravnom mestu

Worst case slozenost: T(n)=(n-1)+(n-2)+...+1=


(n1)n
2
=O(n
2
) je broj poredjenja koje trebe napraviti u najgorem
slucaju.
Insertion sort (sort umetanjem)
Na prvo mesto dovodimo proizvoljan element niza a[]. Iz ostatka niza uzimamo proizvoljno elemenat i dovodimo ga
na prvo mesto niza, ako je manji od elementa koji tamo vec stoji ili na drugo mesto, u suprotnom. Zatim iz ostatka
niza uzimamo neki element i poredimo gas a prvim i drugim elementom, tako da prva tri elementa budu uredjeni u
rastucem poretku, itd. dok ne uredimo svih n elemenata niza. [Slicno postupamo na primer slazuci karte u remiju.]
Implementacija sorta umetanjem u C++
templ ate <cl assT>
voi d s or t ( T a , i nt n)

f o r ( i nt i =1; i <n ; i ++)

T temp=a [ i ] ;
f o r ( i nt j=I ; j >0 && a [ j i ]>temp ; j )
a [ j ]=a [ j 1] ;
a [ j ]=temp ;
// I nvar i j ant a : a[0] <=a [ 1 ] <=...<=a [ i ]

Worst case kompleksnost T(n)=1+2+...+(n-1)=O( n


2
) jer za dvoclani niz imamo jedno poredjenje, za troclani
dva poredjenja... I za n-ti clan, zavrsni niz, imamo n-1 poredjenja. Uopste, i-ti element se dovodi na pravo mesto u
i-tom nizu, koristeci u najgorem slucaju (i-1) poredjenja.
Sort izborom
U prvom krugu se na prvo mesto niza a[] dovodi najmanji element niza, u drugom krugu se na drugo mesto dovodi
najmanji element iz ostatka niza, itd.
// Sort i zborom
templ ate <cl assT>
voi d s or t ( T a , i nt n)

f or ( i nt i =0; i <n1; i ++)

i nt min=I ;
f o r ( i nt j=i +1; j <n ; j ++)
i f ( a [ j ]<a [ min ] )
min =j ;
// I nvar i j ant a : a [ min]<=a [ j ] za i <=j <n
swap( a [ min ] , a [ i ] ) ;

Worst case slozenost T(n)=(n-1)+(n-2)+...+1=O(n


2
) (n-1) broj poredjenja da se od n brojeva izabere najmanji
(n-2) broj poredjenja da se iz n-1 brojeva izabere najmanji 1 broj poredjenja da se od 2 elementa izabere manji
0.10 Algoritam za nalazenje drugog elementa u nizu i razvoj algoritama
efektivnog sortiranja
Dajemo primer za nalazenje prvog i drugog po velicini elementa niza u n+log
2
n - const koraka.
Sa slike vidimo da prvi element biramo u n-1 koraka (== broj cvorova drveta). Kandidati za drugi po velicini
element su oni koji su izgubili od najveceg kandidata. Na svakom nivou drveta je po jedan takav element, pa je zbog
toga njihov broj jednak visini drveta, dakle log2n. Na slici smo takve brojeve oznacili pravougaonikom. Dakle, prvi i
drugi element niza mozemo izabrati u (n-1)+(log
2
n-1) koraka.
Ideja za sortiranje niza od n elemenata:
Naci najveci element niza i staviti ga prvo mesto u novom nizu. Naci drugi element po velicini u nizu i staviti ga na
drugom mesto, itd. U najgorem slucaju, ovaj algoritam ima slozenost T(n)=n+(n-1)+...+1=O(n
2
). Medjutim, ako
algoritam poboljsamo tako da pamtimo ko je sve izgubio od prethodnog izabranog elementa, dobicemo slozenost u
najgorem slucaju. T(n)=O(nlogn).
0.11 Metoda programiranja podeli i vladaj. Dizajn i analiza slozenosti
rekurzivnih algoritama.
1. Denisati model komputacije
2. Denisati formate podataka ulaza i izlaza
3. Denisati COST funkciju
4. Pridruziti duzine ulazima
5. Slozenost funkcije se odnosi na duzinu inputa i pri tome ne na partikularan input
Pokusavamo naci gornju i donju granicu problema. Ako problem ima gornju granicu O(f(n)) to znaci algoritam
A za problem i O(f(n)) je slozenost od A.
Algoritam je jedan potpuno specikovan niz koraka koji uvek daje korektan odgovor. Sa druge strane, hevristika
dozvoljava na nekim inputima greske, ali na vecini inputa ne.
0.11.1 Divide and conquer tehnika (ili rekurzivna tehnika) resavanja problema.
Svaki od b problema dobija
n
c
duzinu inputa duzine n. Analiza kompleksnosti takvog algoritma daje
T(n) =
_
bT(
n
c
) +n
d
, n > 1
1, n = 1
T(n)= O(n
h(a,b,c)
)
T(n) = n
d
+b,(
n
c
)
d
+b,(
n
c
2
)
d
+b T(
n
c
3
)||
n
c
i
= 1 i = log
c
n daje nam uslov zaustavljanja = n
d
+ b(
n
c
)
d
+ b
2
(
n
c
2
)
d
+ b
3
(
n
c
3
) + ... + b
i
(
n
c
i
)
d
= n
d
,1 +
b
c
d
+
(
b
c
d
)
2
+ (
b
c
d
)
3
+... + (
b
c
d
)
i
|
Mi razlikujemo izmedju b?cd log
c
b ? d
1. log
c
b = d T(n)=O(n
d
log
c
n)
2. log
c
b < d T(n)=O(n
d
)
3. log
c
b > d T(n)=O(n
log
c
b
), jer je b
log
c
n
= b
log
c
blog
b
n
log
c
b nazivamo eksponent rekurzije, a d nazivamo direktni eksponent.
0.12 Binarno pretrazivanje: nalazenje zadatog elementa u uredjenom
nizu brojeva za vreme O(logn)
Dat je sortiran niz od n brojeva. Treba naci clan niza jednak zadatom elementu x. Dajemo sledeci algoritam.
Biramo u nizu clan a
n
2
.
Ako je a
n
2
=x, tada Stop.
Ako je a
n
2
< x, ostaje da se pretrazi samo desna polovina, a ako je a
n
2
> x, ostaje da se pretrazi samo leva polovina.
Slozenost u najgorem slucaju je T(n)=n+T(
n
2
).
Dakle, d=0, b=1, c=2, sto daje log
c
b = log
2
1 = 0 = d; Prema rezultatima u pitanju 85. dobijamo T(n)=O(logn).
Implementacija algoritma binarnog pretrazivanja C++
(a) Rekurzivna procedura
/* Ako je x u nizu a[ ] tada ce njegova lokacija biti vracena, a inace ce biti vraceno -1 */
i nt f i nd ( f l o a t a , i nt s t ar t , i nt stop , f l o a t x)

i f ( s t ar t >stop ) r et ur n 1l
i nt mid=( s t a r t+stop ) /2;
i f ( x==a [ mid ] r et ur n mid ) ;
i f ( x<a [ mid ] r et ur n f i nd ( a , s t ar t , mid1, x ) ;
i f ( x>a [ mid ] r et ur n f i nd ( a , mid+1, stop , x ) ;

Dajemo t e s t ni program za proceduru f i nd


i nt main ( )
f l o a t a [ ] =11. 1 , 2 2 . 2 , 3 3 . 3 , 4 4 . 4 , 5 5 . 5 , 6 6 . 6 , 7 7 . 7 , 8 8 . 8 ;
i nt k=f i nd ( a , 0 , 8 , 6 6 . 6 ) ;
cout <<k= <<k<<end ;
k=f i nd ( a , 0 , 8 , 5 0 ) ;
cout <<k= <<k<<end ;
(b) Iterativna procedura
templ ate <c l a s s T>
i nt f i nd ( constTa , i nt begi n , i nt end , cons t T & t ar ge t )
i nt Lo=begi n ; i nt hi=end1l
whi l e ( Lo<=hi )
i nt mid=(Lo+hi ( /2; // Naci s r edi nu .
i f ( a [ mid]==t ar ge t ) r et ur n mid ; //Nadjen !
i f ( a [ mid]>t ar ge t ) hi=mid1;// Trazi u l e vo j pol ovi ni .
e l s e Lo=mid+1l // Trazi u des noj pol ovi ni .

r et ur n end ;

Testni program bi se napravio slicno kao u slucaju a.


0.13 Efektivno mnozenje dugackih celih brojeva u vremenu O(n
1
.59)
Razmotrimo mnozenje dva n-bitna binarna broja. Tradicionalni metod treba T(n)=T(n
2
) operacija nad bitovima. U
metodu koji izlazemo dovoljno je T(n)=O(n
1
.59) operacija nad bitovima. Razbijemo x i y na dva jednaka dela kao na
slici.
Ako svaki od tih delova posmatramo kao
n
2
-cifreni, rada mozemo predstaviti mnozenje x i y u obliku xy =
(a2
n
2
+b)(c2
n
2
+d) = ac2
n
+ (ad +bc)2
n
2
+bd. Proizvod dakle mozemo izracunati pomocu programa

u<(a+b) ( c+d ) ;
v<ac ;
w<bd ;
z<v2n + ( uvw)2m/2 + w;

Prema formuli za slozenost programa imamo T(n) = 3T(


n
2
) +n, sto daje T(n)=O(n
1
.59).
0.14 Merge sort. Dizajn i analiza slozenosti
Razmotrimo niz celih brojeva x
1
, x
2
, . . . , x
n
. Radi prostijeg racuna pretpostavimo da je n stepen broja 2. Jedan od
nacina da sortiramo dati niz je da razbijemo dati niz na dva podniza x
1
, x
2
, . . . , x
n
2
i x
n
2
+1
, x
n
2
+2
, . . . , x
n
, sortiramo
svaki od njih i zatim ih merdzujemo(smesamo). Pod merdzovanjem mi podrazumevamo spajanje dva vec sortirana
podniza u jedan sortiran niz. Slozenost (worst-case):Prema podeli i vladaj imamo T(n)=2T(
n
2
)+n, pa je d=1, b=1,
c=2. Konacno log
c
b = log
2
2 = 1 = d = T(n)=O(nlogn). Dakle, merge sort je bolji od insert sorta, bubble sorta i
sorta izborom, ako nas interesuje worst-case.
Implementacija merge sorta u C++
//Merge s or t
templ ate <c l a s s T>
voi d merge (Ta , i nt n1 , i nt n2 )
Ttemp=new T[ n1+n2 ] ;
i nt i =0, j 1 =0, j 2 =0;
whi l e ( j 1>n1 && j 2<n2 )
temp [ i ++]=(a [ j 1]<=a [ n1+j 2 ] ? a [ j 1 ++]: a [ n1+j 2 ++] );
whi l e ( j 1<n1 )
temp [ i ++]=a [ j 1 ++];
whi l e ( j 2<n2 )
temp [ i ++]=(a+n1 ) [ j 2 ++];
f o r ( i =0; i <n1+n2 ; i ++)
a [ i ]=temp [ i ] ;
de l e t e [ ] temp ;

templ ate <c l a s s T>


voi d s or t (Ta , i nt n)
i f ( n>1)
i nt n1=n/2;
i nt n2=nn1 ;
s or t ( a , n1 ) ;
s or t ( a+n1 , n2 ) ;
merge ( a , n1 , n2 ) ;

0.15 Efektivno mnozenje matrica u vremenu O(n


2.81
)
Neka su A i B dve (nxn) matrice, pri cemu je n stepen broja 2. Svaku matricu A i B mozemo razbiti na cetiri matrice
i preko njih izraziti proizvod matrica A i B:
_
A
11
A
12
A
21
A
22
_ _
B
11
B
12
B
21
B
22
_
=
_
C
11
C
12
C
12
C
22
_
gde je
C
11
= A
11
B
11
+A
12
B
21
, C
12
= A
11
B
12
+A
12
B
22
, C
21
= A
21
B
11
+A
22
B
21
, C
22
= A
21
B
12
+A
22
B
22
Ako se C
ij
izracunava pomocu m mnozenja i a sabiranja/oduzimanja, tada rekurzivno primenjujuci gornji algoritam
dobijamo T(n) mT(
n
2
) +
a n
2
4
, n > 2, gde je n stepen dvojke. Obican metod mnozenja matrica ima slozenost
T(n)=O(n
3
). Nas rekurzivni metod ima 8 mnozenja(*) i 4 sabiranja(+), sto daje T(n) = 8T(
n
2
) +n
2
, i dalje log
c
b =
log
2
8 = 3 > d = 2 T(n) = O(n
loc
c
b
) = O(n
3
). Dakle, na ovaj nacin primene tehnike podeli i vladaj nismo ostvarili
napredak.
Strasen (Strassen W.) napravio je svojevremeno iznenadjenje kada je nasao metod mnozenja matrica nad proizvoljnim
prstenom u kojem je dovoljno sedam mnozenja, pa je poboljsao vremensku slozenost. Na pocetku je formirao proizvode
blokova matrica.
m
1
= (A
12
A
22
)(B
21
+B
22
)
m
2
= (A
11
+A
22
)(B
11
+B
22
)
m
3
= (A
11
A
21
)(B
11
+B
12
)
m
4
= (A
11
+A
12
)B
22
m
5
= A
11
(B
12
B
22
)
m
6
= A
22
(B
21
B
11
)
m
7
= (A
21
+A
22
)B
11
Zatim izracunamo
C
11
= m
1
+m
2
m
4
+m
6
,
C
12
= m
4
+m
5
,
C
21
= m
6
+m
7
,
C
22
= m
2
m
3
+m
5
m
7
.
Prema formuli iz Podeli i vladaj imamo: T(n) = 7T(
n
2
) +18n
2
, sto daje T(n) = O(n
l
og
2
7) = O(n
2
.81) sto je bolje
od klasicnog algoritma.
Napomena.
Neki pokusavaju popraviti algoritam tako sto startuju sa 3x3 matricama. Tada je T(n) = xT(
n
3
) +O(n
2
) i treba naci
x(tj. broj mnozenja) tako da bude log
3
x < 2.81.
0.16 Quick sort. Dizajn i analiza slozenosti.
Algoritam:
Izabrati slucajno(random) element deljenja niza.
Podeliti niz u podskupove manjih i vecih elemenata u odnosu na izabrani element.
Posebno sortirati podskup.
Nadovezati sortirane podskupove.
Worst case vreme izvodjenja:
U slucaju da u svakom koraku deljenja izaberemo maksimalan(minimalan) element, za niz od n elemenata imamo
T(n)=n+(n-1)+. . .+1=O(n
2
).
Best case vreme izvodjenja:
U slucaju da u svakom koraku izaberemo medium element, prema formuli iz Podeli i vladaj imamo T(n)=2T(
n
2
) +n
sto daje T(n)=O(nlogn).
Awerage case analiza:
T(n) c n +

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

n1
i=0
T(i), c n je vreme podele za n elemenata.
Mi zelimo dokazati ogranicenje T(n) knlogn. T(n) cn+
2
n
n1

i=0
ilogi cn+
2k
n
,
n
2
logn
2

n
2
4
| knlogn+cn
k
2
n Za
k=2c imamo T(n) knlogn. Ocena je postignuta koristeci induktivnu hipotezu T(i) ilogi za i<n, te sledeci kvaziar-
gument
n1

i=0
ilogi =
_
n1
0+
xlogxdx =
x
2
2
logx [
n1
0

_
n1
0+
x
2
2
1
x
dx =
(n 1)
2
2
log(n 1)
x
2
4
[
n1
0
=
(n 1)
2
2
log(n
1)
(n 1)
2
4
//Quick s or t
templ ate <c l a s s T>
voi d qui c ks or t (Ta , i nt Lo , i nt hi )
i f ( Lo>=hi ) r et ur n ;
T pi vot = a [ hi ] ;
i nt i= Lo1l
i nt j=hi ;
whi l e ( i <j )
whi l e ( a[++i ]<pi vot )
whi l e ( j >=0 && a[j ]<pi vot ) ;
i f ( i <j ) swap ( a [ i ] , a [ j ] ) ;

swap( a [ i ] , a [ hi ] ) ;
// I nvar i j ant a : a [ j ]<=a [ i ]<=a [ k ] za Lo<=j <i <k<=hi //
qui c ks or t ( a , Lo , i 1);
qui c ks or t ( a , i +1, hi ) ;

templ ate <c l a s s T>


voi d s or t (Ta , i nt n)
qui c ks or t ( a , 0 , n1);

0.17 Nalazenje k-tog elementa u linearnom vremenu


Za izbotr k-tog po velicini elementa niza S primenjujemo sledeci algoritam Procedure izbor(k,s):
1. if [ 5 [< 50 then
2. urediti 5;
3. return k-ti najmanji element iz S ; else
4. Razbiti S na [ 5 [ /5| nizova po 5 elemenata u svakom nizu
5. pri cemu ce ostati najvise 4 neiskoristena elementa niza
6. urediti svaki petoelementni niz
7. neka je M niz medijana tih petoelementnih nizova
8. M=IZBOR(,[ M [ /2|)
9. S
1
, S
2
, S
3
- skupovi elemenata manjih, jednakih, vecih od m
10. if [ S
1
[ k then return IZBOR(k, S
1
); else
11. if [ S
1
[ + [ S
2
[ k) then return m; else
12. return IZBOR (k-[ S
1
[ [ S
2
[, S
3
)
0.18 Donje ogranicenje O(nlogn) za algoritme sortiranja poredjenjem u
opstem slucaju
Dokazujemo da je (nlogn) donje ogranicenje za vreme sortiranja n vrednosti, ako se koristi poredjenje, u opstem
slucaju. Slicno kao u primeru drveta odlucivanja za tri elementa a,b,c. Vidimo da i u opstem slucaju algoritam
sortiranja poredjenjem i u opstem slucaju moze biti opisan drvetom odlucivanja sa najmanje n! listova. Jasno je da je
1. Worst case vreme=visina dohvatljivog dela drveta. Svako drvo visine h moze imati najvise 2
h
listova. Za n!
listova visina mora biti veca ili jednaka log
2
n!. Posto je n! (
n
e
)
n
to je hlogn! n[log
2
n log
2
e]=O(nlogn)
2.
Teorema 0.2.. (nlogn) donja granica za sortiranje poredjenjem, primenljiva je i za awerage case kompleksnost.
Dokaz 0.3. Opsta denicija awerage case kompleksnosti je
A(n)=

|x|=n
(x)T(x). U opstem slucaju je
1
n!

|x|=n
T(x) i D(m)=minD(T) za sumu dubina listova bilo kojeg
drveta poredjenja sa m listova. Treba dokazati D(m)=nlogn.
Dokaz izvvodimo indukcijom. Za m=1 je trivijalno 0.
Za m>1:
Pretpostavimo da TR ima k listova, tako da je i listova u levom poddrvetu TR
i
i k-i listova u desnom poddrvetu
TR
ki
.
0.19 Dinamicko programiranje. Poredak mnozenja matrica.
Dynamic Programming
Dynamic programming, like the divide-and-conquer method, solves problems by combining the solutions to subprob-
lems. (Programming in this context refers to a tabular method, not to writing computer code.) As we saw in
Chapter 2, divide-and-conquer algorithms partition the problem into independent subproblems, solve the subproblems
recursively, and then combine their solutions to solve the original problem. In contrast, dynamic programming is ap-
plicable when the subproblems are not independent, that is, when subproblems share subsubproblems. In this context,
a divide-and-conquer algorithm does more work than necessary, repeatedly solving the common subsubproblems. A
dynamic-programming algorithm solves every subsubproblem just once and then saves its answer in a table, thereby
avoiding the work of recomputing the answer every time the subsubproblem is encountered.
Dynamic programming is typically applied to optimization problems. In such problems there can be many possible
solutions. Each solution has a value, and we wish to nd a solution with the optimal (minimum or maximum) value.
We call such a solution an optimal solution to the problem, as opposed to the optimal solution, since there may be
several solutions that achieve the optimal value.
The development of a dynamic-programming algorithm can be broken into a sequence of four steps.
Characterize the structure of an optimal solution.
Recursively dene the value of an optimal solution.
Compute the value of an optimal solution in a bottom-up fashion.
Construct an optimal solution from computed information.
Steps 1-3 form the basis of a dynamic-programming solution to a problem. Step 4 can be omitted if only the value of
an optimal solution is required. When we do perform step 4, we sometimes maintain additional information during
the computation in step 3 to ease the construction of an optimal solution.
The sections that follow use the dynamic-programming method to solve some optimization problems. Section 15.1
examines a problem in scheduling two automobile assembly lines, where after each station, the auto under construction
can stay on the same line or move to the other. Section 15.2 asks how we can multiply a chain of matrices so that
the fewest total scalar multiplications are performed. Given these examples of dynamic programming, Section 15.3
discusses two key characteristics that a problem must have for dynamic programming to be a viable solution technique.
Section 15.4 then shows how to nd the longest common subsequence of two sequences. Finally, Section 15.5 uses
dynamic programming to construct binary search trees that are optimal, given a known distribution of keys to be
looked up.
0.19.1 Matrix-chain multiplication
Our next example of dynamic programming is an algorithm that solves the problem of matrix-chain multiplication.
We are given a sequence (chain) A
1
, A
2
, ...,A
n
of n matrices to be multiplied, and we wish to compute the product
(15.10) We can evaluate the expression (15.10) using the standard algorithm for multiplying pairs of matrices as a
subroutine once we have parenthesized it to resolve all ambiguities in how the matrices are multiplied together. A
product of matrices is fully parenthesized if it is either a single matrix or the product of two fully parenthesized
matrix products, surrounded by parentheses. Matrix multiplication is associative, and so all parenthesizations yield
the same product. For example, if the chain of matrices is A
1
, A
2
, A
3
, A
4
, the product A
1
A
2
A
3
A
4
can be fully
parenthesized in ve distinct ways: (A
1
(A
2
(A
3
A
4
)))
(A
1
((A
2
A
3
)A
4
))
((A
1
A
2
)(A
3
A
4
))
((A
1
(A
2
A
3
))A
4
)
(((A
1
A
2
)A
3
)A
4
). The way we parenthesize a chain of matrices can have a dramatic impact on the cost of evaluating the
product. Consider rst the cost of multiplying two matrices. The standard algorithm is given by the following pseu-
docode. The attributes rows and columns are the numbers of rows and columns in a matrix. MATRIX-MULTIPLY(A,
B)
1 i f columns [ A] neq rows [ B]
2 then e r r or i ncompat i bl e di mensi ons
3 e l s e f o r i < 1 to rows [ A]
4 do f or j < 1 to columns [ B]
5 do C[ i , j ] < 0
6 f o r k < 1 to columns [ A]
7 do C[ i , j ] < C[ i , j ] + A[ i , k ] B[ k , j ]
8 r et ur n C
We can multiply two matrices A and B only if they are compatible: the number of columns of A must equal the
number of rows of B. If A is a p x q matrix and B is a q x r matrix, the resulting matrix C is a p x r matrix. The time
to compute C is dominated by the number of scalar multiplications in line 7, which is pqr. In what follows, we shall
express costs in terms of the number of scalar multiplications. To illustrate the dierent costs incurred by dierent
parenthesizations of a matrix product, consider the problem of a chain A
1
, A
2
, A
3
of three matrices. Suppose
that the dimensions of the matrices are 10 x 100, 100 x 5, and 5 x 50, respectively. If we multiply according to the
parenthesization ((A
1
A
2
)A
3
), we perform 10100 5 = 5000 scalar multiplications to compute the 10 x 5 matrix product
A
1
A
2
, plus another 10 5 50 = 2500 scalar multiplications to multiply this matrix by A
3
, for a total of 7500 scalar
multiplications. If instead we multiply according to the parenthesization (A
1
(A
2
A
3
)), we perform 100 5 50 = 25, 000
scalar multiplications to compute the 100 x 50 matrix product A
2
A
3
, plus another 10 100 50 = 50, 000 scalar
multiplications to multiply A
1
by this matrix, for a total of 75,000 scalar multiplications. Thus, computing the
product according to the rst parenthesization is 10 times faster. The matrix-chain multiplication problem can be
stated as follows: given a chain A
1
, A
2
, ..., A
n
of n matrices, where for i = 1, 2, ..., n, matrix A
i
has dimension p
i1
xp
i
, fully parenthesize the product A
1
A
2
A
n
in a way that minimizes the number of scalar multiplications.
0.19.2 Counting the number of parenthesizations
Before solving the matrix-chain multiplication problem by dynamic programming, let us convince ourselves that
exhaustively checking all possible parenthesizations does not yield an ecient algorithm. Denote the number of
alternative parenthesizations of a sequence of n matrices by P(n). When n = 1, there is just one matrix and therefore
only one way to fully parenthesize the matrix product. When n 2, a fully parenthesized matrix product is the
product of two fully parenthesized matrix subproducts, and the split between the two subproducts may occur between
the kth and (k + 1)st matrices for any k = 1, 2, ..., n - 1. Thus, we obtain the recurrence Problem 12-4 asked you
to show that the solution to a similar recurrence is the sequence of Catalan numbers The number of solutions is thus
exponential in n, and the brute-force method of exhaustive search is therefore a poor strategy for determining the
optimal parenthesization of a matrix chain.
0.19.3 The structure of an optimal parenthesization
Our rst step in the dynamic-programming paradigm is to nd the optimal substructure and then use it to construct an
optimal solution to the problem from optimal solutions to subproblems. For the matrix-chain multiplication problem,
we can perform this step as follows. For convenience, let us adopt the notation A
i..j
, where i j, for the matrix
that results from evaluating the product A
i
A
i+1
A
j
. Observe that if the problem is nontrivial, i.e., i j, then any
parenthesization of the product A
i
A
i+1
A
j
must split the product between A
k
and A
k+1
for some integer k in the
range i k j. That is, for some value of k, we rst compute the matrices A
i...k
and A
k+1...n
and then multiply them
together to produce the nal product A
i..j
. The cost of this parenthesization is thus the cost of computing the matrix
A
i..k
, plus the cost of computing A
k+1..n
, plus the cost of multiplying them together. The optimal substructure of
this problem is as follows. Suppose that an optimal parenthesization of A
i
A
i+1
A
j
splits the product between A
k
and A
k+1
. Then the parenthesization of the prex subchain A
i
A
i+1
A
k
within this optimal parenthesization of
A
i
A
i+1
A
j
must be an optimal parenthesization of A
i
A
i+1
A
k
. Why? If there were a less costly way to parenthesize
A
i
A
i+1
A
k
, substituting that parenthesization in the optimal parenthesization of A
i
A
i+1
A
j
would produce another
parenthesization of A
i
A
i+1
A
j
whose cost was lower than the optimum: a contradiction. A similar observation holds
for the parenthesization of the subchain A
k+1
A
k+2
A
j
in the optimal parenthesization of A
i
A
i+1
A
j
: it must be an
optimal parenthesization of A
k+1
A
k+2
A
j
. Now we use our optimal substructure to show that we can construct an
optimal solution to the problem from optimal solutions to subproblems. We have seen that any solution to a nontrivial
instance of the matrix-chain multiplication problem requires us to split the product, and that any optimal solution
contains within it optimal solutions to subproblem instances. Thus, we can build an optimal solution to an instance
of the matrix-chain multiplication problem by splitting the problem into two subproblems (optimally parenthesizing
A
i
A
i+1
A
k
andA
k+1
A
k+2
A
j
), nding optimal solutions to subproblem instances, and then combining these optimal
subproblem solutions. We must ensure that when we search for the correct place to split the product, we have
considered all possible places so that we are sure of having examined the optimal one.
0.19.4 A recursive solution
Next, we dene the cost of an optimal solution recursively in terms of the optimal solutions to subproblems. For the
matrix-chain multiplication problem, we pick as our subproblems the problems of determining the minimum cost of a
parenthesization of A
i
A
i+1
A
j
for 1 i j n. Let m,i, j| be the minimum number of scalar multiplications needed
to compute the matrix A
i...j
; for the full problem, the cost of a cheapest way to compute A
1..n
would thus be m,1, n|.
We can dene m ,i, j| recursively as follows. If i = j, the problem is trivial; the chain consists of just one matrix A
i..i
= A
i
, so that no scalar multiplications are necessary to compute the product. Thus, m[i, i] = 0 for i = 1, 2, ..., n.
To compute m,i, j| when i j, we take advantage of the structure of an optimal solution from step 1. Let us assume
that the optimal parenthesization splits the product A
i
A
i+1
A
j
between A
k
and A
k+1
, where i k j. Then, m,i, j|
is equal to the minimum cost for computing the subproducts A
i...k
and A
k+1...j
, plus the cost of multiplying these two
matrices together. Recalling that each matrix A
i
is p
i1
xp
i
, we see that computing the matrix product A
i..k
A
k+1..j
takes p
i1
p
k
p
j
scalar multiplications. Thus, we obtain m,i, j| = m,i, k| + m,k + 1, j| + p
i1
p
k
p
j
. This recursive
equation assumes that we know the value of k, which we do not. There are only j - i possible values for k, however,
namely k = i, i + 1, ..., j - 1. Since the optimal parenthesization must use one of these values for k, we need only
check them all to nd the best. Thus, our recursive denition for the minimum cost of parenthesizing the product
A
i
A
i+1
A
j
becomes (15.12)
m,i, j| =
_
0, if i = j
min
ik<j
m,i, k| +m,k + 1, j| +p
i1
p
j
p
k
, if i < j
The m,i, j| values give the costs of optimal solutions to subproblems. To help us keep track of how to construct
an optimal solution, let us dene s,i, j| to be a value of k at which we can split the product A
i
A
i+1
A
j
to obtain an
optimal parenthesization. That is, s,i, j| equals a value k such that m,i, j| = m,i, k| + m,k + 1, j| + p
i1
p
k
p
j
.
0.19.5 Computing the optimal costs
At this point, it is a simple matter to write a recursive algorithm based on recurrence (15.12) to compute the minimum
cost m[1, n] for multiplying A
1
A
2
A
n
. As we shall see in Section 15.3, however, this algorithm takes exponential time,
which is no better than the brute-force method of checking each way of parenthesizing the product. The important
observation that we can make at this point is that we have relatively few subproblems: one problem for each choice of i
and j satisfying 1 i j n, or in all. A recursive algorithm may encounter each subproblem many times in dierent
branches of its recursion tree. This property of overlapping subproblems is the second hallmark of the applicability of
dynamic programming (the rst hallmark being optimal substructure). Instead of computing the solution to recurrence
(15.12) recursively, we perform the third step of the dynamic-programming paradigm and compute the optimal cost
by using a tabular, bottom-up approach. The following pseudocode assumes that matrix Ai has dimensions p
i1
xp
i
for i = 1, 2, ..., n. The input is a sequence p = p
0
, p
1
, ..., p
n
, where length,p| = n + 1. The procedure uses an
auxiliary table m,1...n, 1...n| for storing the m,i, j| costs and an auxiliary table s,1...n, 1...n| that records which
index of k achieved the optimal cost in computing m,i, j|. We will use the table s to construct an optimal solution.
MATRIX-CHAIN-ORDER(p)
1 n < l engt h [ p ] 1
2 f o r i < 1 to n
3 do m[ i , i ] < 0
4 f o r l < 2 to n
5 do f or i < 1 to n l + 1
6 do j < i + l 1
7 m[ i , j ] < i nf t y
8 f o r k < i to j 1
9 do q < m[ i , k ] + m[ k + 1 , j ] + p i 1 p kp j
10 i f q < m[ i , j ]
11 then m[ i , j ] < q
12 s [ i , j ] < k
13 r et ur n m and s
The algorithm rst computes m,i, i| 0 for i = 1, 2, ..., n (the minimum costs for chains of length 1) in lines 2-3.
It then uses recurrence (15.12) to compute m[i, i + 1] for i = 1, 2, ..., n - 1 (the minimum costs for chains of length
l = 2) during the rst execution of the loop in lines 4-12. The second time through the loop, it computes m[i, i +
2] for i = 1, 2, ..., n - 2 (the minimum costs for chains of length l = 3), and so forth. At each step, the m[i, j] cost
computed in lines 9-12 depends only on table entries m[i, k] and m[k + 1, j] already computed. Figure 15.3 illustrates
this procedure on a chain of n = 6 matrices. Since we have dened m,i, j| only for i j, only the portion of the
table m strictly above the main diagonal is used. The gure shows the table rotated to make the main diagonal run
horizontally. The matrix chain is listed along the bottom. Using this layout, the minimum cost m[i, j] for multiplying
a subchain A
i
A
i+1
A
j
of matrices can be found at the intersection of lines running northeast from A
i
and northwest
from A
j
. Each horizontal row in the table contains the entries for matrix chains of the same length.
MATRIX-CHAIN-ORDER computes the rows from bottom to top and from left to right within each row. An
entry m,i, j| is computed using the products p
i1
p
k
p
j
for k = i, i + 1, ..., j - 1 and all entries southwest and southeast
from m[i, j].
Figure 15.3: The m and s tables computed by MATRIX-CHAIN-ORDER for n = 6 and the
following matrix dimensions:
matrix dimension
A1 30 35
A2 35 15
A3 15 5
A4 5 10
A5 10 20
A6 20 25
The tables are rotated so that the main diagonal runs horizontally. Only the main diagonal and upper triangle are
used in the m table, and only the upper triangle is used in the s table. The minimum number of scalar multiplications
to multiply the 6 matrices is m,1, 6| = 15,125. Of the darker entries, the pairs that have the same shading are taken
together in line 9 when computing
A simple inspection of the nested loop structure of MATRIX-CHAIN-ORDER yields a running time of O(n
3
) for
the algorithm. The loops are nested three deep, and each loop index (l, i, and k) takes on at most n -1 values. Exercise
15.2-4 asks you to show that the running time of this algorithm is in fact also (n
3
). The algorithm requires (n
2
)
space to store the m and s tables. Thus, MATRIX-CHAIN-ORDER is much more ecient than the exponential-time
method of enumerating all possible parenthesizations and checking each one.
0.19.6 Constructing an optimal solution
Although MATRIX-CHAIN-ORDER determines the optimal number of scalar multiplications needed to compute a
matrix-chain product, it does not directly show how to multiply the matrices. It is not dicult to construct an optimal
solution from the computed information stored in the table s ,1...n, 1...n|. Each entry s ,i, j| records the value of k
such that the optimal parenthesization of A
i
A
i+1
...A
j
splits the product between A
k
and A
k+1
. Thus, we know that
the nal matrix multiplication in computing A
1..n
optimally is A
1..s[1,n]
A
s[1,n]+1..n
. The earlier matrix multiplications
can be computed recursively, since s,1, s,1, n|| determines the last matrix multiplication in computing A
1..s[1,n]
, and
s ,s,1, n| + 1, n| determines the last matrix multiplication in computing A
s[1,n]+1..n
.
The following recursive procedure prints an optimal parenthesization of A
i
, A
i+1
, ..., A
j
, given the s table computed
by MATRIX-CHAIN-ORDER and the indices i and j. The initial call is MATRIX-CHAIN-ORDER (A, s, 1, n).
MATRIXCHAINORDER (A, s , 1 , n)
1 i f i < j
2 then X < MATRIXCHAINORDER (A, s , i , s [ i , j ] )
3 then Y < MATRIXCHAINORDER (A, s , s [ i , j ] + 1 , j )
4 r et ur n MATRIX MULTIPLY (X, Y)
5 e l s e r et ur n Ai
In the example of Figure 15.3, the call MATRIX-CHAIN-MULTIPLY (A, s, 1, 6) computes the matrix-chain product
according to the parenthesization ((A
1
(A
2
A
3
))((A
4
A
5
)A
6
)).
0.19.7 Exercises
Exercises 15.2-1
Find an optimal parenthesization of a matrix-chain product whose sequence of dimensions is 5, 10, 3, 12, 5, 50, 6.
Exercises 15.2-2
Give a recursive algorithm MATRIX-CHAIN-MULTIPLY(A, s, i, j) that actually performs the optimal matrix-chain
multiplication, given the sequence of matrices A
1
, A
2
, ..., A
n
, the s table computed by MATRIX-CHAIN-ORDER,
and the indices i and j. (The initial call would be MATRIX-CHAIN-MULTIPLY(A, s, 1, n))
Exercises 15.2-3
Show that a full parenthesization of an n-element expression has exactly n - 1 pairs of parentheses.
subsectionOsobine najduzeg zajednickog podniza Algoritam grube sile. Numerisati sve odnizove niza X i probati
koji je od njih najduzi i zajednici sa Y podnizom. Postoji 2
m
podnizova od X, pa algoritam zahteva eksponencijalno
vreme sto ga cini nepakticnim. Denisemo i-ti preks od X, i=0,1,...,m kao X
i
= x
1
, x
2
, ..., x
i
. Na primer: X =
A, B, C, B, D, A, B je X
4
= A, B, C, D.
Teorema 0.3.. Neka je X
i
= x
1
, x
2
, ..., x
m
i Y
i
= y
1
, y
2
, ..., y
n
i neka je Z
i
= z
1
, z
2
, ..., z
k
LCS za X i Y.
1. Ako je x
m
= y
n
tada je z
k
= x
m
= y
n
i z
k1
= LCS(x
m1
, y
n1
)
2. Ako je x
m
,= y
n
tada iz z
k
,= x
m
sledi da je z = LCS(x
m1
, y)
3. Ako je x
m
,= y
n
tada iz z
k
,= y
n
sledi da je z = LCS(x, y
n1
)
Dokaz 0.4. 1. Ako je z
k
,= x
m
, tada mozemo dodati y
n
= x
m
na Z i dobiti zajednicki podniz X i Y duzine k+1, sto
je suprotno pretpostavci x
m
= y
n
= z
k
. Pretpostavka z
k1
,= LCS(x
n1
, y
m1
) . Lako dovodi do kontradikcije.
2. Ako je z
k
,= x
m
, tada je Z zajednicki podniz od X
m1
i Y. Ako bi postojao zajednicki podniz X
m1
i Y sa
duzinom vecom od k, tada bi taj podniz W bio zajednicki podniz X
m
i Y, sto je suprotno pretpostavci.
3. Simetricno dokazu 2.
0.19.8 Najduzi zajednicki podniz
X = x
1
, x
2
, ..., x
m
; Z = z
1
, z
2
, ..., z
k
je podniz niza X ako postoji strogo rastuci niz i
1
, i
2
, ..., i
l
indeksa X, tako
da je za svako j=1,2,...,l u vaznosti x
ij
= z
j
.
Primer 0.4. X = A, B, C, B, D, A, B; Z = B, C, D, B je podniz niza X sa odgovarajucim indeksima 2, 3, 5, 7.
Za dva niza X i Y niz Z je zajednicki podniz, ako je Z podniz od oba X i Y.
Primer 0.5. X = A, B, C, B, D, A, B, Y = B, D, C, A, B, A, niz Z = B, C, A je podniz i X i Y. B, C, A nije
najduzi zajednicki podniz, jer je niz B, C, B, A zajednicki i ima duzinu 4. Pri tome je B, C, B, A najduzi zajednicki
podniz X i Y, jer ne postoji zajednicki podniz duzine 5 ili vise.
LCS problem. Dati su nizovi X = x
1
, x
2
, ..., x
m
i Y = y
1
, y
2
, ..., y
n
. Naci najduzi zajednicki podniz Z nizova
X i Y. (Longest Common Subsequence problem)
Rekurzivno resenje problema
Cena je denisana kao duzina LCS od X
i
iY
j
: c,i, j| =
_
_
_
0, za i = 0 ili j = 0
c,i 1, j 1| + 1, za i, j > 0, X
i
= Y
j
max(c,i, j 1|, c,i 1, j|, i, j > 0, X
i
,= Y
i
)
Racunanje duzine LCS
LCS LENGTH ( x , y)
m < l engt h [ x ]
n < l engt h [ y ]
f o r i < 1 to m
do c [ i , 0 ] <0
f o r i <1 to m
do f or j <1 to n
do i f xi = yj
then c [ i , j ] <c [ i 1, j 1]+1
b [ i , j ] < <
e l s e i f c [ i 1, j ]>=c [ i , j 1]
then c [ i , j ] < c [ i 1, j ]
b [ i , j ] < <
e l s e c [ i , j ] < c [ i , j 1]
b [ i , j ] <<
r et ur n c and b
end l s t i l i s t i n g
s ubs ubs ect i on Kons t r ukci j a LCS
begi n l s t l i s t i n g
PRINTLCS( b , X, i , j )
i f i =0 or j =0
then r et ur n
i f b [ i , j ]=<
then PRINTLCS( b , X, i 1, j 1)
pr i nt Xi
e l s e i f b [ i , j ]=<
then PRINTLCS( b , X, i 1, j )
e l s e PRINTLCS ( b , X, i , j 1)
Optimalna triangulacija poligona
Dat je konveksan poligon P = v
0
, v
1
, ..., v
n1
i tezinska funkcija w denisana na trouglovima formiranim stranama i
tetivama P. Problem je naci triangulaciju koja minimizira tezinu trouglova u triangulaciji. Primer tezine. (v
i
v
j
v
k
) =[
v
i
v
j
[ + [ v
j
v
k
[ + [ v
k
v
i
[, gde je [ v
i
v
j
[ Euklidovo rastojanje tacaka v
i
i v
j
.
Korespodencija sa postavljanjem zagrada
Struktura resenja
Triangulacija podpoligona mora biti optimalna, inace, mogli bismo poboljsati globalnu strukturu(triangulaciju). Jedna
optimalna triangulacija P u odnosu na tezinsku funkciju daje parsing drvo za optimalno razmestanje zagrada pri
mnozenju matrice A
1
A
2
...A
n
. Obrnuto nije tacno.
Rekurzivno resenje
y =
_
0, ako je i = j
mint[i, k] +t[k + 1, j] +(v
i1
v
k
v
j
), zai < j, i k j 1
Optimalno binarno drvo za pretrazivanje
Ulaz: lista reci sa ksnim verovatnocama pojavljivanja p
1
, p
2
, ..., p
n
. Problem: Aranzirati ove reci u binarno drvo
pretrazivanja tako da MINIMIZIRAMO ocekivano vreme pretrazivanja. Posto je broj poredjenja do pristupa elemntu
na dubini d jednak d+1, treba minimizirati

i=1
np
i
(1 +d
i
).
rec w
i
verovatnoca p
i
broj niz broj niz broj niz
a 0.22 2 0.44 3 0.66 2 0.44
am 0.18 4 0.72 2 0.36 3 0.54
and 0.20 3 0.60 3 0.60 1 0.20
egg 0.05 4 0.20 1 0.05 3 0.15
if 0.25 1 0.25 3 0.75 2 0.50
the 0.02 3 0.06 2 0.04 4 0.08
two 0.08 2 0.16 3 0.24 3 0.24
1.00 2.43 2.70 2.15
C
left,right
= minp
i
+C
left,i1
+C
i+1,right
+
i1

j=left
p
j
+
right

j=i+1
p
i
= minC
left,i1
+C
i+1,right
+
right

j=left
p
j

0.19.9 Dijkstra algoritam. Najkraci put medju svim parovima vrhova grafa
D
k,i,j
= minD
k1,i,j
+D
k1,i,k
+D
k1,k,j

D
0,i,j
= c
ij
(v
i
, v
j
) / Grane D
ij
= +
D
|v|,i,j
je najkraci put izmedju v
i
i v
j
.
D
k,i,j
je najrkaci put izmedju v
i
i v
j
koji koristi samo vrhove v
1
, v
2
, ..., v
k
.
0.20 Minimizacija vremena cekanja procesa na jednom ili vise procesora.
Greedy (nezasiti) algoritmi.
Postupak: Neki lokalni optimum je izabran i kada se algoritam zavrsi ocekujemo da je lokalni optimum jednak
globalnom optimumu. Ako apsolutno najbolji odgovor nije zahtevan, tada se greedy algoritam koristi za generisanje
pribliznog odgovora. U slucaju da se trazi tacan odgovor, moramo koristiti komplikovanije algoritme. Svakodnevni
primeri:
1. Razmena banknote.
2. Trac jam: da li uci u ulicu u kojoj vas mozda nakon kilometar cekuje zacepljenje ili se vratiti 5km nazad da
bi se izbeglo zacepljenje.
3. Pravljenje rasporeda procesa na jednom ili vise procesora razmatramo detaljnije. U principu su problemi pravl-
jenja rasporeda NP-kompletni.
Dati su poslovi p
1
, p
2
, ..., p
n
, koji se zavrsavaju za vreme t
1
, t
2
, ..., t
n
respektivne.Imamo jedan procesor. Koji je
najbolji nacin da se rasproede ovi poslovi tako da je srednje vreme cekanja minimalno?
posao vreme
p1 15
p2 8
p3 3
p4 10
Prosecno vreme t
sr
=
15 + 23 + 26 + 36
4
= 25
Prosecno vreme t
sr
=
3 + 11 + 21 + 36
4
= 17.75 optimalno.
Resenje problema. Aranziranje po najkracim vremenima cekanja uvek daje oprimalno resenje.
Dokaz 0.5. Raspored p
i1
, p
i2
, ..., p
in
. Prvi posao zavrsava u vremenu t
i1
. Drugi posao zavrsava u vremenu t
i1
+ t
i2
,
treci t
i1
+t
i2
+t
i3
,...
C =
n

k=1
(nk +1)t
ik
= (n+1)
n

k=1
t
ik

k=1
kt
ik
Ako je stavljeno x iza y uz t
ix
< t
iy
, tada razmenom x i y smanjujemo
totalno vreme cekanja. Zbog toga je svaki raspored po rastucim vremenima SUBOPTIMALAN.
Vise procesora Slicno kao u slucaju jednog procesora dokazujemo da se optimalna cena postize ako prvom pro-
cesoru damo proces sa najmanjim vremenom cekanja, drugom procesoru proces sa najmanjim vremenom cekanja u
preostalim procesima, i tako ciklicno dok ne iscrpimo sve procese.
posao vreme
p1 3
p2 5
p3 6
p4 10
p5 11
p6 14
p7 15
p8 18
p9 20
Minimizacija konacnog vremena zavrsavanja Kada ce i poslednji proces zavrsiti? U primerima a i c vreme
zavrsavanja je i 40 i 38 respektivno. Ovaj problem ekvivalentan je problemu pakovanja ranca, pa je prema tome
NP-kompletan(tj. problem minimizacije konacnog vremena). U slucaju b minimalnog vremena izvrsavanja ne moze
biti poboljsan, jer su svi procesori uvek zauzeti.
0.21 Human-ovi kodovi. Human-ov algoritam.
Skup ASCII sastoji se od 100 printabilnih karaktera. ,log
2
100| = 7, pa je potrebno 7 bita za reprezentaciju. Posto je
2
7
=128, imamo i neke neprintabilne karaktere. Osmi bit je dodat za kontrolu parnosti.
Primer 0.6. Datoteka sadrzi a,e,i,s,t,space,new line.
Karakter Kod Frekvencija Broj bitova
a 000 10 30
e 001 15 45
i 010 12 36
s 011 3 9
t 100 4 12
space 101 3 39
new line 110 1 3
total 174
Problem Zainteresovani smo za redukovanje duzine datoteke zbog prenosa telefonskom linijom ili zbog smanjenja
velicine prostora za zapis datoteke na disku. Je li moguce uvesti novi kod i tako smanjiti duzinu datoteke i ukupan
broj potrebnih bita? Odgovor Da! To je moguce i mozemo ustedeti i 25 odsto, a na velikim datotetkama i do 50 -
60 odsto prostora.
Opsta strategija je da se dozvoli da duzina koda varira od karaktera do karaktera i omoguciti da karakteri sa visokim
frekvencijom imaju kraci kod. Ako nam se svi karakteri pojavljuju sa istom frekvencijom, tada verovatno necemo
imati velike ustede.
Predstavljanje koda drvetom
Grana levo znaci 0, a desno znaci 1. Npr. 010 predstavlja i. Cena koja je

d
i
f
i
, gde karakter c
i
ima dubinu d
i
i frekvenciju d
i
. Jeftiniji je donji kod na slici. Kod kod kojeg su vrednosti samo u listovima naziva se PREFIKSNI
KOD.
Zadatak. Izracunati cenu kodova u gornja dva drveta.
Primedba Optimalan kod je predstavljen potpunim drvetom, inace jednog potomka mozemo dici na visi nivo i tako
smanjiti cenu.
Ako su znaci samo na listovima drveta, tada svaka sekvenca moze biti kodirana na jedinstven nacin. Npr, pret-
postavimo da je kodirani string 0100111100010110001000111, sledi da 0 nije znak, 01 nije nak, ali 010 predstavlja i,
pa je prvi karakter i. Tada je 011 s, 11 je nl, a zatim a,sp,t,i,e,nl. Nijedan od znakova nije preks nekog drugog koda
znaka. Ako se karakteri pojavljuju i u cvorovima, tada dekodiranje nije jednoznacno.
Nas problem se svodi na nalazenje KOMPLETNOG BINARNOG DRVETA SA MINIMALNOM TOTALNOM
CENOM, pri cemu se svi znakovi nalaze na listovima.
Optimalan preksni kod
Karakter Kod Frekvencija Broj bitova
a 001 10 30
e 01 15 30
i 10 12 24
s 00000 3 15
t 0001 4 16
space 11 13 26
new line 00001 1 5
total 146
Razmenom dece u drvetu, mozemo dobiti razlicite optimalne kodove.
Human-ov algoritam Neka je C broj razlicitih znakova. Svaki znak predstavljamo drvetom i razmatramo
SUMU drveta. Tezina drveta jednaka je zbiru frekvencija njegovih listova. C-1 puta izaberemo dva drveta T1 i T2
sa najmanjom tezinom ( u slucaju jednakih tezina uzimamo proizvoljno) i formiramo novo drvo sa poddrvetima T1 i
T2. Inicijalno (ulaz) je C suma od drveta sa jednim cvorom za svaki znak. Na kraju (izlaz) postoji jedinstveno drvo i
to je OPTIMALNO HUFFMAN-ovo drvo kodiranja.
Ideje za dokaz korektnosti Human-ovog algoritma:
1. Drvo mora biti potpuno, inace mozemo jedan list podici na nivo za jedan visi i smanjiti cenu.
2. Dva najmanje frekventna karaktera i moraju biti najdublji listovi. Dokaz kontradikcijom: Ako i nisu
najdublji listovi, tada to mora biti neko , jer je drvo kompletno. Swaping sai smanjuje cenu drveta!
3. Dva lista iste duvine mogu zameniti mesta ne narusavajuci optimalnost.
4. Inicijalni korak je dobar.
5. Indukcija kod spajanja drveta. Dati detalje!
Pitanje. Zasto je ovaj algoritam hill climbing (greedy)?
Odgovor. U svakoj fazi mi izvodimo merge lokalno, bez obzira na globalno stanje.
Pitanje. Oceniti slozenost algoritma.
Odgovor.
1. Ako drveta drzimo na heap-u (priority queue) tada je T(c)=O(clogC), jer imamo izgradnju heap-a, 2c-2 brisanja
min i c-2 inserta.
2. Linked list priority queue daje T(c)=O(c
2
). Posto je u ASCII kodu C malo, kvadratna ocena je prihvatljiva.
Napomene.
1. Kodirana informacija mora biti transformisana na pocetak datoteke, inace je necemo moci dekodirat. To je slavo
i skupo za male fajlove.
2. Algoritam ima dva prolaza. Prvi prolaz utvrdjuje frekvenciju podataka, a drugi kodira. Dvoprolaznost je skupa
za velike fajlove.
0.22 Pravljenje rasporeda: minimizacija konacnog vremena cekanja. Prob-
lem pakovanja ranca.
Neka su dati poslovi p
1
, p
2
, ..., p
n
sa vremenima izvrsavanja t
1
, t
2
, ..., t
n
retrospektivno. Treba naci raspored izvrsa-
vanja poslova koji ce minimizirati neku zadatu funkciju. U Minimizacija vremena cekanja procesa na jednom ili vise
procesora. Greedy (nezasiti) algoritmi. razmotrili smo i resili problem rasporeda za jednostavan problem minimizacije
prosecnog vremena cekanja.
U problemu minimizacije KONACNOG VREMENA IZVRSAVANJA trazi se raspored u kome ce vreme izvrsavanja i
poslednjeg procesa biti minimalno(optimalno). Mada je po formulaciji poslednji problem slican prethodnom, pokazuje
se da je on zapravo mnogo tezi. Ovaj problem je NP-kompletan jer je ekvivalentan problemu pakovanja ranca. U
Minimizacija vremena cekanja procesa na jednom ili vise procesora. Greedy (nezasiti) algoritmi dali smo ilustraciju
problema optimizacije konacnog vremena izvrsavanja za jedan specijalni slucaj.
NAPOMINJEMO da mi razmatramo NONPREEMPTIVNE RASPOREDE, tj. ako je neki posao pocet, tada se
on izvrsava do kraja i to bez prekida. Umesto problema pakovanja ranca mi razmatramo ekvivalentan problem
pakovanja u bin-ove (kutije,korpe). Dacemo Greedy(nezasicen) resenje problema pakovanja u bin-ove. Greedy
algoritmi su brzi, ali ne daju uvek optimalno resenje. Dokazujemo da nasa resenja nisu daleko od optimalnih.
Dato je n komada kapaciteta s
1
, s
2
, ..., s
n
. Svi komadi zadovoljavaju 0 < s
i
< 1. PROBLEM PAKOVANJA U
BINOVE je problem pakovanja svih komada u sto manji broj kutija(binova) kapaciteta 1.
Primer 0.7. s
1
= 0.2, s
2
= 0.5, s
3
= 0.4, s
4
= 0.7, s
5
= 0.1, s
6
= 0.3, s
7
= 0.8
0.8
0.2
0.3
0.7
0.5
0.1
0.4
Razlikujemo on-line i o-line algoritme. ON-LINE problem trazi da svaki komad mora biti ubacen u kutiju pre
nego sto sledeci komad bude razmotren. U OFF-LINE problemima ne moramo raditi nista pre nego sto svi komadi
budu ucitani.
0.23 ON-LINE algoritmi : primer pakovanja u binove.
Pokazujemo da ON-LINE algoritmi pakovanja u binove ne moze uvek dati odgovor koji je optimalan. Cak ako
mu dozvolimo neograniceno racunanje, on-line algoritam mora smestiti komad pre nego sto razmotri sledeci komad.
Situaciju ilustrujemo sledecim primerom :
Primer 0.8. Neka su I
1
= (i
1
[[i
1
[ =
1
2
) , [I
1
[ = m i I
2
= (i
2
[[i
2
[ =
1
2
+ ) , [I
2
[ = m, 0 < < 0.01. Neka je
I = I
1
I
2
, gdje je operacija konkatenacije (dopisivanja)nizova.
1. Pretpostavimo da postoji optimalan algoritam A koji pakuje niz I optimalna u m kutija, tako da jedan bin
izgleda kao na slici.
1
2
+
1
2

2. Neka je J = I
1
. Niz J moze biti upakovan u [
m
2
] kutija, ali ce sa optimalnim algoritmom A pakovati isto ako i
pre niz I, dakle u m kutija.
Iz (1) i (2) sledi da ne postoji optimalan on-line algoritam za pakovanje u binove.
Dajemo sledecu kvantitativnu ocjenu.
Teorema 0.5.. Postoji ulaz koji forsira on-line algoritam pakovanja u binove da koristi najmanje
4
3
od optimalnog
broja binova.
Dokaz 0.6. Neka je M2N, a niz I kao u primeru 1. Pretpostavimo suprotno.
1. Nakon m komada A koristi b binova,a optimalno je
m
2
.
Na osnovu pretpostavke slijedi
2b
<
4
3
i odatle 6b > 4m.
2. Nakon 2m komada svi su komadi upakovani. Svi binovi nakon b-tog sadrze najvise jedan komad, jer su svi
1
2

komadi upakovani u b-binova.
Trebamo 2mb binova vise
2mb
m
<
4
3
6b > 4m. Zakljuci pod (1) i (2) su u kontradikciji i to dokazuje
tvrdnju.
POSTOJE TRI JEDNOSTAVNA ZA IMPLEMENTACIJU ALGORITMA KOJI GARANTUJU NE VISE OD
2 (OPTIMALANBROJBINOV A) : NEXT FIT, FIRST FIT, BEST FIT. Razmotrimo ih u sledecim
pitanjima.
0.24 Next t pakovanje
NEXT FIT (SLEDECI ODGOVARAJUCI)
Algoritam: Komad se stavlja u istu kutiju kao i prethodni, a ako to nije moguce stavlja se u novoformiranu kutiju.
Teorema 0.6.. Neka je m optimalan broj kutija potrebnih ya pakovanje niza komada
Dokaz 0.7. B
j
i B
j+1
sadrze komade sa zbirom vecim od 1-inace bi svi komadi iz njih stali u jedan bin. Primijenjeno
na sve parove susjednih binova daje dokaz, jer najvise pola prostora moze biti izgubljeno (nepopunjeno).
Primer 0.9. I = (0.5,
2
n
, 0.5,
2
n
, ...)
0.5
0.5
B1 ...
0.5
0.5
B
n
4
2
n
2
n
2
n
2
n
B
n
4
+1
0.25 Best t pakovanje
Best t (najbolje smestanje)
Umesto stavljanja u prvi bin (kutiju,korpu,boks), trazi se bin u koji komad najbolje pasuje (tesno pasuje).
Primer 0.10. Best t za niz ,0.2, 0.5, 0.4, 0.7, 0.1, 0.3, 0.8|
Prazan
0.1
0.5
0.2
Prazan
0.4
0.3
0.7
Prazan
0.8
Bez dokaza navodimo da best t u najgorem slucaju trosi 1.7 od optimalnog broja binova.
Jednostavan je za kodiranje ako trebamo 0(nlogn) vreme izvodjenja.
0.26 First t pakovanje
First t (Prvi odgovarajuci)
First t strategija skenira binove (kutije,korpe,boksove) i smesta novi komad u prvu pregradu (prvi bin) sa do-
voljno mesta da se prihvati. Nova kutija se kreira samo ako prethodne kutije ne mogu da prihvate element.
Primer 0.11. First t za niz , 0.2,0.5,0.4,0.7,0.1,0.3,0.8 |
Prazan
0.1
0.5
0.2
Prazan
0.3
0.4
Prazan
0.7
Prazan
0.8
Teorema 0.7.. Neka je m optimalan broj binova za pakovanje niza I.
1. Tada First t koristi manje ili jednako od ,
17
10
m| binova.
2. Postoji niz koji zahteva
17
10
(m-1) binova.
Dokaz 0.8. Ovde izostavljamo dokaz (1)
(2) Za ilustraciju dajemo sledeci primer:
Neka u nizu I imamo
6m komada duzine
1
7
+
6m komada duzine
1
3
+
6m komada duzine
1
2
+.
Lako se vidi da optimalno imamo 6m binova, svaki za sve tri vrste elemenata. First t koristi 10m binova umesto 6m.
Prazno
1
7
+
1
7
+
1
7
+
1
7
+
1
7
+
1
7
+
Od B
1
do B
m

Prazno
1
3
+
1
3
+
Od B
m+1
do B
4m

Prazno
1
2
+
Od B
4m+1
do B
10m
Napomena Prakticna merenja pokazuju da u slucaju vrednosti uniformno rasporedjenih u intervalu ,0, 1|, za rst
t trebamo oko 2 posto vise binova.
0.27 O-Line algoritmi : First t decreasing.
U o-line obradi korisno je elemente sortirati pre rasporedjivanja u binove. Za First t algoritam sortiramo u
opadajucem(decreasing) poretku, a za best t zgodnije je sortirati elemente u rastucem (increasing) poretku.
Primer 0.12. First t za niz 0.8, 0.5, 0.4, 0.3, 0.2, 0.1
0.2
0.8 B1
0.3
0.7 B2
0.1
0.4
0.5
B3
Zelimo dokazati da rst-t decreasing algoritam koristi najvise
4m+1
3
binova, ukoliko optimalno pakovanje koristi m
binova.
Lema 0.2. Neka n elemenata niza sortiranog u opadajucem poretku imaju duzine s
1
, ..., s
n
i pretpostavimo da se
optimalno mogu u m binova. Tada svi komadi koji se smestaju u dodatne binove po principu rst t decreasing
imaju duzinu manju ili jednaku
1
3
.
Dokaz 0.9. Dokazimo da za s
i
element koji je prvi smjesten u m+1-om binu vazi [s
i
[
1
3
.
Pretpostavimo da je [ s
i
[>
1
3
. Tada je svaki od s
1
, s
2
, ..., s
i1
>
1
3
jer su sortirani u opadajucem poretku. Zbog
toga svaki od binova B
1
, ..., B
m
imaju najvise dva elementa.
Neka B
x
iB
y
takvi da je 1 x<y m i neka su u B
x
dva komada x
1
i x
2
, a u B
y
jedan komad y
1
. Tada
(x
1
y
1
x
2
s
i
) x
1
+x
2
y
1
+s
i
.
Iz zakljucka implikacije sledi da s
i
moze biti smesten u B
y
, sto je suprotno pretpostavci.
Moramo imati prvo niz binova sa po jednim komadom, a zatim ide niz binova koji sadrze po dva komada. Neka
je prvih j, a drugih m-j. Neka su s
1
, ..., s
j
po jedan u binu, a s
j+1
, s
j+2
, ..., s
i1
i m-j binova, po dva komada zajedno
2(m-j) je ukupan broj komada u tih m-j binova. Ne mogu se svi elementi staviti u m binova, sto je kontradikcija.
Lema 0.3. Broj objekata u dodatnim binovima najvise moze biti m-1.
Dokaz 0.10. Pretpostavimo, suprotno tvrdnji, da u dodatnim binovima imamo m komada(elemenata niza). Posto
s eoptimalno svi elementi niza s
1
, ..., s
n
mogu smestiti u m binova, to je

n
i=1
s
i
m. Sa druge strane, ako oznacimo
s
i
=
_
w
j
, 1
x
i
, ako se s
i
nalazi u dodatnom binu(a ima ih najmanje m po pretpostavci)
imamo da je

n
i=1
s
i


m
j=1
w
j
+

m
j=1
x
j


m
j=1
(w
j
+x
j
)
w
j
+ x
j
> 1, inace bi x
j
moglo biti smesteno u B
j
.

n
j=1
s
i
>

m
j=1
1 > m Kontradikcija! Time je lema
dokazana.
Teorema 0.10.. Neka je m optimalan broj binova za pakovanje niza I elemenata s
1
, ..., s
n
.Tada rst-t decreasing
ne treba vise od
4m+ 1
3
binova.
Dokaz 0.11. m-1 elemenata velicine koja je
1
3
treba ,
m1
3
| ekstra binova. Ukupan broj binova je najvise ,
m1
3
|
m+1
3
|.
Teorema 0.11.. Neka je m optimalan broj binova potrebnih za pakovanje niza I=s
1
, s
2
, ..., s
n

1. Tada rst t decreasing ne koristi vise od


11
9
+m binova
2. Postoji niz koji za FFD trazi
11
9
m binova.
Dokaz 0.12. (2) I:
1
2
+ - 6m elemenata
1
4
+ 2 - 6m elemenata
1
4
+ - 6m elemenata
1
4
2 - 12m elemenata
1
4
2
1
4
+ 2
1
2
+
B
1
, ..., B
6m
1
4
2
1
4
2
1
4
+ 2
1
4
+ 2
B
6m+1
, ..., B
9m
Prazan
1
4
+ 2
1
2
+
B
1
, ..., B
6m
Prazan
1
4
+
1
4
+
1
4
+
B
6m+1
, ..., B
8m
1
4
2
1
4
2
1
4
2
1
4
2
B
8m+1
, ..., B
11m
0.28 Metoda Hill Climbins. Problem prelaska pustinje dzipom
Algoritam Hill Climbins daje neki lokalni optimum za koji ocekujemo da je jednak globalnom optimumu. Ako
apsolutno najbolje resenje nije tacno, tada se hill climbins koristi za generisanje pribliznog resenja.
U slucaju da se trazi tacno resenje, tada hill clibinG algoritam treba poboljsati do tacnog algoritma.
Primer 0.13. Pustinja je duga 1000km. Dzip trosi 1l benzina na 1km. Neka na pocetku pustinje postoji neogranicena
kolicina goriva i neka je dozvoljeno praviti skladista goriva na proizvoljno izabranom mestu u pustinji. Naci minimalnu
kolicinu goriva potrebnu da dzip predje pustinju,ako dzip moze imati maksimalno 500l goriva.
Dokaz 0.13.
1. Neka dzip iz poslednjeg skladista A uzme dovoljnu kolicinu goriva za dolazak do kraja pustinje. Koristeci princip
optimalnosti zakljucujemo da skladiste A mora sadrzati 500l benzina.
2. Skladiste A punimo koristeci skladiste B, udaljenosti xkm od skladista A. Da bi smo u A mogli uskladistiti 500l
benzina moramo imati u B(3x+500)l benzina. Zbog optimalnosti dzip u svakoj turi nosi maksimalnu kolicinu od
500l benzina. To nam daje jednacinu 3x+500=1000 za tacku B,pa sledi da je tako maksimizirano x=
500
3
.
3. Slicno za tacku C dobijamo 5y+1000=1500, odakle je y=
500
5
. Dalje je z=
500
7
itd.
Konacno imamo:
(500+x+y+z+...)=1000
(500+
500
3
+
500
5
+
500
7
+...)=1000
500(1+
1
3
+
1
5
+
1
7
+...)=1000 tj.
(1+
1
3
+
1
5
+
1
7
+...)=2
OPTIMALAN
Broj skladista i kolicinu benzina u njima odredjujemo iz broja clanova harmonijskog reda ciji zbir po prvi put pre-
masi 2,znaci (1 +
1
3
+
1
5
+
1
7
+
1
9
+
1
11
+
1
13
). Nas dokaz optimalnosti je neuristicki. Formalan dokaz moze se izvesti
u teoriji lanaca Markova.
0.29 Metoda Backtracking. Problem osam kraljica.
Ideju pretrazivanja sa vracanjem (backtrack) lako je objasniti na primeru izlaska iz lavirinta. Nas je cilj da iz nekog
zadatog kvadrata dodjemo u drugi zadati kvadrat premestajuci se postepeno po kvadratima. Problem je u tome sto
u nekim kvadratima postoje pregrade koje onemogucuju prolaz.
Jedan od nacina prolaska kroz lavirint je kretanje od pocetnog kvadrata po sledeca dva pravila.
1. U svakom kvadratu izabrati jos neiskoristen put.
2. Ako iz kvadrata razmatranog u datom trenutku ne vode neiskoristeni putevi, tada se treba vratiti jedan korak
nazad po zadnjem predjenom putu, po kojem smo usli u kvadrat.
Sustina pretrazivanja sa vracanjem sastoji se u tome da produzavamo put dok je moguce, a kada nije moguce, vratimo
se po putu i pokusamo drugi izbor po najblizem putu, ako takav izbor postoji.
Backtracking mozemo predstaviti drvetom pretrazivanja tako da cvor drveta predstavlja dato stanje, a grane drveta
predstavljaju korake iz datog stanja u sledeca stanja. Tada drvo pretrazujemo po putevima oznacenim isprekidanim
linijama. Na nekom nivou biramo resenja d
i
uz pretpostavku da su d
1
d
2
...d
i1
izabrani na prethodnim nivoima.
Predstavnike koji ne odgovaraju odbacujemo, tj. podrezujemo drvo.
U najopstijem slucaju pretpostavljamo da se resenje sastoji od vektora (a
1
, a
2
, ..., a
n
), konacne, ali nedenisane duzine,
koji zadovoljava dodatna resenja. Pri tome je svako a
i
iz nekog linearno odredjenog skupa A
i
. Na taj nacin pri iscrp-
nom istrazivanju mozemo razmotriti sve elemente skupa. A
1
A
2
A
i
,i=0,1,2,... kao moguca resenja.
Za polazno resenje biramo prazan vektor () i na osnovu postojecih ogranicenja nalazimo elemente iz A
1
koji su
kandidati za a
1
. Oznacicemo taj skup sa S
1
. Za a
1
uzimamo najmanji elemenat iz S
1
. Rezultat je parcijalno resenje
(a
1
).
Uopste razlicita ogranicenja koja opisuju resenja, govore nam iz kojeg skupa S
k
A
k
uzimamo kandidate a
k
za
parcijalno resenje (a
1
, a
2
, ..., a
k1
).
Ako parcijalno resenje (a
1
, a
2
, ..., a
k1
) ne mozemo rasiriti dodavanjem elementa a
k
, tada je s
k
= . U tom slucaju se
vracamo i biramo novi element a
k1
. Ako ni izabrani a
k1
ni izabrani S
k1
ne daju mogucnost rasirenja, vracamo se
jos jedan korak nazad i biramo element a
k2
S
k2
i td.
Primenjujemo opisanu metodu na resavanje problema osam kraljica. U tom problemu treba na sahovsku tablu dimen-
zije n n postaviti sto vise kraljica tako da ni jedna ne tuce drugu.
Posto kraljica napada sva polja u koloni(stupcu),u redu i na dijagonali na kojoj se nalazi, jasno je da mozemo postaviti
najvise n kraljica koje jedna drugu ne napadaju. Problem se svodi na :
1. Postavljanje kraljica na ploci tako da jedna drugu ne napadaju.
2. Ako resenje postoji, onda naci ukupan broj resenja.
U svakom stupcu moze se nalaziti tacno jedna kraljica, a to znaci da resenje mozemo predstaviti vektorom (a
1
, a
2
, ..., a
n
)
u kojem je a
i
broj reda kraljice iz stupca i.
U svakom redu moze postojati tacno jedna kraljica pa i ,= j a
i
,= a
j
. Kraljice ne smeju jedna drugu napa-
dati po dijagonali i zbog toga moramo imati [a
i
a
j
[ , = [i j[ za i ,= j.
Da bi smo u ovom problemu dodali a
k
u (a
1
, a
2
, ..., a
k1
) jednostavno poredimo a
k
sa svakim a
i
, i < k. Uvek je
S
n+1
= za plocu n n. Ilustrujmo i slikom backtrack na ploci 8 8.
U nasem resenju zadatka nismo pokusali da nadjemo
_
_
n
2
n
_
_
nacina na koje se n kraljica moze postaviti na plocu
n n (oko 4.4 10
9
za n=8).
Druga ideja mogla je koristiti cinjenicu da svaka kolona sadrzi najvise jednu kraljicu, sto bi dalo n
n
mogucih polozaja
za istrazivanje (za n=8 oko 1.7 10
7
). Ako primetimo da nikoje dve kraljice ne mogu biti u jednom redu, to znaci da
vektor (a
1
, ..., a
n
) mora biti permutacija (1,...,n) sto daje n! mogucnosti (za n=8 oko 4.0 10
4
mogucnosti).
Na kraju, posto dve kraljice ne mogu biti na jednoj dijagonali, broj mogucnosti se skracuje jos vise (za n=8 na oko
2056 mogucnosti sto je racunarski prihvatljivo).
Proces skracivanja u problemu sa kraljicama mozemo produziti i dalje. Dva resenja mozemo smatrati ekvivalent-
nim ako se jedan od njih prevodi u drugo pomocu niza rotacija i/ili simetrija.
Ako utvrdimo postojanje kraljice u cosku table, tada ta kraljica napada sve ostale coskove. Zbog toga nema resenja u
kojem je kraljica postavljena u vise nego jednom cosku. Ako je nadjeno resenje u kojem je kraljica na polju (1,1) tada
ono moze biti prevedeno rotacijama i/ili simetrijama u ekvivalentno resenje u kojem je polje (1,1) prazno. Uopste,
ako nadjemo sva neekvivalentna resenja tada mozemo konstruisati i sva ostala resenja.
Sledece usavrsavanje odnosi se na spajanje grana drveta. Ako primetimo da su dva poddrveta izomorfna, dovoljno je
razmotriti samo jedno od njih.
Metoda preuredjenja drveta korisna je u slucaju u kojem neka resenja imaju slican izgled. Drvo mozemo preurediti
da pre svega pretrazimo takva resenja.
Metod dekompozicije je razbijanje problema na niz problema uz moguce koristenje metoda rekurzije i/ili dinam-
ickog programiranja. Resenje problema komponuje se od resenja podproblema.
Za implementaciju nasega algoritma kljucna je procedura u kojoj ispitujemo u kojem retku k-tog stupca stoji
kraljica. U grubim crtama ta procedura izgleda na sledeci nacin :
bo l l f l a g=t r ue ;
i nt i =1 ;
whi l e ( i <k & & f l a g )
i f ( a=a k ) [ [ ( [ a i a k [ =[ i k [ ) then f l a g=f a l s e ;
i=i +1 ;

Uz koristenje ove procedure program trosenja resenja u problemu n kraljica mozemo skicirati na sledeci nacin :
s 1 =1;
k=1;
whi l e k>1
whi l e s k <=n
a k<=s k ;
s k=s k +1;
whi l e ( s k<=n && k r a l j i c a ne moze b i t i u redu s k stupca k)
s k=s k+1 ;
i f k=n then z a pi s a t i
e ( a 1 , . . . , a n )
k=k+1;
s k =1;
whi l e ( s k<= && k r a l j i c a ne moze b i t i u redu s k stupca k)
s k=s k+1

k=k1;

U ovom programu umesto citavog skupa s


k
cuva se samo minimalan element s
k
. Provera uslova S
k
,= odgovara
uslovu s
k
n. Posto s
n+1
nije manje od n+1 to je s
n+1
uvek prazan skup.
Dajemo za ilustraciju jos dva detaljna resenja problema n kraljica. Ideje ovih resenja razlikuju se u nekoj meri od
ideja za resavanje koje smo mi prethodno izlozili. Drugo resenje dato je prema ideji N. Wirth-a. Programi su testirani
na TURBO C++, v.6.0 i daju resenja za n70.
/ Pocetak prvog programa /
i nt n ; // za nxn t abl u .
i nt f l a g ;
voi d pri ntArray ( i nt a [ ] ) ; // za stampanj e konacnog r e s e nj a
voi d s e t Pos i t i o n ( i nt a [ ] , i nt n 1 , i nt 2 ) ; // r ekur zi vna f unkc i j a
i nt main ( )

i nt a ;
i nt c t r =0;
pr i nt f (n problem n k r a l j i c a ) ;
pr i nt f (n Broj redova za nxn t abl u ) ;
s c anf (%d , &n ) ;
a=( i nt ) ( mal l oc ( s i z e o f ( i nt )n ) ) ;
pr i nt f (n U svakom r e s e nj u su koor di nat e i t e k r a l j i c e date sa ( Red , Kolona ) ) ;
pr i nt f ( n Svi su r edovi i kol one numeri sani od 1 do n ) ;
f o r ( c t r =0; ctr <n ; c t r++)
ge t Pos i t i ons ( a , 0 , c t r ) ;
get char ( ) ;
get char ( ) ;

voi d pri ntArray ( i nt a [ ] )

i nt i , c hoi c e ;
s t a t i c . i nt counter =0;
counter++;
pr i nt f ( n RESENJE #%d , counter ) ;
f o r ( i =0; i <n ; i ++)
pr i nt f ((%d,%d) , i +1, a [ i ] +1) ;
i f ( counter %10==0) pr i nt f ( n Ubes i t e 0 za kraj , j edan za nastavak ) ;
s c anf (%d , &c hoi c e ) ;
i f ( c hoi c e==0) e xi t ( 0 ) ;
;

voi d ge t Pos i t i ons ( i nt a 1 [ ] , i nt col no , i nt val )

i nt ctr1 , c t r 2 ;
a 1 [ col no ]=val ;
i f [ col no]==n1
pr i nt f Ar r ay ( a 1 ) ; r et ur n ;
;
f o r ( c t r 1 =0; ctr1<n ; )
/ ova pe t l j a na l az i odgovaraj uce br oj eve kol ona u sl edecem redu /
f o r ( c t r 2 =0; ctr<=col no ; c t r 2++)
i f ( a 1 [ c t r 2]==c t r 1 [ [ ( col no+1c t r 2 ) ( col no+1c t r 2)==( ctr1a 1 [ c t r 2 ]
( ctr1a 1 [ c t r 2 ] ) )
goto mi ss1 ;
ge t Pos i t i ons ( a 1 , col no +1, c t r 1 ) ;
mi ss1 ;
c t r 1++;

/ KRAJ PROGRAMA /
Program za n kraljica koji umesto rekurzije koristi dva steka. Stekovi su implementirani pomocu
nizova (arrays).
#i nc l ude <s t di o . h>
#i nc l ude <s t dl i b . h>
#i nc l ude <ti me . h>
t ypedef s t r uc t i nt x , y ;
po s i t i o n ;
voi d Sol veProbl em( i nt n ) ;
i nt n=0;
voi d main ( )
pr i nt f (n Unes i t e di menzi j u n za t abl u nxn : ) ;
s c anf (%d,&n ) ;
pr i nt f (n U svakom od r e s e nj a koor di nat e nt e k r a l j i c e su date sa ( Red , Kolona ) ) ;
pr i nt f (n Redovi i kol one su numeri sani od 1 do n: n ) ;
Sol veProbl em( n ) ;
get char ( ) ;

voi d Sol veProbl em( i nt n)

i nt counter1 , counter2=1, counter3=1;


s t a t i c i nt counter 0, c hoi c e ;
i nt d [ 1 0 0 ] [ 3 ] = 0 ;
i nt s t ack2 ;
pos i t i on Pos i t i on1 , Pos i t i on2 , Pos i t i on3 ;
pos i t i on head( po s i t i o n ) mal l oc ( nn s i z e o f ( pos i t i on ) ) ;
s t ack2=( i nt ) mal l oc ( n s i z e o f ( i nt ) ) ;
f or ( counter1=n1; counter1 >=0; counter1 )

Pos i t i on1 . x=0;


Pos i t i on1 . y=counter1 ;
head1[++counter2 ]=Pos i t i on1
;
whi l e ( counter2 >=0) Pos i t i on1=head1 [ counter2 ];
whi l e ( counter3>=0 && Pos i t i on1 . x<=counter3 )
Pos i t i on2 . x=counter3 ;
Pos i t i on2 . y=s t ack2 [ counter3 ];
d [ Pos i t i on2 . y ] [ 0] =0;
d [ Pos i t i on2 . x+ Pos i t i on2 . y ] [ 1] =0;
d [ Pos i t i on2 . x Pos i t i on2 . y+n ] [ 2] =0; ;
s t ack2[++ counter3 ]=Pos i t i on1 . y ;
d [ Pos i t i on1 . y ] [ 0] =1;
d [ Pos i t i on1 . x+ Pos i t i on1 . y ] [ 1] =1;
d [ Pos i t i on1 . x Pos i t i on1 . y+n ] [ 2] =1;
i f ( counter3==(n1))

counter++ ;
pr i nt f (n SOLUTION #%d : , counter ) ;
f or ( counter1 =0; counter1<=counter3 ; counter1++)
pr i nt f ((%d,%d) , counter1 +1, s t ack2 [ counter1 ] +1) ;
i f ( counter %10==0) pr i nt f (n Enter1 to conti nue , 0 to Exi t ) ;
s c anf (%d , & c hoi c e ) ;
i f ( c hoi c e==0)
e xi t ( 0 ) ;
;
Pos i t i on2 . x=counter3 ;
Pos i t i on2 . y=s t ack2 [ counter3 ];
d [ Pos i t i on2 . y ] [ 0] =0;
d [ Pos i t i on2 . x+ Pos i t i on2 . y ] [ 1] =0;
d [ Pos i t i on2 . x Pos i t i on2 . y+n ] [ 2] =0;
e l s e f or ( counter1=n1; counter1 >=0; counter1 )
i f ( d [ counter1 ] [0]==0 && d [ Pos i t i on1 . x+counter1 ] [1]==0
&& d [ n+Pos i t i on1 . x+1counter1 ] [ 2] ==0)
Pos i t i on3 . x=Pos i t i on1 . x+1;
Pos i t i on3 . y=counter1 ;
head1[++counter2 ]=Pos i t i on3 ;
;

get char ( ) ;
get char ( ) ;
r et ur n0 ;

Problem kraljica. Koliki je maksimalan broj kraljica koje se mogu postaviti na sahovsku plocu n n tako da
nikoje dve ne tuku jedna drugu? Odgovor : n kraljica.
Broj nacina na koje se n kraljica mogu postaviti na plocu n n da ne tuku jedna drugu je (1,0,0,2,10,4,40,92,...) za
n=1,2,3,4,5,6,7,8,...
Na slici je dato 12 neekvivalentnih resenja za n=8. Od njih se rotacijama i simetrijama dobijaju svih 92 resenja.
Na datoj slici je minimalan broj kraljica da zauzimaju ili tuku sva polja ploce 8 8.
0.30 Dodatak A.
0.30.1 Heap sort (sort drvetom)
templ ate <c l a s s T>
voi d heapi f y (Ta , i nt k , i nt n)
T t= a [ k ] ;
whi l e ( k<n/2)
i nt j =2k+i ; // pr et var a j u n a j s t a r i j e g potomka k
i f ( j +1<n && a [ j ]<a [ j +1] ) ++j ;
i f ( t>a [ j ] ) break ;
a [ k]=a [ j ] ;
k=j ;

a [ k]=t ;

templ ate <c l a s s T>


voi d s or t (Ta , i nt n)
f or ( i nt i=n/21; i >=0; i )
heapi f y ( a , i , n ) ;
f o r ( i=n1; i >0; i )
swap( a [ 0 ] , a [ i ] ) ;
// I nvar i j ant a : el ement i a [ i : n1] su u korektnom poretku
heapi f y ( a , o , i ) ;
// I nvar i j ant a : podni z a [ o : n1] j e heap

templ ate <c l a s s T>


voi d swap (T&x , T&y)

T temp=x ;
x=y ;
y=temp ;

0.30.2 Dinamicke strukture


Tipicna implementacija dinamickog skupa:
Svaki element je predstavljen nekim objektom, a polja tog objekta mogu biti posecena i manipulisana pomocu pokazi-
vaca na objekat.
Razlikujemo:
KEY (kljuc)
Satelitski podaci //nisu koristeni u implementaciji
Operacije
Queries(upitne, selektorske) operacije
Modikatorske operacije
Search(S,k) // vraca key[x]=k ili NIL
Insert(S,x)
Delete(S,x)
Minimum(S) //vraca minimum S
Maximum(S)
Successor(S,x) //NIL ili neposredno veci od x
Predecessor(S,x) //NIL ili manji od x
Dictionary(recnik)
< S,Insert, Delete, Membership >
Stack (Stek), LIFO property
S [1...top [S]] , S [1] -bottom, S [to] - vrh
top [S]=0 empty
underow, overow
STACKEMPTY( S)
i f top [ S]=0
then r et ur n TRUE
e l s e r et ur n FALSE
PUSH( S , x)
top [ S]<top [ S]+1
S [ top [ S]] <x
POP( S)
i f STACKEMPTY( S)
then e r r or underf l ow
e l s e top [ S]<top [ S] 1
r et ur n S [ top [ S] +1]
Red(Queue), FIFO property
ENQUEUE (Insert)
DEQUEUE (Delete)
Enqueue ( a , x)
a [ t a i l [ a]] <x
i f t a i l [ a]=l engt h [ a ]
then t a i l [ a ] <1
e l s e t a i l [ a ] <t a i l [ a]+1
Dequeue ( a )
x<a [ head [ a ] ]
i f head [ a]=l engt h [ a ]
then head [ a ] <1
e l s e head [ a ] <head [ a]+1
r et ur n x
0.30.3 Linkovane liste
Linearno uredjeni objekti - dvostruko povezana lista
next, prev
next[x], prev[x]
prev[x]=NIL, head[L]=NIL
-jednostruko povezana lista: prev, nesortirana, cirkularna lista.
LIST SEARCH (L, x)
x<head [ L]
whi l e x< >NIL and key [ x]<>k
do x<next [ x ]
r et ur n x
T(n)=O(n) u najgorem slucaju (worst case)
LIST INSERT(L, x ) , LIST DELETE (L, x)
LIST INSERT(L, x)
next [ x]<head [ L]
i f head [ L]< >NIL
then prev [ head [ L]] <x
head [ L]<x
prev [ L]<NIL
LIST DELETE (L, x)
i f prev [ x]< >NIL
then next [ prev [ x]] <next [ x ]
e l s e head [ L]<next [ x ]
i f next [ x]< >NIL
then prev [ next [ x]] <prev [ x ]
T(n)=O(n) in worst case.
0.30.4 Sentineli
LISTDELETE (L, x)
next [ prev [ x]] <next [ x ]
prex [ next [ x]] <prev [ x ]
SENTINEL je uvedeni emenet da olaksa rad sa granicnim vrednostima.
Primer 0.14. nil[L] za NIL
LIST SEARCH
x<next [ n i l [ L ] ]
whi l e x< >n i l [ L] and key [ x]< >k
do x<next [ x ]
r et ur n x
LIST INSERT (L, x)
next [ x ] <next [ n i l [ L ] ]
prev [ next [ n i l [ L ] ] ] <x
next [ n i l [ L ] ] <x
prev [ x ] <n i l [ L]
0.30.5 Implementacija pointera i objekata matricom
0.30.6 Implementacija pointera jednodimenzionalnim nizom
0.30.7 Alociranje i oslobadjanje elemenata.
Garbage collector-i vode racuna o neiskoristenim lokacijama.
Free objekti u jednostruko povezanoj listi, SLOBODNA LISTA. Samo next, head u free.
Slobodna lista je stek.
T(n)=O(1)
ALLOCATE OBJECT ( )
i f f r e e = NIL
then e r r or out of space
e l s e x<f r e e
f r e e <next [ x ]
r et ur n x
FREE OBJECT( x)
next ( x) < f r e e
f r e e <x
0.30.8 Binarno drvo
p , l e f t , r i ght
p [ x]=NIL x j e koren ( r oot )
r oot [ T]=NIL prazno drvo
0.30.9 Neograniceno grananje
left-child, rightsibling representation
1 l e f t c hi l d [ x ]
pokazuj e na najl evo dete od x
2 r i ght s i b l i n g [ x ]
pokazuj e na rodj aka neposredno sa desne s t r ane
l e f t c hi l d [ x]=NIL nema dece x
r i ght s i b l i n g [ x]=NIL <= r i ght most c hi l d r o d i t e l j a
levi-desni
child1,...,child k
Nije pogodna reprezentacija za beskonacno grananje!
Druge reprezentacije:
1. Heap sa 1 array i indeksom.
2. Za drveta koja prolazimo samo prema korenu treba samo pokazivac na roditelja.
0.30.10 Hes-tabele
INSERT, SEARCH, DELETE
1. Tabele sa direktnim adresiranjem
Key U = 0, ..., m1
Svaka dva elementa imaju razlicite kljuceve.
Array(niz) = Direct - address table
T,om1|
Pozicija ili slot odgovara jednom kljucu iz univerzum U.
U = ,0, 1, ..., 9|
K = ,2, 3, 5, 8|
DIRECTADDRESSSEARCH (T, k)
r et ur n T[ k ]
DIRECTADDRESSINSERT(T, x)
T[ key [ x ] ] < x
DIRECTADDRESSDELETE (T, x)
T[ key [ x ] ] <NIL
2. Hes tabele
Direktnim adresiranjem element sa kljucem k stavlja se u slot k Hesiranjem se on stavlja u h(k) gde je h kes funkcija
koja racuna slot za k.
h= U 0, 1, ..., m1
k hesira slot h(k)
h(k) je hes vrednost od k
k2 i k5 he s i r a j u s e u i s t i s l o t
KOLIZIJA
h - mora biti deterministicka
[ U [ > m
Iako dobro dizajnirana random funkcija moze minimizirati broj kolizija, mi trebamo neki metod za resavanje kolizija.
0.30.11 Resavanje kolizija uvezivanjem
h(k1)=h(k4) i h(k5)=h(k2)=h(k7)
CHAINED HASH INSERT (T, x)
I ns e r t x of the head of l i s t T[ h( key [ x ] ) ]
CHAINED HASH SEARCH (T, k)
Trazi j edan el ement sa kl j ucem k u l i s t i T[ h [ k ] ]
CHAINED HASH DELETE (T, x)
Del et e x i z l i s t e T[ h [ key [ x ] ] ]
Analiza hashing za ulancavanje
n elemenata
m slotova
d=
n
m
faktor opterecenja <, >, = 1
Worst-case je neprihvatljivo.
Lista+hashingfunkcija (racun) O(n)
Awerage-case
Prosto uniformno hesiranje
length(T[j]) = n
j
, j = 0, ..., m1
n = n
0
+... +n
m1
E[n
j
] = = n/msrednja vrednost n
j
.
Neka h(k) mozemo izracunati u O(1) vremenu i pristupiti slotu h(k) pretrazivanje zavisi lineatno od duzine n
h(k)
liste T,h,k||
1. Nijedan element tabele nema kljuc k
2. Pretrazivanje uspesno nalazi element sa kljucem k
Teorema 0.13.. U hes tabeli, u kojoj su kolizije resene uvezivanjem , neuspesno pretrazivanje zahteva T=O(1+) uz
pretpostavku uniformnog hesiranja.
Dokaz 0.14. Ocekivano vreme je duzina liste T,h,k||, a ta ima duzinu E[n
h(k)
] = d. Broj ispitivanih elemenata je
T = (1 +).
Teorema 0.14.. U hes tabeli, u kojoj se kolizije resavaju uvezivanjem, uspesno pretrazivanje, u srednjem, zahteva
O(1 +) vreme, uz pretpostavku uniformnog hesiranja.
Dokaz 0.15. k
i
= key,x
i
|, i = 1, 2, ..., n
X
ij
= Ih(k
i
) = h(k
j
) =
1
m
E,X
ij
| =
1
m
Ocekivani broj ispitanih elemenata je
E,
1
n

n
i=1
(1 +

n
j=i+1
X
ij
)|
=
1
n

n
i=1
(1 +

n
j=i+1
E,ij|)
=
1
n

n
i=1
(1 +

n
j=i+1
1
m
)
= 1 +
1
nm

n
i=1
(n i)
= 1 +
1
nm
(

n
i=1
n

n
i=1
i)
= 1 +
1
nm
(n
2

n(n + 1)
2
)
= 1 +
n 1
2m
= 1 +
d
2

d
2n
= T = (2 +
d
2

d
2n
) = (1 +)
0.30.12 Hes funkcije
Heuristicke:
hashing deljenjem i hashing mnozenjem
Stohasticke: univerzalno hesiranje
Uniformno hesiranje:
Svaki kljuc je podjednako moguce hesirati u bilo koji slot od m, nezavisno od toga gde su hesirani drugi kljucevi.
Teskoce
1. Ne znamo distribuciji verovatnoca sa kojima ce kljucevi biti izvuceni.
2. Kljucevi mogu biti vuceni u zavisnosti jedan od drugog.
Ponekad znamo distribucije: kljuveci su k slucajnih brojeva nezavisno i uniformno distribuirani u 0 k < 1 h(k) =
km| zadovoljava uslov prostog uniformnog hesiranja. Praksa:
1. pt i pts slati u razlicite slotove,
2. zahtevaju se ponekad ostriji uslovi: daleke vrednosti hesirati u bliske slotove.
Kljucevi kao prirodni brojevi
U = N = 0, 1, 2, ... Ako nisu, interpretiramo ih tako.
Primer 0.15. pt=(112,116), (112*128)+116=14452 (ceo broj u osnovi 128)
Metod deljenja.
h(k)=k mod m
Primer 0.16. m=12, k=100, h(k)=4
mora biti m,= 2
p
, jer je h(k)=p najnizih bitova.
Bolje je napraviti hes funkciju zavisnu od svih bitova!
m = 2
p
1 je los izbor, jer permutovanje znakova k
(interpretirano u radix 2
p
) ne menja slot. Dokazati!
Prost broj daleko od 2
p
je dobar izbor.
Primer 0.17. Uvezivanje za kolizije n=2000 stringova znakova (char ima 8 bitova). Nije nam problem pretrazivati u
srednjem 3 elementa.
m=701, h(k)=kmod701, gde je k integer!
701=2001/3 je daleko od 2
n
!
Metod mnozenja.
1. k mnozimo konstantom A, 0 < A < 1 i uzimamo funkcijski deo od kA
2. mnozimo sa m i uzimamo oor kao rezultat
h(k)= m(kAmod1)|,
sa kA mod1 kA-kA|
Tipicno, m nije kritican, pa uzimamo m=2
p
, p Z, jer je implementacija na kompjuteru jednostavnija.
1. Duzina reci masine je w bita.
2. k staje u jednu rec.
3. A je decimalni deo od
s
2
w
, 0 < s < 2
w
.
Rezultat je r
1
2
w
+r
0
.
4. Uzimamo p bitova najvece tezine u r
0
.
D.Knuth sugerise: A

5 1
2
= 0.6180339887.
Primer 0.18. k=123456, p=14, m=2
1
4=16384, w=32.
A decimalni deo
s
2
32
najblize

5 1
2
A=
2654435769
2
32
k s= 327706022297664 = (76300 2
32
) + 17612864
i r
1
=76300, r
0
=17612864 h(k)=67.
0.30.13 Univerzalno hesiranje
Da ne bi svi kljucevi bili kesirani u isti slot, treba izabrati SLUCAJNO hes funckiju. To je UNIVERZALNO HESIR-
ANJE, ako je funkcija izabrana nezavisno od vrednosti kljuceva.
Poredjenje sa Quick-sortom. Izbor hes funkcije iz unapred pazljivo dizajniranog skupa funkcija.
H - konacna kolekcija hes funkcija.
h: U 0, 1, ..., m1
Univerzalna kolekcija akko k, l U, broj h H za koje je h(k)=h(l) najvise
H
m
, tj. sanse da bude kolizija h(k) i
h(l) su
1
m
. Pri tome su h(k) i h(l) nezavisno i slucajno izabrani iz 0, 1, ..., m1.
Teorema 0.15.. Neka je h izabrana iz univerzalne kolekcije H hes funkcija. h se koristi za hesiranje n kljuceva u
tabelu T duzine m, sa uvezivanjem za razresavanje kolizija.
Ako k nije u tabeli, tada je ocekivana duzina E,n
h(k)
| liste u koju se hesira k, najvise .
Ako je k u T, tada je ocekivana duzina E,n
h(k)
| liste sa kljucem k najvise 1+.
Dokaz 0.16. Za k, l denisemo X
kl
= Ih(k) = h(l)
k,l kolidiraju sa verovatnocom
1
m
.
Prh(k) = h(l)
1
m
E,X
kl
|
1
m
.
Denisemo za k
Y
k
=

lT
l=k
X
k
l
E,Y
k
| = E,

lT
l=k
X
k
l| =

lT
l=k
E,X
kl
|

lT
l=k
1
m
k / T n
h(k)
= Y
k
i
[ k [ l T&l ,= k [= n
E,n
h(k)
| = E,Y
k
|
n
m
=
k T&k T,h(k)|& k nije u racunu Y
k
n
h(k)
= Y
k
+ 1 [ l [ l T&l ,= k [= n 1
E,n
h(k)
| = E,Y
k
| + 1
n 1
m+ 1
= 1 +
1
m
< 1 +.
Korolar.
Koristenje univerzalnog hesiranja i resavanja kolizija uvezivanjem u tabeli sa m slota, zahteva T=(n) za bilo koju
sekvencu od n INSERT, SEARCH, DELETE operacija od kojih su njih (m) INSERT.
Dokaz 0.17. [ Ins [= O(m) n = O(m) = O(1)
INSERT, DELETE trebaju O(1) vreme, a takodje i SEARCH. Zbog linearnosti E za citavu sekvencu (niz) treba T=O(n)
koraka.
0.30.14 Otvoreno adresiranje
Svi elementi su u samoj hes tabeli, tj. svaki unos sadrzi ili element ili NIL. Kada trazimo element, pretrazujemo samo
tabelu dok ne nadjemo element ili dok ne bude jasno da tabela ne sadrzi element. Tabela moze biti popunjena do kraja
bez mogucnosti daljeg unosa. Load faktor (faktor popunjenosti) nikada ne moze biti veci od 1.
Umesto pointera racunamo(sledimo) nizove slotova koje treba ispitati. Memorija koju bi koristili pointeri daje veci
broj slotova, potencijalno vodeci ka smanjenju kolizija i brzem pretrazivanju.
INSERT
h: Ux 0, 1, ..., m1 0, 1, ..., m1 zahtevamo:
probni niz h(k,0), h(k,1),...,h(k,m-1) je permutacija 0, 1, ..., m1.
HASHINSERT(T, k)
i < 0
r epeat j < h( k , i )
i f T[ j ]=NIL
then T[ j ] < k
r et ur n j
e l s e i < i +1
unt i l i=m
e r r or hash t abl e over f l ow
HASHSEARCH (T, k)
i < 0
r epeat j < h( k , i )
i f T[ j ]=k
then r et ur n j
i < i +1
unt i l T[ j ]=NIL or i=m
r et ur n NIL
DELETE ce imati poteskoca ako stavimo NIL u izbrisani slot i. Necemo moci izbrisati element za koji je u
postavljanju i nadjen kao popunjen. Izlaz iz problema: umesto NIL stavimo DELETE.
0.30.15 Uniformno hesiranje
Za svaki element probni niz ima jednaku verovatnocu da bude jedan od m! permutacija. Tacno uniformno hesiranje
je tesko za implementaciju.
Umesto pravog UH koristimo i dvostruko hesiranje, linearnu probu, kvadratnu probu.
Linearna proba.
h

: U 0, 1, ..., m1 neka je pomocna hes funkcija. Linearna proba koristi h(k,i)=(h(k)+i) mod m.
Samo je m razlicitih probnih nizova odredjeno sa h(k,0).
JEDNOSTAVNA JE IMPLEMENTACIJA, ali imamo PROBLEM:
primarno klasterovanje! To nam povecava AWERAGE TIME.
CLUSTER: iza i popunjenih, verovatnoca popunjavanja slota i+1 da bude sledeci popunjen je
i + 1
m
- KLAS-
TEROVANJE.
Kvadratna proba.
h(k, i) = (h

(k) +c
1
i +c
2
i
2
)modm
Dvostruko hesiranje.
Kod kvadratne probe h(k
1
, 0) = h(k
2
, 0) h(k
1
, i) = h(k
2
, i), tzv. sekundarno klasterovanje, tj. k
1
i k
2
imaju iste
nizove.
Zbog toga uvodimo dvostruko hesiranje h(k, i) = (h
1
(k) +h
2
(k)), pri cemu h
2
(k) mora biti relativno prost sa duzinom
table.
Primer 0.19. h
1
(k) = kmod 13
h
2
(k) = 1 + (kmod 11)
Za vezbu ubaciti 79,69,98,72,14,50.