You are on page 1of 7

SLOŽENOST ALGORITAMA

Što je Algoritam - Algoritam je precizno opisan način rješenja nekog problema te
nam on zapravo određuje što i kako napraviti da bi riješili određeni problem.
Algoritam se sastoji od konačnog broja koraka, a svaki korak je opisan
instrukcijom, ishod algoritma je završni objekt ili rezultat.
Formalno se algoritam prikazuje kao ulazno-izlazni sistem.

Sada čemo prikazi primjer Euklidovog algoritma - algoritam za nalaženje najveće
zajedničke mjere (djeljitelja). Ulaz čine dva prirodna broja a, b. Algoritam se može
opisati u tri koraka (instrukcije):
E1. [Nađi ostatak] Podijeli „a“ sa „b“ i ostatak označi sa „r“.
E2. [Ostatak je nula?] Ako je „r“=0, algoritam završava s odgovorom „b“
E3. [Zamijeni] Nazovi iznos „b“ sa „a“ i iznos „r“ sa „b“ (točnije a:=b, b:=r) i vrati
se na korak E1

Algoritam započinje instrukcijom (naredbom) E1. Sljedeća instrukcija je E2 koja se
izvršava ako je r=0. Ako je r != 0, prelazimo na instrukciju E3.
Obratimo pažnju na još jedan mali detalj u ovom algoritmu. Ako je a<b onda će
ostatak biti „a“, pa će nakon instrukcije E3 vrijednosti za „a“ i „b“s kojima započinje
instrukcija E1 biti jednostavno zamijenjene, tako da smo u situaciji gdje je a>b. To
možemo riješiti elegantnije i tako da algoritmu dodamo na sam početak još i nultu
instrukciju. Znači ako je a<b, zamijeni vrijednosti varijabla „a“ i „b“ (umjesto a:=b
pišemo a<-b)


Programerski bi to zapisali iterativno:
int a = 190, b = 34;
int r;
if (a < b){
int temp = a;
a = b;
b = temp;
}

do
{
r = a % b;
a = b;
b = r;
} while (r != 0);
Console.WriteLine(a);

ili rekurzivno:

int nzm(int a, int b)
{
if (b == 0)
return a;
return nzm(b, a % b);
}

Temeljne osobitosti algoritama kao slijeda propisanih postupaka i naredbi su ova:
1) postojanje ulaznih podataka (input). Podatci se daju na početku, prije nego
što algoritam započinje s radom. Euklidov algoritam npr. ima za ulaz bilo koji par
prirodnih brojeva: a i b.
2) postojanje izlaza (output). Rezultat provedbe algoritma ovisno o ulazu može
biti broj (kao kod Euklidova algoritma), odluka „da“ ili „ne“, vektor, itd...
3) određenost – svaka naredba u algoritmu mora biti jednoznačno određena, tj.
ne-dvosmislena
4) konačnost – broj koraka u kojem se algoritam provodi je uvijek konačan, ali
ovisan o ulaznim podatcima
5) efektivnost – dotično provedivost algoritma u razumnom, konačnom vremenu.






Da bi smo odabrali bolji algoritam potrebno je odrediti mjeru kvalitete algoritma,
odnosno potrebno je izmjeriti resurse koji su potrebni algoritmu da riješi određeni
problem. Mjere koje se koriste pri ocjenjivanju kvalitete programa jesu vrijeme koje
je potrebno da bi se algoritam izvršio i prostor koji je potreban za pohranu ulaznih
podataka, međurezultata i izlaznih rezultata.
Složenost algoritma. Pretpostavimo radi jednostavnosti da je dimenzija ulaznih
podataka nekog algoritma izražena samo s jednom brojem n € N. Za računalstvo je
onda važno pitanje kolika je složenost(kompleksnost) algoritma u ovisnoti o „n“.
Ona se obično definira kao procjena broja računskih operacija (množenja,
zbrajanja, ...) dovoljnih da se algoritam izvrši, u ovisnoti od ulaznog podatka „n“.
Označimo li taj broj sa h(n), onda je od iznimne važnosti znati je li kompleksnost
h(n):


U računalstvu se algoritam smatra dobrim (primjenjivim) ako je kompleksnost h(n)
najviše polinomijalnog rasta (što manjeg stupnja to bolje). Algoritmi koji imaju
eksponencijalnu kompleksnost, a pogotovo faktorijelnu, smatraju se nepovljnim za
primjenu, tj. za njihovu primjenu treba previše vremena (osim ako je ulaz „n“
malen). Nas uglavnom zanima tzv. Vremenska složenost algoritma (procjena
duljine vremena izvedbe u ovisnosti od ulaznih podataka), za razliku od prostorne
(memorijske) složenosti koja se odnosi na količinu memorijskog prostora
dovoljnog da se izvrši algoritamska procedura u ovisnosti od ulaza. Kod
vremenske složenosti algoritma potrebno je pronaći mjeru koja ne ovisi o brzini
računala na kojem se algoritam izvodi, već o samom algoritmu.
Izvjestan osjećaj za složenost algoritma može dati ova tablica vrijednosti nekih
funkcija u ovisnosti od n:

Primjerice kod rješavanja linearnog sustava s „n“ jednadžbi s „n“ nepoznanica,
Cramerov algoritam ima čak faktorijelnu složenost Θ(n!), dok isti problem ako
riješavamo pomoću Gaussova algoritma imamo kubičnu složenost tj. Θ(n
3
). Tako će
npr. linearni sustav od 20 jednadžbi s 20 nepoznanica Gaussovim algoritmom biti
na računalo riješen u djeliću sekunde (20
3
=8000), dok će Cramerovim pravilom
trebati nekoliko stotina tisuća godina!


Klasifikacija stupnjeva rasta
Kod analize algoritama nas ne zanima točan (egzaktan) broj operacija koje će neki
algoritam izvršiti, već nas zanima stupanj tog rasta sa porastom veličine ulaza.
Isto tako ne zanima nas šta se događa sa ponašanjem algoritma za male ulaze,
nego nas zapravo zanima šta se događa sa efikasnošću algoritma za velike ulaze.
Općenito, možemo reći, da kada analiziramo efikasnost nekog algoritma zapravo
nas zanima u koju klasu stupnja rasta taj algoritam spada, a ne tačan broj
operacija koje će taj algoritam izvršiti Bitno je napomenuti da su razlike velike kod
različitih klasa algoritama upravo za velike veličine ulaza, odnosno, za velike
vrijednosti n.

Notacija Big-O ( npr. O(n) )
-Jedna od najčešće korištenih notacija za klasifikaciju algoritma s obzirom na
stupanj rasta vremenske složenosti je tzv. big-O notacija. Upper bound, gornja
granica. Predstavlja maksimalno vrijeme potrebno za izvršavanje algoritma. U
algoritmima pretraživanja (binary search) najgori slučaj se javlja kada vrijednost
koju tražimo niti ne postoji. Najgori slučaj u algoritmima pretraživanja (ukoliko
vrijednost postoji) bio bi da se ta vrijednost nalazi na posljednjoj poziciji u nizu. U
nekim se situacijama najgori slučaj pojavljuje često
Notacija Ω ( omega, npr. Ω(n) )
- lower bound, donja granica. Minimalno vrijeme potrebno za izvršavanje algoritma.
Primjerice za euklida u najidelanijem slučaju bi bilo Ω(1) da su oba a i b = 1
Notacija Θ ( theta, npr. Θ(n) )
- Zahtjeva poznavanje oba Big-O i Ω. Predstavlja tight bound (tjesna/uska) granica.

Klasifikacija algoritama prema redu funkcije složenosti za najpoznatije klase
algoritama prikazana je u sljedećoj tablici:

Za dovoljno veliki n vrijedi:
O(1) < O(log n) < O(n) < O(nlog n) < O(n
2
) < O(n
3
) < ...< O(2
n
) < O(n!)



Neke od tipičnih Big-O notacija:

O(1) - Konstantni algoritmi
Vrijeme za izvršavanje algoritma se ne mijenja ako se broj podataka u obradi
promijeni. Nije ovisan o veliči podataka na kojima vrši obradu. Rijetkost. Pristup
elementima niza ima složenost O(1), npr. ispitaj da li je taj element niza jednak
necemu pa vrati true, ili uvecaj taj element niza za neki broj....

O(n) - Algoritam linearne složenosti. („o od n“)
Vrijeme za izvršavanje algoritma je direktno proporcionalno broju (veličini)
podataka koji se obrađuju. Udvostručenje količine radnji ima za posljedicu
udvostručenje vremena obrade. Opći oblik linearnog algoritma može se prikazati u
vidu jedne for petlje:

for (i = 0; i < n; i++)
{
....
}

O(n
2
) - Algoritam kvadratne složenosti.
Vrijeme za izvršavanje algoritma je direktno proporcionalno kvadratu broja
(velicine) podataka koje se obrađuju. Najčešće se dobiva kada se koriste dvije for
petlje jedna unutar druge. Bubble Sort ima složenost O(n
2
)

for (i = 0; i < n - 1; i++)
{
for (j = i + 1; j < n; j++)
{
if (niz[i] > niz[j])
{
temp = niz[i];
niz[i] = niz[j];
niz[j] = temp;
}
}
}
/----------------------------------------------------------/
int x = 0;

for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
Console.WriteLine(++x); // ... 25
}
}

O(n
k
) - Algoritam stupanjske složenosti. ( O(n
3
), ... )

Stupanjski algoritmi se mogu dobiti poopćenjem kvadratnih algoritama, za
algoritam s k umetnutih for petlji složenost je O(n
k
). Uglavnom povečanje broja
ugnježđenih petlji...
O(K
n
) – Eksponencijalni algoritamski
... (npr 2
n
) Predstavlja algoritam čija se veličina uduplava sa svakim novim dodatim
podatkom. Vrijeme izvršavanja ovakvog algoritma u kratkom vremenu postaje jako
veliko. Jedan od takovih primjera je algoritam koji rekurzivno rješava igru "Hanojski
tornjevi". Dodavanjem novog koluta uduplava se vrijeme izvršavanaj algoritma (tj
broj poteza potrebnih za sloziti kolutove) Tower of Hanoi. Pravila:
- premjestiti sve kolutove s prvog nosača na treći, ali tako da u svakom potezu
smije se pomaknuti samo jedan kolut, i da veći kolut nikada ne može doći na
manji kolut.
With three disks, the puzzle can be solved in seven moves

O(log
2
n) – Logaritamski algoritam (Binarno pretraživanje)
Logaritam nekog pozitivnog relanog broja x u nekoj bazi b je broj y kojim se treba
potencirati bazu da bi dobili zadanu vrijednost x:
y = log
b
(x)
log
10
(10)= log
10
(10
1
)=1
log
10
(100)= log
10
(10
2
)=2
...
(logaritam od n po bazi 2)
Vrijeme za izvršavanje algoritma povećava se u skladu s log
2
(n). Npr. izvršavanje
za 1024 broja (podatka) traje otprilike dvostruko dulje od 32 broja (podatka) jer
log
2
(1024)=10 i log
2
(32)=5
Opća koncepcija logaritamskih algoritama je slijedeća:
1. Obaviti postupak kojom se veličina problema prepolovi.
2. Nastaviti razlaganje problema dok se ne dođe do veličine 1.
3. Obaviti završnu obradu s problemom jedinične veličine.

Niz mora biti sortiran.
1 2 3 4 5 6 7 (trazimo broj 7)
5 6 7
7

O(n log
2
n) - Linearno-logaritamski algoritmi
Slično kao i kod logaritamskih algoritama i ovdje je ukupan broj polovljenja log
2
n,
ali kako se pri svakom polovljenju sekvencijalno obrade svi podaci, to je ukupan
broj elementarnih obrada jednak nlog
2
n. Primjer za ovakav algoritam je Quicksort
(sortiranje).
log
2
(8)=3 * n (8) = 24 (nlog
2
n) puno manje od 64 (n
2
Algoritam kvadratne
složenosti)
quicksort vs bubblesort
za n = 64, log
2
n = 6 < nlog
2
n = 384 < n
2
= 4096
O(n!) – Faktorijelni algoritmi
Faktorijela od 5 ce biti 5*4*3*2*1=120. Dakle ako obrađujemo 5 podataka (brojeva) a
algoritam je faktorijelni onda bi to zahtijevalo 120 koraka obrade. Potrebno je pronadi
bolje rješenje algoritma. Solving the traveling salesman problem via brute-force search .
Dakle, trgovački putnik mora obidi n gradova tako da završi u onom u kojem je i počeo, te
da svaki grad (osim prvoga) obiđe samo jednom. Svaka dva grada povezuje jedna cesta
tako da je mnogo različitih načina na koje naš trgovački putnik može posjetiti sve
gradove, no njegov je cilj prijedi što manje kilometara i vratiti se kudi što prije. Za n
gradova takvih je puteva n!. Tako bismo za 5 gradova morali izračunati duljine 5! = 1 * 2 *
3 * 4 * 5 = 120 različitih puteva. Neupotrebljiv vec za 20 gradova...

Za algoritme slozenosti O(n) kazemo da imaju linarnu slozenost, za O(n2)
kvadratnu, za O(n3) kubnu, za O(nk) za neko k polinomijalnu, a za O(log n)
logaritamsku
n - nekakva mjera za ulazne podatke (npr. duzina niza cijelih brojeva)
O(1) - konstantno vrijeme izvođenja
O(n^c) - polinomijalno vrijeme izvođenja
O(c^n) - eksponecijalno vrijeme izvodjenja
slozenost algoritma jest naprosto broj osnovnih računskih koraka koje algoritam izvodi prilikom
prijelaza od ulaznih podataka do izlaznih rezultata

Na početku složenost algoritma definisademo neformalno kao maksimalni broj operacija potrebnih za
izvršavanje algoritma