strukture podataka i algoritmi - bilješke s predavanja

34
0. Dinamička alokacija memorije MEMORIJA - organizacija memorije može se „donekle“ shvatiti poput pješčanog sata (jer se za razliku od pješčanog sata, pijesak prosipa iz obaju dijelova, i to od rubova prema sredini – „gornji“ dio se naziva gomila, a „donji“ stog ) - varijable deklarirane pri kompajliranju nalaze se na stogu --> svaka standardna deklaracija varijable dodaje novi memorijski okvir na stog --> što je varijabla „globalnija“ to je niže na stogu --> memorija pridijeljena varijablama koje su lokalne nekoj funkciji se po završetku izvođenja te funkcije automatski oslobađa - varijable deklarirane nakon kompajliranja nalaze se na gomili --> koristi se za podatke za koje je važno da budu dostupni dulje vrijeme --> ponajviše za podatke čiji broj i veličina nisu poznati prije vremena izvršavanja --> pridijeljena memorija se ne oslobađa automatski – to je zadaća programera - ako stog i gomila toliko narastu da se preklope, dolazi do rušenja programa, a potencijalno i operacijskog sustava – ova se pojava zove CURENJE MEMORIJE - GOMILA=HEAP – korijen je najveći, svaki čvor je već od svoje djece, svaka razina je maksimalno popunjena (osim možda posljednje, a i ona s lijeva na desno) - temeljne razlike stoga i gomile: * stog je struktura podataka organizirana po LIFO principu, malen je, a pristup njemu je brz * gomila je struktura podataka koja je znatno veća po kapacitetu od stoga, ali pristup njoj je spor * varijable koje se smještaju na stog su statičke, a varijable koje se smještaju na gomilu su dinamičke STOG I RED - stog je apstraktna struktura podataka organizirana po LIFU principu (last in first out) - karakteriziraju ga dvije temeljne operacije: 1) push() – dodavanje novog elementa na vrh stoga *pseudokod: Provjeri je li stog prazan Ako stog nije prazan postavi novi čvor da pokazuje na prethodni vrh postavi vrh da bude novi čvor Ako stog jest prazan postavi vrh da bude novi čvor 2) pop() – uklanjanje trenutnog elementa s vrha stoga 1 | SPA

Upload: tena-skok

Post on 28-Apr-2015

129 views

Category:

Documents


6 download

DESCRIPTION

Bilješke za usmeni ispit iz SPA

TRANSCRIPT

Page 1: Strukture podataka i algoritmi - bilješke s predavanja

0. Dinamička alokacija memorijeMEMORIJA- organizacija memorije može se „donekle“ shvatiti poput pješčanog sata (jer se za razliku od pješčanog sata, pijesak prosipa iz obaju dijelova, i to od rubova prema sredini – „gornji“ dio se naziva gomila, a „donji“ stog )- varijable deklarirane pri kompajliranju nalaze se na stogu--> svaka standardna deklaracija varijable dodaje novi memorijski okvir na stog--> što je varijabla „globalnija“ to je niže na stogu--> memorija pridijeljena varijablama koje su lokalne nekoj funkciji se po završetku izvođenja te funkcije automatski oslobađa- varijable deklarirane nakon kompajliranja nalaze se na gomili--> koristi se za podatke za koje je važno da budu dostupni dulje vrijeme--> ponajviše za podatke čiji broj i veličina nisu poznati prije vremena izvršavanja--> pridijeljena memorija se ne oslobađa automatski – to je zadaća programera- ako stog i gomila toliko narastu da se preklope, dolazi do rušenja programa, a potencijalno i operacijskog sustava – ova se pojava zove CURENJE MEMORIJE- GOMILA=HEAP – korijen je najveći, svaki čvor je već od svoje djece, svaka razina je maksimalno popunjena (osim možda posljednje, a i ona s lijeva na desno)- temeljne razlike stoga i gomile:* stog je struktura podataka organizirana po LIFO principu, malen je, a pristup njemu je brz* gomila je struktura podataka koja je znatno veća po kapacitetu od stoga, ali pristup njoj je spor* varijable koje se smještaju na stog su statičke, a varijable koje se smještaju na gomilu su dinamičke

STOG I RED- stog je apstraktna struktura podataka organizirana po LIFU principu (last in first out)- karakteriziraju ga dvije temeljne operacije:1) push() – dodavanje novog elementa na vrh stoga*pseudokod: Provjeri je li stog prazan

Ako stog nije prazanpostavi novi čvor da pokazuje na prethodni vrhpostavi vrh da bude novi čvor

Ako stog jest prazanpostavi vrh da bude novi čvor

2) pop() – uklanjanje trenutnog elementa s vrha stoga*pseudokod: Provjeri je li stog prazan

Ako stog nije prazanpostavi vrh da pokazuje na prvog ispod sebe

Ako stog jest prazanispiši poruku o tome

- elementi stoga su objekti koji su po svojoj definiciji instance neke klase – te objekte nazivamo čvorovima- red je apstraktna struktura podataka organizirana po FIFO principu (first in first out)- karakteriziraju ga dvije temeljne operacije:1) ulaz() – dodavanje novog elementa na kraj reda*pseudokod: Provjeriti je li red prazan

Ako jestdodati novi čvor u red kao prvi i jedini

Ako nijepronaći posljednji čvor u redupostaviti posljednjeg da pokazuje na novog

2) izlaz() – uklanjanje trenutnog elementa s početka reda

1 | SPA

Page 2: Strukture podataka i algoritmi - bilješke s predavanja

*pseudokod: Isti kao kod stoga!!

TORNJEVI HANOIA- prema drevnoj legendi postoji hram boga Brahme u kojem se nalaze 3 stupa okružena sa 64 zlatna diska- svećenici premještaju diskove s jednog stupa na drugi, poštujući pravila kako bi udovoljili Brahmi--> veći disk ne smije doći na manji, već samo manji na veći- onog dana kada svećenici uspiju premjestiti sve diskove s jednog stupa na drugi, nastupit će smak svijeta- kad bi legenda bila istinita i kada bi svećenici bili toliko brzi da im treba samo 1 sekunda za premještanje diska sa stupa na stup – to bi sveukupno trajalo 600 milijardi godina

SLUČAJNI BROJEVI- slučajni brojevi već u svom imenu nose dezinformaciju (ispravnije bi ih bilo zvati pseudoslučajni brojevi)- temeljna im je karakteristika da svaki novogenerirani broj nema veze (bar ne očite) s prethodno generiranim brojem- računalo ne može generirati slučajne brojeve deterministički--> ipak postoje algoritmi za generiranje koji daju dojam slučajnosti, a zovu se linerani kongruencijski generatori

- linearni kongruencijski niz je niz brojeva koji se temelji na ponovljenom izvođenju sljedeće relacije:

m – modul, a – multiplikator, c – inkrement

--> iz gornje napisane relacije za zadane a=2, c=3, m=10 te početnu vrijednost x=5, nije teško odrediti niz brojeva koji će se generirati- vrijednosti se ponavljaju u ciklusima zato što modularna aritmetika gura generirane vrijednosti u željeni raspon- duljina ciklusa još se zove i period niza -> logično, što je period veći, nizovi brojeva se doimaju slučajnijima, budući da na prvi pogled nema uočljivog ponavljanja- najdulji mogući period za ovakav algoritam je vrijednost od m--> što je m veći, veće su šanse da period bude dulji--> valja primijetiti kako unatoč tome što je modul m=10 da je ciklus duljine 4--> ovo navodi da valja pripaziti kod odabira i modula i inkrementa

ALGORITMI SORTIRANJA- sortiramo da bi nam bilo lakše pretraživati: minimalni i maksimalni element, pojedino prezime- sortirati se može na puno načina, a svaki od njih se zove algoritam sortiranjaBUBBLE SORT - najjednostavniji i najsporiji--> šetnjom kroz niz uspoređuju se svaka dva susjedna elementa - ako nisu u željenom odnosu, zamijene se--> šetnja traje sve dok niz nije sortiranSELECTION SORT - malo složeniji, ali brži od bubble sorta--> pronađe se najmanji element u nizu, zamijeni se s prvim elementom--> procedura se nastavlja za podniz od sljedećeg elementa nadaljeINSERTION SORT - još složeniji, ali i još brži od bubble sorta--> najlakše ga je vizualizirati kroz slaganje karata--> krene se s podnizom od jednog elementa, promatra se sljedeći element te ga se umeće ili ispred ili iza u taj podniz – podniz je narastao na 2 elementa, promatramo trećeg itd.MERGE SORT - koristi taktiku „podijeli pa vladaj“--> ako je niz duljine 0 ili 1 – sortiran je--> u protivnom podijeli niz na 2 otprilike jednaka dijela (sortiraj svaki od podnizova rekurzivno primjenjujući

2 | SPA

Page 3: Strukture podataka i algoritmi - bilješke s predavanja

merge sort algoritam, spoji dva sortirana podniza u jedan niz)

SHELL SORT - unaprjeđenje insertion sorta--> umjesto da uspoređuje susjedne elem., uspoređuju se elementi udaljeni za unaprijed definirani broj mjesta--> progresivnim smanjivanjem broja koraka, dolazi se do skoro sortiranog niza kojeg se sortira insertion sortomQUICK SORT - također koristi taktiku „podijeli pa vladaj“--> odabere se element niza (pivot), elementi niza se ponovno poredaju na način da svi elementi manji od pivota završe ispred njega, a svi veći iza njega završe desno--> rekurzivno se ponavljaju ovi koraci na nastale podnizoveRADIX SORT - „totalno drukčiji od drugih“--> ne uspoređuje elemente već njihove znamenke počevši od najmanje značajne znamenke prema onoj najznačajnijoj – u tom procesu obavlja potrebne zamjene

1. Analiza složenosti algoritamaALGORITAM- ideja algoritma je fundamentalna za programiranje- riječ „algoritam“ – izvedena iz „algorism“ koja dolazi od latiniziranog imena perzijskog matematičara, a zvao se: Al-Kwarizmi (9.st.) --> zaslužan za izum algebre i uvođenje jednadžbi u matematiku- u 50-im g. prošlog stoljeća, riječ „algoritam“ bila je skoro jednoznačno povezana s Euklidovim algoritmom (za pronalazak najvećeg zajedničkog djelitelja dvaju brojeva)- Euklidov algoritam: Za 2 prirodna broja m i n, odredi njihov najveći zajednički djelitelj tj. najveći prirodni broj koji istovremeno dijeli i m i n1) [pronađi ostatak] – ako je n>m onda ih zamijeni. Neka je r ostatak pri dijeljenju m sa n. Moguće vrijednosti od r su 0,1,2,...,n-1.2) [je li ostatak 0?] – ako je r=0 algoritam završava, rješenje je broj n.3) [reduciraj] – postavi prvo m na n, a zatim n na r. Vrati se na korak 1.--> redoslijed u ovom koraku je iznimno bitan (u suprotnom bi sve vrijednosti bile iste)

- algoritam predstavlja konačan skup pravila koja se izvode u određenom redoslijedi s ciljem rješavanja nekog problema, i ima 5 važnih osobina:1) KONAČNOST - algoritam se uvijek mora završiti nakon konačnog broja koraka*Euklidov algoritam zadovoljava ovaj uvjet:--> nakon 1. koraka, vrijednost od r je manja od n--> ako r nije 0, budući da će u 3. koraku n poprimiti tu vrijednost, u ponovnom 1. koraku će n biti manji--> ovaj pripadajući niz prirodnih brojeva (n1,n2,n3) se mora kad tad prekinuti tj. kad tad će r biti 0 --> to znači da će se nakon konačno mnogo koraka pronaći djelitelj2) DEFINIRANOST – svaki korak mora biti precizno definiran, a sve radnje koje se provode moraju biti jednoznačne za svaki mogući slučaj*Euklidov algoritam zadovoljava ovaj uvjet:--> podrazumijeva se da je onome tko provodi algoritam jasno što znači podijeliti prirodan broj s drugim prirodnim brojem

3 | SPA

Page 4: Strukture podataka i algoritmi - bilješke s predavanja

--> također, potrebno je da su ti brojevi zaista prirodni brojevi--> ovo je u početnom koraku svakako istina jer taj algoritam primjenjujemo na prirodne brojeve, a nakon 1. koraka r je nenegativan cijeli broj koji mora biti prirodan ako će biti 3. koraka3) ULAZ – algoritam mora imati ulazne podatke*Euklidov algoritam zadovoljava ovaj uvjet: brojevi m i n su dani od strane korisnika4) IZLAZ – algoritam mora imati jedan ili više izlaznih podataka, usko povezanih s ulaznim podacima*Euklidov algoritam zadovoljava ovaj uvjet:--> broj n iz 2. koraka je najveći zajednički dijeljitelj početnih brojeva m i n--> ovo je lako provjeriti budući da je prema Lemi o dijeljenju m=q*n+r--> kako je za ulaz u 2. korak nužno da r bude jednak 0, tada je n očito dijeljitelj od m5) UČINKOVITOST – algoritam mora biti učinkovit i to na način da njegove radnje moraju biti dovoljno jednostavne da ih netko, u konačno mnogo vremena, može napraviti koristeći olovku i papir*Euklidov algoritam zadovoljava ovaj uvjet:--> podrazumijevane operacije jesu dijeljenje i oduzimanje prirodnih brojeva (moguće je izvesti na papiru)--> da se radi o dijeljenju realnih brojeva to ne bi bilo moguće- značenje riječi „algoritam“ nije istovjetno značenju riječi „recept“, „proces“, „metoda“, „tehnika“ itd.--> recept uglavnom posjeduje: konačnost, ulaz (jaja, brašno), izlaz (večera, kolač)--> nedostaje mu definiranost (prstohvat soli, zagrijte mlijeko u malom lončiću...)- svojstvo konačnosti u praksi i nije toliko primjereno- cjenjeniji su algoritmi s razumno mnogo koraka (algoritam koji određuje hoće li bijeli uvijek pobijediti crnog u šahu ako ne napravi ni jednu pogrešku može se završiti u konačno mnogo koraka, ali njihov broj je toliko velik da ga možda nećemo doseći za našeg života)- potrebni su nam algoritmi koji su dobri ma šta god to značilo (jednostavnost, elegancija, njegova prilagodba na različita računala, koliko se puta svaki korak izvršio) --> ovo vodi analizi algoritma*Promatranje Euklidovog algoritma:--> pod pretpostavkom da je vrijednost broja n poznata, dok m može poprimiti bilo koju vrijednost iz skupa

prirodnih brojeva, koliki je prosječni broj izvršavanja 1. koraka Euklidovog algoritma?

--> budući da promatramo sve prirodne brojeve m, potrebno prvo provjeriti postoji li smislen odg. na to pitanje

--> očito je da je nakon prvog izvođenja 1. koraka bitan samo ostatak dijeljenja m sa n, tako da je za pronaći

dovoljno: provesti algoritam za m=1,m=2,...m=n; prebrojiti koliko puta se izvršio 1. korak; podijeliti taj broj s n

--> sada je važno odrediti prirodu tog broja odnosno izraziti ga preko n

ANALIZA ALGORITMA- Algoritam M: Za zadani niz brojeva x[1],x[2],...,x[n] odredi m i j takve da vrijedi m=x[j] koji je maksimalni element tog niza, pri čemu je j najveći indeks koji zadovoljava ovaj uvjet.M1 [Inicijaliziraj] j=n, k=n-1, m=x[n]M2 [Provjera] ako je k=0 algoritam završavaM3 [Usporedba] ako je x[k] <=m idi na M5M4 [Promijeni m] j=k, m=x[k]M5 [Smanji k] k=k-1 i idi na M2

- algoritam M zahtijeva fiksnu količinu memorije tako da ćemo analizirati samo vrijeme potrebno za njegovo izvršavanje (stoga prebrojimo koliko će se puta svaki od koraka izvršiti: M1=1,M2=n,M3=n-1,M4=A,M5=n-1)- analiza ovog algoritma se uglavnom sastoji od pronalaska--> minimalne vrijednosti od A

4 | SPA

Page 5: Strukture podataka i algoritmi - bilješke s predavanja

--> maksimalne vrijednosti od A--> prosječne vrijednosti od A--> standardnu devijaciju od A (kvantitativna indikacija koliko blizu prosjeka očekujemo da će A biti)- dakle, prosječna vrijednost leži negdje između 0 i n-1- za odrediti ovo, potrebno je prvo definirati što se točno podrazumijeva pod prosjek, a za dobro definirati prosjek potrebno je napraviti određene pretpostavke o ulaznim podacima--> pretpostavimo da su svi elementi x[k] međusobno različiti--> pretpostavimo da je svaka od n! permutacija ovih elemenata jednako vjerojatna- učinkovitost algoritma M ne ovisi o preciznim vrijednostima x[k] već o njihovom međusobnom odnosu

ASIMPTOTSKI PRIKAZ- često znamo iskazati neku veličinu aproksimativno, a ne precizno, a to činimo kako bi ju usporedili s nekom drugom--> to je zgodno jer nam često nije potrebno znati precizno kakve su te veličine već samo kojeg su reda- 1894.g. u svom djelu „Analytische Zahlentheorie“, matematičar Paul Bachman uveo je vrlo zgodan zapis za aproksimacije --> radi se o O-notaciji koja omogućuje da se znak jednakosti zamijeni sa znakom ≈- općenito govoreći, zapis O(f(n)) može se koristiti kada god je f(n) funkcija prirodnog broja n--> predstavlja veličinu koja nije eksplicitno poznata, ali svakako nije prevelika- svaki put kad se pojavi O(f(n)) to znači:--> da postoje pozitivne konstante M i n0 takve da broj xn koji je predstavljen izrazom O(f(n)) zadovoljava uvjet

za sve prirodne brojeve

--> nigdje se te konstante ne preciziraju, budući da su različite za svaku upotrebu O(f(n))--> samo se podrazumijeva da postoje- O-notacija je od velike koristi pri radu s aproksimacijama budući da na vrlo sažet način opisuje pojavu koja se često ponavlja te potiskuje detalje koji su često nevažni- račun s O-notacijom je prilično jednostavan,pritom valja reći kako se radi isključivo s jednosmjernim jednadžb.- pri analizi algoritma, često je važno kazati kako se algoritam ponaša pri najgorem slučaju, odnosno pri slučaju kada je potrebno izvršiti najviše koraka--> O-notacija nam tu uvelike pomaže budući da se njome iskazuje upravo to (broj koraka algoritma pri najgorem slučaju)- valja naglasiti kako je sama O-notacija aproksimativnog tipa, tako će dva algoritma koja za svoje izvršenje nad n ulaznih podataka imaju različitu složenost, možda imati istu O-notaciju- važno zapamtiti: potencije od n rastu brže od logaritma od n, veća potencija znači brži rast, eksponencijalne funkcije rastu brže od potencija od n, faktorijeli rastu brže od eksponencijalnih funkcija

2. Sortiranje- sortiranje je postupak ponovnog raspoređivanja stvari prema nekoj njihovoj odrednici, na način da te stvari budu raspoređene uzlazno ili silazno- neke od važnijih primjena sortiranja:*rješenje problema zajedništva kod kojeg su svi elementi s istim „opisom“ doneseni odjednom--> ako je dano 10 000 elemenata u proizvoljnom poretku, pri čemu mnogi od njih imaju isti vrijednost, a potrebno je presložiti te elemente tako da svi elementi s jednakim vrijednostima budu jedan pored drugoga*uspoređivanje elemenata u jednoj ili više datoteka--> ako je nekoliko datoteka sortirano na isti način (npr. uzlazno) moguće je pronaći sve podatke koji se poklapaju u samo jednom sekvencijalnom prolazu kroz njih, bez kretanja u suprotnom smjeru*potraga za informacijom prema vrijednosti ključa (telefonski imenik)- jedna od prvih primjena sortiranja u velikim informacijskim sustavima bile ja 1960. u tvrtci Computer Sciences

5 | SPA

Page 6: Strukture podataka i algoritmi - bilješke s predavanja

Corporation- u tom desetljeću proizvođači računala su tvrdili kako više od 25% vremena u kojem njihova računala rade, otpada na sortiranje, a u nekim tvrtkama taj je postotak rastao i do 50%- odavde su se kristalizirala 3 zaključka:1) sortiranje ima mnogo važnih primjena2) ljudi sortiraju kada i ne bi trebali3) u upotrebi su neučinkoviti algoritmi sortiranja--> na 1) i 2) računarstvo nije moglo utjecati, na 3) je (razvojem novih i učinkovitijih algoritama sortiranja)- za bolje shvaćanje sortiranja potrebno je pobliže definirati problem kojeg ono ima riješiti- dano je n elemenata R1,R2,...,Rn koje treba sortirati, pri čemu se elementi često zovu zapisi (record)- svakom od zapisa Rj pripada odgovarajući ključ Kj koji usmjerava proces sortiranja-->ključevi predstavljaju neku odrednicu zapisa po kojoj se sortira. Ako zapis predstavlja studenta s imenom, prezimenom, godinom rođenja i sl. onda jedan od ključeva može biti dob ili prezime- zapise sortiranjem valja poredati na specifičan način,a ta relacija poretka (uređaja) koja se definira nad ključevima mora zadovoljavati sljedeće uvjete za bilo koja 3 ključa a,b,c*načelo trihotomije – uvijek vrijedi točno jedan od izraza a<b, a=b, a>b*tranzitivnost – iz odnosa a<b i b<c slijedi odnos a<c- cilj sortiranja je pronaći permutaciju p(1)p(2)...p(n) nad indeksima {1,2,...,n} koja će postaviti ključeve u

nepadajući poredak

- sortiranje se dodatno naziva stabilnim ako zapisi sa istim ključevima nakon sortiranja zadrže svoj isti relativni poredak u odnosu na početno stanjeVRSTE SORTIRANJA:- SORTIRANJE UMETANJEM--> brojevi se razmatraju jedan po jedan i svaki novorazmatrani broj se umeće na odgovarajuću poziciju ovisno o prethodno sortiranim elementima- SORTIRANJE IZMJENOM--> ako se za dva susjedna broja utvrdi da nisu u povoljnom međusobnom odnosu tada oni mijenjaju mjesta, a ovaj postupak se ponavlja sve dok zamjene više nisu potrebne- SORTIRANJE IZBOROM--> prvo se pronađe najmanji (najveći) element i na neki način izdvoji od ostatka, a potom se proces ponavlja za preostale elemente- SORTIRANJE SPAJANJEM- NEŠTO TOTALNO DRUGAČIJE

SORTIRANJE – UMETANJEM – INSERTION SORT- algoritmi iz ove skupine podsjećaju na algoritme korištene pri slaganju karata u trešeti ili remiju- prije razmatranja zapisa Rj

--> pretpostavljamo da su prethodni zapisi R1,R2,...,Rj-1 sortirani--> potom ga umećemo na odgovarajuće mjesto među prethodno sortirane zapise*algoritam:I1 [Vrti se u petlji po j] Obavljaj korake I2 do I5 za j=2,3,...,n a potom završi algoritamI2 [Postavi i, K, R] Postavi i=j-1, K=Kj, R=Rj (u sljedećim koracima pokušat ćemo smjestiti R na pravo mjesto, uspoređujući K sa Ki za sve pripadajuće vrijednosti od i)

I3 [Usporedi K sa Ki] Ako je idi na I5 (pronađeno mjesto za R)

I4 [Pomakni Ri, smanji i] Postavi Ri+1=Ri, i=i-1 a ako je i>0 idi na I3 (ako je i=0, tada je K najmanji do sada pronađeni ključ tako da zapis R pripada na mjestu 1)I5 [Smjesti R] Postavi Ri+1=R- ovaj se program izvršava 9B+10N-3A-9 vremenskih jedinica (N-broj zapisa koje treba sortirati, A-koliko puta se i smanjuje do 0 u koraku I4, B-broj micanja elemenata)

6 | SPA

Page 7: Strukture podataka i algoritmi - bilješke s predavanja

- vremenska složenost ovog algoritma je O(n2) za najgori slučaj

SORTIRANJE – UMETANJEM – SHELL SORT- ako je dan algoritam sortiranja koji pomiče elemente samo jednu po jednu poziciju tada će njegovo prosječno vrijeme izvođenja u najbolju ruku biti O(n2)- za unaprjeđenje su potrebni određeni mehanizmi koji pomiču elemente koji su međusobno udaljeni za puno više od jedne pozicije- 1959. Donald L. Shell objavio je rad u kojem je izložio jedan takav mehanizam, a taj algoritam njemu u čast nosi naziv Shellov sort- ideja algoritma je jednostavna:--> promatrati svako k-ti element u nizu--> tako nastale k podnizove sortirati insertion sortom--> smanjiti k i ponoviti postupak--> kada je k=1, cijeli niz sortirati insertion sortom*algoritam:S1 [Vrti se u petlji po s] Obavi korak S2 za s=t-1,t-2,...,0 a onda završi algoritamS2 [Vrti se u petlji po j] Postavi h=hs i obavljaj korake S3 do S6 za h<j<nS3 [Postavi i, K, R] Postavi i=j-h, K=Kj, R=Rj

S4 [Usporedi K sa Ki] Ako je idi na S6

S5 [Pomakni Ri, smanji i] Postavi Ri+h=Ri, i=i-h, a ako je i>0 idi natrag na S4S6 [Smjesti R] Postavi Ri+h=R- očito je da će za izvršenje programa trebati manje ili više vremena ovisno o odabiru koraka k kojima se stvaraju podnizovi--> najgori slučaj se ne može spustiti ispod O(n3/2)- istraživanja ovog problema su pokazala da je trenutno najbolji niz koraka onaj kojeg definira poljski matematičar Marcin Ciura {1,4,10,23,57,132,302,701}--> ukoliko je potrebno povećati korak, svaki sljedeći je za otprilike 2.3 puta veći od prethodnog

SORTIRANJE – IZMJENOM – BUBBLE SORT- ova familija algoritama za sortiranje koristi zamjenu ili transpoziciju kao metodu sortiranja, pri čemu sistematično zamjenjuje svaka dva elementa koja nisu u željenom odnosu, sve dok takvih parova više nema- varijacije na temu su: bubble sort i quick sort- vjerojatno najočitiji način sortiranja izmjenom je uspoređivati ključeve K1 i K2 te onda zamijeniti zapise R1 i R2 ako nisu u dobrom odnosu, a postupak nastaviti s parovima R2 i R3, R3 i R4 itd.- metoda se zove bubble sort budući da najveći elementi (ako sortiramo uzlazno) odmah isplivaju na „površinu“ poput mjehurića zraka na vodi- u najboljem slučaju će bubble sort izvršiti samo jedan prolaz kroz sve elemente, dok je načelno potrebno više prolaza- vremenska složenost u najgorem slučaju je O(n2)

SORTIRANJE – IZMJENOM – QUICK SORT- unaprijeđenje bubble sorta je algoritam quick sort kojeg je izumio C.A.R. Hoare 1962.g.- temelji se na proceduri sortiranja koja bi se mogla nazvati particijska zamjena budući da koristeći rekurziju particionira niz na dva podniza prethodno napravivši odgovarajuće zamjene- odabere se neki element koji se proglasi pivotom- potom se provjeravaju svi preostali elementi tog niza i ako su manji od njega a desno ili veći od njega a lijevo, mijenjaju mjesta s pivotom- algoritam je izrazito brz, ali i složen za analizu- vremenska složenost je u najgorem slučaju O(n2), ali brzina algoritma se strahovito ubrzava u preostalim slučajevima gdje mu je složenost reda O(n ln n)

7 | SPA

Page 8: Strukture podataka i algoritmi - bilješke s predavanja

SORTIRANJE – IZBOROM – SELECTION SORT- familija algoritama sortiranja bazirana je na ideji opetovanog izbora* klasični predstavnik je selection sort, a njegov algoritam izgleda ovako:- pronađi najmanji (najveći) ključ--> prenesi zapis s tim ključem na privremenu lokaciju--> zamijeni taj ključ vrijednošću većom (manjom) od max. broja elemenata (0)- ponovi prethodni korak--> pošto je prethodni najmanji (najveći) ključ sada postao veći (manji) od najvećeg (najmanjeg) više nije u igri-nastavi ponavljati korak 1 dok svih n zapisa nije odabrano- vremenska složenost u najgorem slučaju je O(n2)

SORTIRANJE – SPAJANJEM – MERGE SORT- spajanje podrazumijeva kombiniranje 2 ili više nizova u jedan uređeni niz (npr. spajanje nizova 503 703 765 i 087 512 677 u uređeni niz 087 503 512 677 703 765)- najjednostavniji način za ovo je uspoređivati dva najmanja elementa iz tih nizova te kao rezultat izbaciti manji od njih dva- merge sort koristi ovaj princip, ali također koristi i princip podijeli pa vladaj- polazni niz se rekurzivno komada na dva niza po pola, sve dok duljina nastalog niza nije 1- zatim se spajanjem formiraju novi podnizovi ali sada sortirani- vremenska složenost u najgorem slučaju je O(n ln n)- merge sort je prilično brz algoritam, ali mu je najveći nedostatak to što stalno stvara nove podnizove i na taj način zauzima puno memorije

SORTIRANJE – DRUGAČIJE – RADIX- algoritam drugačiji od ostalih zato što ne uspoređuje elemente već njihove znamenke (uspoređuje jedinice, pa desetice, tisućice itd.)- pošto je potrebno obaviti sve prolaze (ovisno o broju znamenaka najvećeg broja), u međustanjima se pojavljuju nelogični poreci koji se na kraju ipak srede- vremenska složenost u najgorem slučaju je O(kn) gdje je k broj znamenaka najvećeg broja*pseudokod: Odredi koliko znamenaka ima max broj = k

Petlja po i od 1 do kFormiraj niz znamenaka počevši s jedinicama (1) pa s deseticama (2) do kSortiraj taj niz znamenakaPetlja po j od 0 do n-1 po nizu brojeva

Šetaj paralelno po nizu znamenaka i nizu brojevaTraži broj sa odgovarajućom znamenkom i zamijeni ga s trenutnom (1,2,3...)

3. Vezane liste – jednostruka linearnaVEZANA LISTA- vezana lista – apstraktna struktura podataka čiji su elementi međusobno povezani jednom ili dvjema vezama--> elemente zovemo čvorovima--> prema broju veza među čvorovima liste zovemo jednostrukim ili dvostrukim--> u vezanoj listi svaki čvor poznaje samo svog prvog susjeda- listu je najlakše vizualizirati kao vlak s lokomotivom i vagonima--> cijeli vlak predstavlja listu, vagoni predstavljaju čvorove, lokomotiva predstavlja pokazivač na listu- pokazivač na listu od iznimne je važnosti--> pokazuje na prvi čvor koji pokazuje na drugi čvor koji pokazuje na treći čvor itd.--> pristup svim čvorovima u listi nije moguć bez ovog pokazivača

8 | SPA

Page 9: Strukture podataka i algoritmi - bilješke s predavanja

--> zove se head, mora biti inicijaliziran (ili pokazuje na prvi čvor u listi ili pokazuje ni na što -> null)- za listu čiji head pokazuje na null kažemo da je prazna- čvorovi u vezanoj listi sastoje se od:*barem jednog podatkovnog polja koje ga pobliže opisuje *barem jednog pokazivačkog polja koje ga povezuje s drugim čvorovima--> ukoliko je lista jednostruko vezana, to pokazivačko polje se obično zove next--> ukoliko je lista dvostruko vezana, osim polja next, postoji i dodatno pokaz. polje a koje se obično zove past- iako ne toliko važan kao head, i posljednji čvor u listi je također bitan (ima i vlastito ime: tail)- ovisno o definiciji posljednjeg čvora u listi moguća je i dodatna podjela vezanih lista na:--> posljednji je onaj koji ne pokazuje ni na jednog drugog -> linearna vezana lista--> posljednji je onaj koji pokazuje na prvog u listi -> cirkularna lista- obzirom na broj veza među čvorovima te na definiciju posljednjeg čvora, razlikujemo 4 vrste vezanih lista: jednostruko vezana linearna/cirkularna, dvostruko vezana linearna/cirkularnaZAŠTO LISTE, A NE NIZOVI??* neke operacije nad nizovima su složene--> umetanje novog elementa između 2 postojeća--> dodavanje novog elementa nakon što je „kvota“ popunjena--> brisanje postojećeg elementa* u vezanoj listi sve te operacije su znatno jednostavnije* međutim, neke operacije nad listama su opet složenije--> pristupi i-tom elementu--> sortiranje svih elemenata- temeljne operacije nad listama su: unos u listu, ispis iz liste (svih ili nekih elemenata), pretraživanje unutar liste, brisanje iz liste (jednog ili više elemenata)--> svaka od ovih operacija može se i hoće razmatrati nad svim vrstama vezanih lista

UNOS U VEZANU LISTU- prije samog unosa potrebno je prvo stvoriti novi čvor, a to podrazumijeva--> odrediti podatkovna i pokazivačka polja--> pridijeliti memorijski prostor tom novom čvoru- najzgodnije je to napraviti putem konstruktora--> prvo dobiti sve podatke od korisnika (ili od pozivne metode)--> potom ključnom rječju new stvoriti i inicijalizirati novi čvor: Student novi=new Student(i,d,m);- jednom kad je novi student stvoren, unos je moguć: na početku liste, na kraju ili unutar liste nakon nekog određenog čvora- smisleno je napraviti opću metodu za unos koja bi onda u sebi sadržavala opcije koje bi korisnik odabrao pri svakom pojedinom unosuUNOS NA POČETAK JVL LISTE1) usmjeriti novi čvor da pokazuje na prvi čvor u listi2) usmjeriti pokazivač na listu da pokazuje na novi čvor--> kad bi ovaj poredak bio obrnut, izgubili bismo vezu sa svim čvorovima koje se nalaze iza heada- unos će obavljati metoda UnosPocetak()--> kao parametre prima pokazivače na listu (head) i novog studenta (novi), kao rezultat ne vraća ništa--> analogna je metodi Push() koju smo razmatrali kod stogaUNOS NA KRAJ JVL1) odrediti posljednji čvor u listi2) usmjeriti posljednjeg na pokazuje na novog*unos na početak i unos na kraj su jednaki u slučaju kad je lista prazna! (head postavljamo na novog)- unos će obavljati metoda UnosKraj--> kao parametre prima pokazivače na listu (head) te novog studenta (novi), kao rezultat ne vraća ništa

9 | SPA

Page 10: Strukture podataka i algoritmi - bilješke s predavanja

- kako odrediti posljednji čvor? – šetamo listom i ispitujemo je li sljedbenik trenutnog čvora jednak „null“, ako jest onda je trenutni čvor ujedno i posljednji čvorUNOS UNUTAR JVL LISTE- razlikujemo 2 vrste unosa unutar liste: ispred određenog čvora i nakon određenog čvora--> možemo ih svesti na jedan: ispred n-tog => nakon (n-1)-og, nakon n-tog => ispred (n+1)-og1) pronaći traženi čvor nakon kojeg unosimo2) ako je unos prije prvog --> unos na početak3) inače: novog postaviti da pokazuje na sljedbenika, a traženog postaviti da pokazuje na novog- pronalazak n-tog čvora radi metoda Nakon()--> kao parametre prima: pokazivač na listu (head), cijeli broj nakon kojeg se novi čvor unosi (n)--> ako rezultat vraća:pokazivač na pronađeni čvor, null ako nema dovoljno čvorova u listi da zadovoljni redni b.- pozivan metoda dužna je: osigurati da se ne proslijedi negativan broj, ukoliko je n jednak 0 pozvati funkciju UnosPocetak()- unos će obavljati metoda UnosNakon()--> kao parametre prima: pokazivač na listu (head), pokazivač na novog studenta (novi)--> kao rezultat vraća: ništa ako se koristi pomoćna metoda Nakon(), bool vrijednost ako se ne koristi - unos nakon podrazumijeva:*provjeru rednog broja kojeg korisnik unosi*unos moguć najranije od nultog*unos moguć najdalje do nakon zadnjegISPIS- podrazumijeva: ispis jednog čvora, ispis svih čvorova u listi, ispis liste po polaISPIS JEDNOG- ispis točno jednog čvora obavljat će metoda IspisJednog()--> kao ulazne param. prima: čvor koji se ima ispisati, redni broj čvora koji se ispisuje; kao rezultat ne vraća ništa- parametar redni_broj_čvora ima dvostruku ulogu--> ako je 0 tada naznačujemo kako nas zanima samo ispis tog čvora, ne i njegov redni broj--> ako je >0 tada nam je bitno dodatno još ispisati i redni brojISPIS CIJELE LISTE- ukoliko je lista prazna, ispisati poruku o tome- ukoliko je lista neprazna, ispisati podatke prvog čvora- preći na idući čvor i ponavljati postupak sve dok ne dođemo do krajaISPIS LISTE PO POLA – DULJINA- odrediti ukupan broj čvorova u listi – n- ispisati čvorove: od prvog do n/2-tog i od n/2-tog do posljednjeg- u slučaju neparnog broja jedna je polovica očito duljaISPIS LISTE PO POLA – BRZI I SPORI POKAZIVAČ- uvesti dva pokazivača (brzi i spori) i oba usmjeriti na prvi čvor--> spori pokazivač pomicati za po jedan čvor prema kraju liste--> brzi pokazivač pomicati za po dva čvora prema kraju liste- pomicati oba pokazivača sve dok brzi ne dođe do null- ispisati čvorove: od prvog do sporog i od sporog do kraja- u slučaju neparnog broja jedna je polovica očito duljaPRETRAŽIVANJE1) utvrditi kriterij za pretragu2) pronaći traženi čvor3) vratiti pokazivač na njega- rezultat pretrage je null ili traženi čvor- ovisno o jedinstvenosti kriterija, moguće je dobiti više rezultata pretrage -> uzeti u obzir pri njihovu ispisu- ako je kriterija za pretraživanje matični broj, tada su stvari jednostavne

10 | SPA

Page 11: Strukture podataka i algoritmi - bilješke s predavanja

--> učitati MB sa tipkovnice, prošetati kroz listu i utvrditi postoji li takav MB (ako postoji ispisati čvor s tim mb-om, ako ne ispisati poruku da takvog nema)- ako je kriterij za pretraživanje ime ili dob, tada su stvari bitno složenije--> kojeg studenta ispisati? (prvog u listi s tim imenom, sve u listi s tim imenom), što vratiti kao rezultat?BRISANJE- pod brisanjem čvora iz liste podrazumijevamo: --> uklanjanje čvora iz liste--> oslobađanje memorije koju je taj čvor zauzimao za nas radi VS po prestanku izvođenja programa- brisati je moguće: prvi čvor u listi, posljednji čvor u listi, čvor unutar liste prema kriteriju, sve čvorove unutar liste prema istom kriterijuBRISANJE PRVOG ČVORA U LISTI- postaviti head na sljedbenika prvog čvoraBRISANJE POSLJEDNJEG ČVORA U LISTI1) pronaći pretposljednji čvor u listi2) postaviti ga da pokazuje na novogBRISANJE UNUTARNJEG ČVORA PREMA KRITERIJU1) pronaći prethodnika traženog čvora2) postaviti prethodnika da pokazuje na sljedbenika traženog čvoraBRISANJE SVIH ČVOROVA PREMA KRITERIJU- ovisno o postojanju kriterija sve dok je lista neprazna*ako brišemo bez kriterija--> ponavljati postupak brisanja prvog čvora u listi*ako je kriterij bitan--> ponavljati postupak brisanja čvora prema kriteriju--> moguće je spremiti mb-ove upitnih čvorova u pomoćni niz koji se proslijedi metodi za brisanje

4. Hash tablicaRASPRŠENO ADRESIRANJE- ili hashiranje – tehnika kojom se dani ključ K koji predstavlja dio ili cijeli podatak P, pomoću funkcije h(K) transformira u vrijednost koja predstavlja indeks tablice (niza) u koju se podatak P ima spremiti- tablica se još zove i hash tablica pri čemu se elementi tablice zovu džepovi- funkcija h još se zove i hash funkcija

HASH FUNKCIJA- funkcija najčešće djeluje nad jednim dijelom složenog tipa podataka (structa)- taj dio (ključ) može biti broj, string, ali i neki drugi struct- ciljevi hash funkcije jesu rasporediti elemente u hash tablici: proporcionalno, slučajno, ravnomjerno- funkcija koja različite ključeve K pretvara u različite indekse tablice naziva se savršenom hash funkcijom- dobru hash funkciju odlikuju:--> mali trošak računanja--> determinizam (isti ulaz -> isti izlaz)--> jednoznačnost (vjerojatnost generiranja svake izlazne vrijednosti otprilike jednaka)- najjednostavnija hash funkcija: int index=a.ključ % N; (index – mjesto u nizu na koje se smješta podatak, a – vrijednost po kojoj hashiramo, ključ – broj elemenata niza tj. hash tablice)MODULO – ostatak pri dijeljenju, h(K)=K mod T--> primarni nedostatak ove metode je što se uzastopni ključevi preslikavaju u uzastopne hash vrijednosti--> često se koristi kada se malo zna o ključevima- ovo je nedovoljno budući da ključ neće uvijek biti integer već i string

11 | SPA

Page 12: Strukture podataka i algoritmi - bilješke s predavanja

- također, korištenjem operacije modulo (%) ključevi kojim ima mnogo su stjerani u mali prostor- prema Dirichletovom principu u jedno mjesto u hash tablicu će završiti 2 ili više podataka (17%71 i 1650%71)KOLIZIJA- nastaje kada hash funkcija preslika dva ključa na istu hash vrijednost- kako se 2 podatka ne mogu pohraniti na istoj lokaciji, potrebno je pronaći način kojim se može riješiti problem kolizije, a svode se na: poboljšanje hash funkcije, modifikaciju hash tablice -> ti se načini zovu: tehnike razrješavanja kolizije

METODA MNOŽENJA1) odabrati konstantu A takvu da je 0<A<12) pomnožiti ključ K sa A3) izdvojiti mantisu broja K*A

4) pomnožiti rezultat prethodnog koraka s T te izračunati:

METODA SLAGANJA1) particionirati ključ na na dijelova k1,k2,...kn tako da svi dijelovi osim posljednjeg imaju jednak broj znamenaka2) dijelove zbrojiti kako bi se odredila hash vrijednost3) ako postoji posljednji prijenos, on se zanemaruje- broj znamenaka svakog dijela ključa ovisi o veličini hash tablice, stoga ako tablica ima 1000 džepova koji se mogu adresirati, za njihovo adresiranje su potrebne 3 znamenke – svaki dio ki (osim zadnjeg) stoga mora imati 3 znamenke- postoje 2 vrste slaganja:*shift folding – posložiti ki-ove jedan ispod drugog*boundary folding – posložitit ki-ove oko srednjeg poput presavijanja papiraADITIVNO HASHIRANJE- vjerojatno najjednostavniji algoritam za hashiranje ključeva koji su stringovi je zbrojiti vrijednosti i onda na taj zbroj primjeniti operaciju moduloXOR HASHIRANJE- umjesto zbrajanja byteova kao kod aditivnog hashiranja, ovdje se byteovi neprestano slažu kako bi dobili naizgled slučajnu hash vrijednostROTIRAJUĆE HASHIRANJE- umjesto jednostavnog slaganja svakog bytea unosa u unutarnje stanje, ovo hashiranje koristi preslagivanje unutarnjeg stanja prije slijedećeg unosaBERNSTEIN-TOREK HASHIRANJE- ovo hashiranje je vrlo pogodno kada su ključevi maleni, gdje se pokazuje boljim od ostalih hashiranja- izumio ga je Bernstein, a popularizirao TorekMODIFICIRANO BERNSTEIN-TOREK HASHIRANJE- modifikacija je u tome što umjesto zbrajanja koristimo preslagivanje pomoću XOR fukcije (nije široko rasprostranjena jer je algoritam dobar i bez modifikacije, ali ovaj ima bolju distribuciju)SHIFT-ADD-XOR HASHIRANJE- vrlo slično rotirajućem hashiranju, no koriste se druge konstante te zbrajanje umjesto preslagivanja, vrlo učinkovit algoritam1-PO-1 HASHIRANJE

KOLIZIJA – MODIFIKACIJA HASH TABLICE- dvije najčešće metode: otvoreno adresiranje i ulančavanjeOTVORENO ADRESIRANJE- kada se dogodi kolizija, otvoreno adresiranje računa novu adresu koristeći testni niz i naredni zapis posprema se na tu adresu- tablica sadrži 2 tipa vrijednosti: indikator (npr. -1) i vrijednost podatka- ako se na nekoj adresi nalazi indikator – ta lokacija je slobodna za pohranu vrijednosti

12 | SPA

Page 13: Strukture podataka i algoritmi - bilješke s predavanja

- ako se na nekoj adresi ne nalazi indikator već vrijednost--> pregledava se prva sljedeća slobodna lokacija te se na nju sprema vrijednost--> ako niti jedan džep nije slobodan – tablica se nalazi u stanju preljeva- ova tehnika se može implementirati koristeći:--> linearno testiranje (provjeravaju se sljedeća polja 1 po 1)--> kvadratno testiranje (provjerava se 1. pa 4. pa 9. pa 16. polje itd.)ULANČAVANJE - ovdje svaki element hash tablice sadrži pokazivač na vezanu listu koja sadrži sve vrijednosti koje su hashirane na istu lokaciju

5. Stabla- za razliku od vezane liste gdje svaki čvor pokazuje na najviše 2 sljedbenika, kod stabala čvorovi mogu pokazivati na proizvoljno mnogo sljedbenika- stabla su najvažnija nelinearna struktura u programiranju općenito- stablo T se definira kao konačan skup jednog ili više čvorova takvih da--> postoji jedan posebno označeni čvor koji se zove korijen--> preostali čvorovi (izuzev korijena) su particionirani u m>=0 disjunktnih skupova T1,...,Tm pri čemu je svaki od tih skupova također stablo, a naziva se još i podstablom- ova definicija je rekurzivna – definirali smo stablo preko stabla- čvorovi na koje pokazuje neki čvor u stablu se zovu njegovom djecom, a on sam njihovim roditeljem

BINARNO STABLO- postoje mnoge vrste stablastih struktura podataka, a nama je najinteresantnija UREĐENO BINARNO STABLO- binarno stablo se definira kao konačan skup čvorova koji je: ili prazan ili se sastoji od korijena i elemenata dvaju disjunktnih binarnih stabala (lijevog i desnog)- valja naglasiti da iako možda slike na to ukazuju, binarno stablo nije poseban slučaj stabla već, iako sličan, zapravo vrlo različit koncept*stablo – ne može biti prazno, uvijek postoji barem korijen, svaki čvor ima 0,1,2,3...djece*binarno stablo – može biti prazno, svaki čvor ima 0,1 ili 2 djece, razlikujemo između lijevog i desnog djeteta- u binarnom stablu razlikujemo čvorove:--> korijen – nema roditelja--> list – nema djece--> unutrašnji – nije ni korijen ni list

UREĐENO BINARNO STABLO- za binarno stablo kažemo da je uređeno ukoliko za svaki njegov čvor vrijedi da mu je u lijevoj grani dijete koje je manje od njega, a u desnoj dijete koje je veće od njega- manje i veće su relativni pojmovi, a podrazumijevaju uređaj na stablu- ako čvor predstavlja studenta, tada se manje/veće može odnositi: na dob (uređaj na N), ime (leksikografski u.)- za čvorove u uređenom binarnom stablu kažemo da su na istoj razini ako su jednako udaljeni od korijena (korijen je na razini 0, njegova djeca na 1, njegovi unuci na 2 itd.)PUTANJA – u uređenom binarnom stablu je skup čvorova počevši od korijena do nekog listaDULJINA PUTANJE – je razina lista u toj putanji +1DUBINA (VISINA) STABLA – je duljina najdulje putanje- uređeno binarno stablo je potpuno ako za dubinu stabla (D) i broj čvorova u stablu (N) vrijedi: N=2D-1- za uređeno binarno stablo kažemo da je balansirano ako se, za svaki čvor u njemu, dubina lijevog i desnog podstabla razlikuje najviše za 1UNOS U UREĐENO BINARNO STABLO- uređeno binarno stablo ne dozvoljava unos duplikata!- provjeravamo je li korijen možda null--> ako jest novi čvor postaje korijen--> ako nije provjeravamo vrijednost novog čvora i ulazimo u lijevu ili desnu granu

13 | SPA

Page 14: Strukture podataka i algoritmi - bilješke s predavanja

--> ako nema lijeve/desne grane (null) tu smještamo novi čvor--> postupak ponavljamo dok ne nađemo mjesto za novi čvorISPIS UREĐENOG BINARNOG STABLA- pošto smo ograničeni širinom prozora konzole ali ne i visinom, to ćemo ispis modificirati tako da:--> desno dijete bude gore umjesto desno--> korijen umjesto gore bude lijevo--> lijevo dijete bude dolje umjesto lijevo- rekurzivno pozivamo funkciju Ispis() koja ovim redoslijedom ispisuje čvorove

6. Pretvorba u DVCL UREĐENO BINARNO STABLO – BRISANJE- kod brisanja čvora iz uređenog binarnog stabla moguće su sljedeće 3 situacije:1) brišemo čvor koji nema djece2) brišemo čvor koji ima jedno dijete3) brišemo čvor koji ima dvoje djece- ako brišemo čvor koji nema djece -> jednostavno ga postavimo na null- ako brišemo čvor koji ima samo jedno dijete -> postavimo ga na to njegovo dijete (bilo ono lijevo ili desno)- ova 3 slučaja mogu se svesti na 2, pri čemu:--> ako čvor nema lijevo dijete, postavljamo ga na njegovo desno dijete--> ako čvor nema desno dijete, postavljamo ga na njegovo lijevo dijete- ako brišemo čvor koji ima dvoje djece, procedura je kako slijedi--> pronaći najmanji čvor u njegovoj desnoj grani tj. minD--> zamijeniti njegove podatkovne varijable s onima iz minD--> u idućem rekurzivnom pozivu izbrisati minD

UREĐENO BINARNO STABLO – LISTOVI- list je čvor koji nema djece- krenuvši od korijena:--> odrediti koliko ima listova u njegovoj lijevoj grani, a koliko u desnoj--> vratiti zbroj ta dva broja

UREĐENO BINARNO STABLO – VISINA- visina stabla je broj čvorova u njegovoj najduljoj putanji- počevši od lista:--> postaviti da mu je razina 1

--> za nadčvor postaviti da mu je razina:

--> postupno se vratiti do korijena

PRETVORBA U DVCL- ovaj zanimljiv problem predstavlja pravi izazov--> inteligentno premještanje referenci--> rad sa dvjema strukturama--> znatnu upotrebu rekurzije- pošto čvor u objema strukturama ima dva pokazivačka polja, ideja o pretvorbi nameće se sama po sebi

7. Obilasci, rotacije, balansiranost OBILASCI- obilazak u bilo kojoj strukturi podataka podrazumijeva proces „posjećivanja“ svakog čvora u strukturi točno

14 | SPA

Page 15: Strukture podataka i algoritmi - bilješke s predavanja

jednom, a s ciljem utvrđivanja vrijednosti u tom čvoru - u vezanoj listi ili nizu, obilazak je uvijek isti: kreni od prvog čvora, posjeti ga, pređi na idući čvor, i tako sve dok ne dođemo do kraja- u stablu je, baš radi prirode same strukture, obići čvorove moguće na više načina- počevši s korijenom stabla, moguća su 3 različita koraka:*posjetiti čvor*otići do lijevog djeteta*otići do desnog djeteta- ovisno o tome razmatraju li se prvo potomci po dubini (sin/unuk/praunuk) ili potomci na istoj razini (braća) razlikujemo pretraživanje: po dubini, po širiniPRETRAŽIVANJE PO DUBINI- još je dodatno dijeli na:--> preorder – korijen se razmotri prije lijevog djeteta (posjeti, idi lijevo, idi desno)--> inorder – korijen se razmotri nakon lijevog, a prije desnog djeteta (idi lijevo, posjeti, idi desno)--> postorder – korijen se razmotri nakon lijevog i nakon desnog djeteta (idi lijevo, idi desno, posjeti)PRETRAŽIVANJE PO ŠIRINI- ono podrazumijeva da se razmotre svi čvorovi na istoj razini prije prelaska na nižu razinu- također podrazumijeva upotrebu pomoćne strukture podataka, i to najčešće stoga, a zgodno je i prvo odrediti visinu/dubinu stabla

PROVJERA- uređeno binarno stablo po svojoj definiciji:--> ne dozvoljava unos duplikata--> u lijevoj grani podrazumijeva čvor „manji“ od korijena--> u desnoj grani podrazumijeva čvor „veći“ od korijena- kako provjeriti za neko binarno stablo je li uređeno?--> ako je minimum lijeve grane veći od trenutnog korijena – ne valja--> ako je maksimum desne grane manji od trenutnog korijena – ne valja--> ako lijevo podstablo nije uređeno – ne valja--> ako desno podstablo nije uređeno – ne valja

ROTACIJA- rotacija je operacija na binarnom stablu koja mijenja strukturu ali ne utječe na poredak čvorova- rotacije jedan čvor pomiče na gornju razinu, a drugog pomiče na donju- koristi se za oblikovanje stabla, posebice za smanjenje njegove ukupne visine--> ovo za rezultat ima poboljšanje performansama mnogih operacija nad binarnim stablima- razlikujemo lijevu i desnu rotaciju

BALANSIRANOST- za stablo kažemo da je balansirano ako za svaki njegov čvor, apsolutna razlika u visini njegovog lijevog i desnog podstabla nije veća od 1- stabla se mogu balansirati: pri unosu, naknadno (upotrebom rotacija)- kako provjeriti je li stablo balansirano??

8. Crveno – crna stabla BALANSIRANOST- standardna uređena binarna stabla (SUBS) su „jednostavne“ strukture podataka koje se mogu pohvaliti složenošću operacija pretrage, unosa i brisanja od O(log N)

15 | SPA

Page 16: Strukture podataka i algoritmi - bilješke s predavanja

- ovo je najčešće i slučaj, no u određenim slučajevima, SUBS degeneriraju u jednostavne vezane liste sortirane bilo uzlazno bilo silazno- ovaj problem nastaje zbog toga što SUBS pohranjuju podatke na način koji bi se mogao podrazumijevati sortiranim, pa ako su podaci koji dolaze u stablo već sortirani, tada dolazi do problema- operacije nad stablom (koje ima korijen i svaki idući ima samo lijevo/desno dijete - linearno) su jako skupe--> složenost raste s O(log N) na O(N) budući da je sada stablo de facto linearna lista--> puno je „zahvalnija“ situacija kada čvorovi imaju oba djeteta- za onakva degenerirana stabla kažemo da su nebalansirana- za stabla kojima je za svaki čvor u stablu apsolutna razlika među visinama lijeve i desne grane najviše 1, kažemo da su balansirana- u praksi je ovaj zahtjev prilično teško postići, stoga se često pribjegne alternativnom i blažem uvjetu da visina stabla bude najviše log2N- balansiranju SUBSa može se pristupiti:--> nakon što su svi čvorovi uneseni u stablo--> pri svakom pojedinom unosu/brisanju- stabla koje se balansiraju nakon svakog unosa/brisanja zovu se samobalansirajuća stabla- dva najčešća primjera samobalansirajućih stabala su: AVL stabla, crveno-crna stabla (CC stabla)- prvi način za samobalansiranje stabala je izbjeći njegovu prečestu potrebu- rezultat je struktura zvana B-stablo kod kojeg svaki čvor ima proizvoljno mnogo djece, pri čemu je red B-stabla broj djece koju čvorovi mogu imati- B-stabla jesu učinkovita što se samobalansiranja tiče jer za razliku od SUBSa imaju bitno više djece po čvoru, no s druge strane, ukoliko ta mogućnost da imaju više djece nije iskorištena tj. ako čvor od potencijalno 10 djece ima samo jedno, bespotrebno se troši velika količina memorije- sljedeći način je simetrično binarno B-stablo koje je apstrakcija B-stabla reda 4--> idejni tvorac je Rudolf Bayer- budući da sve putanje od korijena do lista sadrže isti broj čvorova, svi listovi su na istom nivou u B-stablu--> ovo je savršeno balansirano stablo, ali nije uređeno binarno stablo- osnovna ideja SBBS je da čvor može imati horizontalne ili vertikalne veze--> vertikalna veza razdvaja dva različita čvora--> horizontalna veza razdvaja čvorove koji se u B-stablu smatraju istim čvorom- budući da su SBBS prilično komplicirane strukture podataka, pojavila se potreba za nečim praktičnijim- 1978. Poznati računarci Robert Sedgewick i Leonidas Guibas došli su na ideju kako na jednostavan način apstrahirati SBBS i stvoriti strukturu kod koje je veoma jednostavno razlikovati horizontalne od vertikalnih veza--> čvorovima su dodali boju

CRVENO CRNO STABLO- svaki čvor u CC stablu odlikuje se jednim dodatnim bitom koji govori o boji čvora- tradicionalno se uzimaju crvena i crna boja, iako same boje nemaju nikakvu važnost- CC stablo je samobalansirajuće uređeno binarno stablo koje karakteriziraju sljedeća pravila:1) listovi imaju „nepostojeću“ djecu koja su po definiciji crna – zovemo ih vanjskim čvorovima2) na svakoj putanji od korijena do bilo kojeg vanjskog čvora, mora biti jednak broj crnih čvorova (crno pravilo)3) crveni čvor ne smije imati crveno dijete (crveno pravilo)- svi algoritmi koji osiguravaju balansiranost CC stabla ne smiju prekršiti nijedno od ovih pravila. Ako to vrijedi, tada je stablo CC stablo pri čemu mu visina ne može biti niža od log(N+1) ali niti viša od 2 log(N+1)- valja naglasiti kako korijen ne mora nužno biti crn, ali ako jest, to malo olakšava operacije

CRVENO CRNO STABLO – UNOS- unos i brisanje iz stabla su prilično složene operacije baš zbog uvjeta koje stablo čine crveno-crnim, no brzina pristupa čvorovima CC stabla višestruko nadoknađuje muku oko balansiranja- ako uneseni/uklonjeni čvor remeti crveno ili crno pravilo, na raspolaganju stoje 2 tehnike:--> zamjena boja danog i/ili susjednih čvorova

16 | SPA

Page 17: Strukture podataka i algoritmi - bilješke s predavanja

--> rotacija susjednih čvorova oko danog čvora- unos u CC stablo odvija se u 2 faze:1) standardni unos u uređeno binarno stablo novog čvora kojeg „po defaultu“ bojimo crveno2) promjena odnosa u stablu ovisno o bojama susjednih čvorova- u klasi čvor nužno je i dovoljno dodati samo jednu varijablu koja predstavlja boju čvorova. Izvorno se koristi tip char gdje 1 predstavlja crvenu, a 0 crnu boju- moguće je koristiti i tip bool koje je memorijski malo skuplji, ali kasnije olakšava provjeru boje danog čvora- kod unosa je potrebno koristiti rotacije u željenom smjeru i to: jednostruke, dvostruke- zgodno je imati metodu koja će provjeriti je li UBS zaista CC stablo- ta metoda mora provjeriti:--> je li stablo uopće uređeno, je li prekršeno crveno pravilo, je li prekršeno crno pravilo--> i tako za svako podstablo u stablu sve do listova. Ukoliko nešto od gornjeg nije zadovoljeno, stablo nije CC- pri unosu u CC stablo postavlja se pitanje – bojamo li novi čvor u crveno ili crno?- ako je novi čvor crn, tada se crno pravilo uvijek krši, a ostatak algoritma se fokusira na popravljanje tog prekršaja bez kršenja crvenog pravila- ako je novi čvor crven, tada se crveno pravilo možda krši, a ostatak algoritma se fokusira na popravljanje tog prekršaja bez kršenja crnog pravila1. SLUČAJ – N(10) dodajemo kao korijen* N obojamo crno (korijen ne mora biti crn, ali dogovorno se prvi čvor unesen u stablo boji crno)* sva pravila su zadovoljena2. SLUČAJ – tata od N(5) je crn* crveni uvjet vrijedi* crni uvjet nije ugrožen budući da je N crven (po defaultu)- pošto se unos u UBS odvija rekurzivno, to je uvijek potrebno spustiti se do razine lista- ovo je zapravo jako korisno budući da se pri rekurzivnom povratku možemo riješiti prekršenih pravila, a ionako se moramo vraćatiKAKO ISPITATI JE LI SE DOGODIO CRVENI PREKRŠAJ?--> ako je bilo koji čvor na putanji crven, testiraj ima li crveno dijete--> valja uočiti kako je moguće da je samo jedno od djece crveno. U protivnom to znači da stablo nije bilo CC i prije unosa novog čvoraKAKO POPRAVITI CRVENI PREKRŠAJ?1. SLUČAJ- ako je brat danog čvora crven tada njihov roditelj mora biti crn => jednostavno im zamijenimo boje

- međutim kako je jedan crni čvor postao crven, riskiramo prekršaje na višim razinama2. SLUČAJ- ako brat danog čvora nije crven, trik sa zamjenom boja neće upaliti jer bismo tada u jednoj grani dobili jedan crni čvor viška, a to je kršenje crnog pravila- potrebno je malo više truda -> rotacija

17 | SPA

Page 18: Strukture podataka i algoritmi - bilješke s predavanja

- dodatno bonus je da rotacija ne mijenja „crnu“ visinu

3. SLUČAJ- do sada je uvijek lijevo dijete bilo crveno, no što ako je crveno desno, a ne lijevo dijete?- potrebno je još malo više truda -> dvostruka rotacija

CRVENO CRNO STABLO – BRISANJE- brisanje je bitno kompliciranije od unosa!- pri unosu smo dodavali novi crveni čvor koji je možda izazivao kršenje crvenog pravila koje smo kasnije razrješavali kako bi se pojavilo- pri brisanju nemamo taj luksuz brisanja po bojama – ako brišemo crvenog super, ali ako brišemo crnog – problemi!- kod standardnog uređenog binarnog stabla, pri brisanju čvora koji ima dva djeteta:--> pronađemo maksimalni element u lijevoj (minimalni element u desnoj) grani--> premjestimo njegovu vrijednost u čvor kojeg brišemo--> potom jednostavno obrišemo taj čvor od kojeg smo kopirali vrijednost- budući da kopiranje vrijednosti ne krši ni crveni ni crni uvjet, problem brisanja se svodi na problem brisanja čvora s najviše jednom dijete-granom--> ništa ne mijenja na stvari je li to čvor kojeg smo originalno htjeli brisati ili čvor od kojeg smo kopirali vrij.- dakle, možemo pretpostaviti da brišemo čvor s najviše jednom dijete-granom:*ukoliko su jedina djeca čvora listovi --> neka neko od njih bude dijete*ukoliko brišemo crveni čvor --> zamijenimo ga njegovim djetetom koje se zasigurno crno (zašto?)*ukoliko brišemo crni čvor koji ima crveno dijete --> zamijenimo ga s tim djetetom koje moramo obojati crno(zašto?)- problemi se javljaju kada su i čvor za brisanje i njegovo dijete oboje crni, jer je onda potrebno rebalansiranje1. SLUČAJ

18 | SPA

Page 19: Strukture podataka i algoritmi - bilješke s predavanja

- i dalje postoji mogućnost kršenja crnog pravila budući da smo crnu visinu u lijevoj grani smanjili s 3 na 2- ako je roditelj brisanog ipak bio crven, tada jednostavno zamijenimo boju roditelja i brata brisanog

2. SLUČAJ- lijevi nećak crven, desni nećak i roditelj svejedno (jednostruka rotacija)

- lijevi nećak crn, desni crven, a roditelj svejedno (dvostruka rotacija)

3. SLUČAJ- brat je crven, a nećaci su mu crni (moraju biti – zašto?)

4. SLUČAJ- brat je crven, desni nećak mu je crn, a sin tog desnog nećaka crven (2 ili 3 rotacije???)

19 | SPA

Page 20: Strukture podataka i algoritmi - bilješke s predavanja

- brat je crven, desni nećak mu je crn, a jedini desni sin tog desnog nećaka je crven

CRVENO CRNO STABLO – ZAKLJUČAK- CC stabla se smatraju jednostavnijim od AVL stabala koji su im izravni konkurenti, i na prvi pogled unos je trivijalan- brisanje, pogotovo kad se razmotre baš svi slučajevi, i nije tako trivijalno- kada ih koristiti? – ako ulazni podaci imaju serije sortiranih vrijednosti, onda su CC stabla prilično dobar izbor

9. Grafovi - graf (u matematici) je reprezentacija skupa objekata u kojem su neki objekti međusobno povezani. Ti se objekti zovu vrhovi (čvorovi ili točke), a veze koje spajaju neke parove vrhova zovu se bridovi

KONIGSBERŠKI MOSTOVI- u gradu Konigsbergu stanovnici su voljeli šetati preko svakog od sedam mostova preko rijeke Pregel i njenih dviju ada-> htjeli su znati je li moguće doći od jedne do druge obale prelaskom preko baš svakog mosta, ali bez da ijedan most prijeđu dvaput- veliki matematičar Leonhard Euler je 1735.g. riješio problem davši negativan odgovor, time je postigao:--> udario je temelje današnjoj teoriji grafova, postao je persona non grata u Konigsbergu- prvo što je Euler napravio je uklonio sve „viškove“ i „smetnje“: oblik i veličina kopna je nebitna -> pretvori ih u točke, za mostove je jedino važno koje točke spajaju -> spoji točke s linijama, prikaz toka rijeke nije nužan za rješavanje

GRAFOVI- bridovi mogu biti usmjereni ili neusmjereni- neka vrhovi A,B,C,.. predstavljaju osobe A,B,C,... na nekom društvenom okupljanju--> ako je povezanost osoba A i B definirana rukovanjem tada za graf kažemo da je neusmjeren budući da su mu bridovi neusmjereni--> ako je povezanost osoba A i B definirana poznavanje tada za graf kažemo da je usmjeren budući da poznavanje osobe nije simetrična relacija- u svom najopćenitijem smislu, graf G je: uređeni par G=(V,B) gdje je V skup vrhova, B skup bridova, pri čemu su bridovi B dvočlani podskupovi skupa V- bridovi su određeni vrhovima koje spajaju; ti vrhovi se još zovu i rubovima, rubnim točkama, rubnim vrhovima- u grafu može postojati vrh koji nije povezan ni sa jednim drugim vrhomRED GRAFA je kardinalni broj od V – broj vrhovaVELIČINA GRAFA je kardinalni broj od B – broj bridovaSTUPANJ VRHA je broj bridova koji izviru iz tog vrha – ukoliko postoji brid koji spaja vrh sa samim sobom, on se broji dvaputSUSJEDSTVO – za vrhove V1 i V2 koje spaja brid b kažemo da su susjedi- za 2 brida u grafu kažemo da su susjedna ako dijele zajednički vrh- bridove u usmjerenom grafu zovemo i LUKOVIMA – za dva luka kažemo da su uzastopna ako je kraj jednog luka početak drugog luka

20 | SPA

Page 21: Strukture podataka i algoritmi - bilješke s predavanja

- za graf kažemo da je POTPUNO ako je svaki par vrhova spojen barem jednom bridom- za graf kažemo da je TEŽINSKI ukoliko je svakom njegovom bridu pridružena vrijednost (težina) – npr. cijena, duljina, kapacitet (ovisno o problemu)- graf (u računarstvu) je apstraktna struktura podataka kojoj je cilj vjerno predstaviti matematički koncept grafa- temeljne operacije:* susjed(G,x,y) – testira postoji li brid od vrha x do vrha y* susjedi(G,x) – daje popis svih vrhova u grafu G koji su povezani s vrhom x* dodaj(G,x,y) – dodaje brid od vrha x do vrha y ukoliko on već ne postoji* brisi(G,x,y) – uklanja brid od vrha x do vrha y ukoliko on već postoji* dohvati_vrh(G,x) – vraća vrijednost vrha x* postavi_vrh(G,x,a) – postavlja vrijednost vrha x na a* dohvati_brid(G,x,y) – vraća vrijednost pridruženu bridu od vrha x do vrha y * postavi_brid(G,x,y,a) – postavlja vrijednost brida od vrha x do vrha y na a

GRAFOVI - PRIKAZ- postoje dvije temeljne varijante prikaza grafa u memoriji: 1) lista susjedstva, 2) matrica susjedstvaLISTA SUSJEDSTVA- graf je prikazan kao niz elemenata- svaki element niza sastoji se od: vrha, ostalih vrhova u grafu koji su s ovim spojeni barem jednim bridom*svi ostali vrhovi tvore listuMATRICA SUSJEDSTVA- graf sa n vrhova je prikazan kao matrica od n x n elemenata- povezanost dvaju vrhova očituje se u tome što:--> ako su vrhovi Vi i Vj povezani – na mjestu ij u matrici je 1--> ako vrhovi Vi i Vj nisu povezani – na mjestu ij u matrici je 0PREDNOSTI I NEDOSTACI- matrica susjedstva troši samo jedan bit po elementu, listi treba bitno više- za n čvorova u grafu, matrici susjedstva je potrebno n2/8 byteova- ukoliko je graf rijedak, lista susjedstva troši manje prostora--> prostor za prikaz nepostojećih bridova- pronalazak svih vrhova susjednih danom vrhu--> u listi susjedstva podrazumijeva šetnju jednom listom--> u matrici susjedstva podrazumijeva razmatranje čitavog retka- određivanje postojanja veze među vrhovima--> u listi susjedstva traje proporcionalno minimumu stupnja vrhova koji se razmatraju--> u matrici susjedstva je gotovo trenutačno

10. Najkraći put – Dijkstrin algoritam NAJKRAĆI PUT- problem najkraćeg puta je iznimno važan s aspekta računarstva, a primjenjiv je u svim sferama ljudskog života--> putovanje od mjesta stanovanja do mjesta zaposlenja--> kretanje podataka od vašeg računala do nekog servera preko međuservera--> dostavno vozilo treba obaviti dostave na više adresa => kraći put, manja potrošnja goriva- sve ove, a i mnoge druge primjene svode se na traženje najkraćeg puta u grafu- vrhovi u grafu predstavljaju: raskrižja, servere, adrese- bridovi predstavljaju: udaljenost u kn, udaljenost u ms- najpoznatiji algoritam za određivanje najkraćeg puta u grafu je onaj nizozemskog računarca Edsgera Wybea Dijkstre (1930-2002)

21 | SPA

Page 22: Strukture podataka i algoritmi - bilješke s predavanja

*zaslužan je za mnoge doprinose računarstvu poput reverzne poljske notacije, ali i za izjave:--> upotreba GOTO naredba izrazito je loša i nepoželjna u programiranju--> podučavanje BASIC-a bi se trebalo tretirati kao kazneno djelo, budući da osakaćuje um to te mjere da se više ne oporaviALGORITAM SE SASTOJI OD SLJEDEĆIH 6 KORAKA:1) Svakom vrhu dodijeli udaljenost: 0 za početni vrh, a beskonačno za sve ostale2) Označi sve vrhove kao neposjećene. Postavi početni vrh

kao trenutni. Napravi skup neposjećenih vrhova koji se sastoji od svih vrhova u grafu osim početnog.3) Za trenutni vrh razmotri sve njegove neposjećene susjede i izračunaj njihovu udaljenost od početnog vrha, vodeći računa da ako bi nova udaljenost bila veća od trenutne da se onda ona ne uzima u obzir. Dodavanje udaljenosti susjedu ne rezultira njegovom posjećenošću.4) Jednom kada su razmotreni svi susjedi trenutnog vrha, označi ga kao posjećenog te izbaci iz skupa neposjećenih vrhova. Jednom posjećeni čvor se više nikada neće razmatrati te je njegova udaljenost konačna i minimalna.5) Ako je odredišni vrh označen kao posjećen ili ako je najmanja udaljenost među vrhovima u skupu neposjećenih beskonačno, tada je algoritam gotov.6) Postavi neposjećeni vrh s najmanjom udaljenošću na trenutni vrh i nastavi s korakom 3.

NAJKRAĆI PUT – ALGORITAMTraži se najkraći put u ovom usmjerenom grafu (na slici) od vrha A do vrha J:1. Udaljenost vrha A postavljena je na 0. Susjedi vrha A su B i D. Njihova udaljenost je udaljenost od čvora A.2. Sada se prvo razmatraju susjedi čvora D, budući da među susjedima od A on ima najmanju udaljenost. Susjedi od D jesu E i G, a njihova udaljenost jednaka je zbroju udaljenosti od D te same udaljenosti od D do A. D je posjećen.3. Zatim se razmatraju susjedi vrha B, a to su C i E. Pošto je E susjed i od B i od D, a put do E preko B je kraći to se udaljenost od A do E postavlja na novu, nižu vrijednost. B je posjećen.4. Sada se razmatra vrh C jer je njegova udaljenost među neposjećenim vrhovima najmanja. Njegovi susjedi su F i J. C je posjećen.5. Sljedeći na redu je vrh E. Njegovi susjedi jesu F i H. Udaljenost od F je veća preko E nego preko C pa se ne ažurira. F je posjećen.6. Sljedeći na redu je vrh J. Njegov jedini susjed jest F, a kako je put do F kraći preko J, to se njegova udaljenost ažurira. J je posjećen. Algoritam bi se mogao prekinuti ovdje jer je do svih ostalih vrhova dulje no do J.7. Sljedeći na redu je vrh F. Njegovi susjedi su J i I. Udaljenost od J je veća no trenutna pa se ne ažurira. F je posjećen. 8. Sljedeći na redu je vrh H. Njegovi susjedi su G i I. Sve udaljenosti preko H su veće od trenutnih pa se nijedan vrh ne ažurira. H je posjećen.9. Konačno, posljednji je vrh I. Njegovi susjedi su H i J. Sve udaljenosti preko I su veće od trenutnih pa se nijedan vrh ne ažurira. I je posjećen.

22 | SPA

Page 23: Strukture podataka i algoritmi - bilješke s predavanja

11. Skip liste - skip lista je struktura koja je proširenje linearne liste s ciljem ubrzavanja procesa pretrage- možemo ju koristiti gdje i balansirana stabla - one koriste vjerojatnost balansiranja odnosno uravnoteženosti prije nego točno provedenu balancu- algoritmi za ubacivanje i brisanje u skip listama su mnogo jednostavniji i znatno brži nego ekvivalentni za balansirana stabla- klasična struktura linearne liste (link liste) se sastoji od čvorova, gdje svaki čvor posjeduje neku korisnu informaciju i prosljeđuje na sljedeći čvor u listi- čvorovi su cijeli vrijeme poredani u sortiranom redu- kad dodajemo novi čvor, mjesto na koje ga dodajemo određujemo tako da ga se uspoređuje sa svim ostalim čvorovima u listi dok ne pronađemo čvor koji predstavlja kraj liste (u tom slučaju novi čvor ide na kraj liste) ili dok ne pronađemo čvor koji predstavlja kraj liste (u ovom slučaju novi čvor ubacujemo prije čvora s najvećom vrijednošću)- moguće je da je vrijednost novog čvora manja od vrijednosti prvog čvora liste, pa u tom slučaju novi čvor ubacujemo na početak liste- za lakše rukovođenje, dodajemo 2 karakteristična čvora – jedan od njih ide na početak liste i ima vrijednost koja je manja od vrijednosti bilo kojeg čvora u listi, dok drugi ide na kraj liste i ima vrijednost koja je veća od vrijednosti bilo kojeg čvora u listi- kada je lista pohranjena u sortiranom poretku i kad svaki čvor ima pokazivač prema čvoru koji je na 2. mjestu ispred u listi, ne trebamo ispitati više od (n/2)+1 čvorova (ako dodamo svakom četvrtom čvoru pokazivač prema idućem četvrtom čvoru trebamo ispitati ne više od (n/4)+2 čvorova)--> ako svaki 2i-ti čvor ima pokazivač prema sljedećem 2i-tom čvoru, broj čvorova koje trebamo ispitati može

biti reduciran na na način da poduplamo broj pokazivača -> ovakva struktura može se koristiti za brzo

pretraživanje, ali bi pri ubacivanju i brisanju bila nepraktična*čvor koji ima k pokazivača prema naprijed naziva se level k čvor- što bi se dogodilo da su slojevi čvorova izabrani slučajno, ali s istim proporcijama? – i-ti čvorni pokazivač umjesto da pokazuje na 2i-1 čvorova unaprijed, ukazuje na sljedeći čvor sloja i i višeg --> ubacivanja i brisanja bi zahtijevala samo lokalne modifikacije; sloj čvora, koji odabiremo slučajno kada ubacujemo čvor nikada se ne mijenaSKIP LISTA – link lista koja ima dodatne pokazivače koji preskaču preko prijelaznih (srednjih čvorova)- binarna stabla dobro izvode kada su elementi umetnuti slučajnim poretkom (kad bi bilo moguće ubaciti na slučajan način permutiranu listu podataka, stabla bi izvodila dobro s visokom vjerojatnošću za bilo koji unesen niz) – međutim, slučajno permutirano ubacivanje je nepraktično--> algoritmi za balansirana stabla reorganiziraju stabla na način da operacije zadržavaju određene uvjete balansa i da osiguraju dobru izvedbu- skip liste su probabilistička alternativa binarnim stablima--> one su balansirane tako da imaju slučajan broj generatora--> iako imaju u najgorem slučaju lošu izvedbu, nijedan uneseni niz ne rezultira izvedbi u najgorem slučaju (malo je vjerojatno da će skip lista strukture podataka biti znatno nebalansirana) - skip liste imaju svojstva balansa slična onima kod stabala pretrage izgrađenih slučajnim ubacivanjem, ali ne zahtijevaju da je ubacivanje slučajno

ALGORITMI SKIP LISTI- operacija SEARCH – vraća sadržaj vrijednosti pridružen željenom ključu ili failure ako ključ nije prisutan- operacija INSERT – pridružuje određeni ključ s novom vrijednošću tj. ubacuje ključ ako već nije prisutan- operacija DELETE – briše određeni ključ- svaki element je predstavljen čvorom, čiji je sloj izabran na slučajan način pri samom ubacivanju čvora i ne uzimajući u obzir broj elemenata u strukturi podataka- čvor razine i ima i prema naprijed pokazivača indeksiranih s 1/i

23 | SPA

Page 24: Strukture podataka i algoritmi - bilješke s predavanja

- u svakom pojedinom čvoru ne trebamo pohraniti njegovu razinu jer su one sačuvane u odgovarajućoj konstanti MaxLevel- razina liste – je trenutna maksimalna razina u listi (ili je 1 ako je lista prazna)- zaglavlje liste – ima pokazivače prema naprijed u razinama 1 kroz MaxLevel – u zaglavlju pokazivači prema naprijed u razinama višim od trenutne maksimalne razine liste pokazuju na NIL

• PRETRAŽIVANJE ELEMENATA*kreće od najbrže razine, traži zadnju stanicu prije tražene, spušta se na stanicu koja povezuje te 2 stanice- pretraživanje ključa unutar skip liste započinje od zaglavlja u cjelokupnom sloju u listi i nastavlja dalje tako da uspoređuje ključeve čvorova s ključem kojeg tražimo--> ako je ključ čvora manji od ključa kojeg tražimo, onda se pretraga nastavlja dalje u istom sloju--> ako je ključ čvora jednak ili veći od ključa kojeg tražimo, onda se pretraga prebacuje na jedan sloj dolje i nastavlja prema naprijed--> ovaj postupak nastavljamo sve dok se ne pronađe ključ kojeg tražimo, ako je taj ključ uopće sadržan u listi (ako on ne postoji u listi, onda se pretraga nastavlja ili dok ne dođemo do kraja liste ili dok ne pronađemo ključ čija je vrijednost veća od vrijednosti onoga koje tražimo)

• UMETANJE ELEMENATA- umetanje započinje pretraživanjem mjesta u skip listi gdje će se novi ključ/par vrijednosti ubaciti*algoritam koji koristimo za pretraživanje mjesta se razlikuje u jednoj stvari od klasičnog algoritma za pretragu: dodan je niz čvorova kako bi se vodio računa o mjestima u skip listi gdje se pretraga prebacuje na donji sloj -> ovo se radi zato što će pokazivači od tih čvorova trebati biti reorganizirani kada se u listu umetne novi čvor- prvi dio ovog algoritma isti je kao algoritam pretrage osim što ovaj koristi update[] niz kako bi zadržao vezu među čvorovima gdje se pretraga prebacuje na donji sloj- nakon što je pretraga završila, izvršava se provjera da se ustanovi da li ključ u čvoru gdje je pretraga stala, odgovara traženom ključu--> ako jest, vrijednost toga ključa je zamijenjena s novom vrijednošću--> ako ključevi ne odgovaraju, kreira se novi čvor koji se ubacuje u listu- da bi umetnuli novi čvor, randomLevel algoritmom se pronalazi njegov sloj (ako je vrijednost tog sloja veća od vrijednosti cjelokupnog sloja cijele skip liste, veze u update nizu od cjelokupnog sloja skip liste pa do novog sloja su dodijeljene tako da ukazuju na zaglavlje) -> ovo je napravljeno zato što ako novi čvor ima vrijednost veću od vrijednosti trenutnog cjelokupnog sloja skip liste, veze prema unaprijed u skip listi bi trebale ukazivati na ovaj novi čvor umjesto na NIL čvor- sljedeće, novi čvor je zapravo kreiran i spojen sa skip listom u sljedećoj „for petlji“ -> ta petlja od najdonjeg sloja skip liste pa do sloja novog čvora dodjeljuje veze prema unaprijed u tom svom putu--> prilično slično reorganizaciji veza u link listama kada se ubacuje novi čvor osim što kod skip listi imamo nizove veza koji moraju biti re-dodijeljeni umjesto samo jedne ili dvije

• BRISANJE ELEMENATA- brisanje koristi isti algoritam kao i ubacivanje; ono vodi računa o mjestu u listi gdje se pretraga prebacila u donji sloj--> ako je pronađen znak koji se treba izbrisati, onda brišemo čvor čija je vrijednost upravo jednaka tom znaku- nakon što je pronađen ključ, „for petlja“ započinje od donjeg pa do gornjeg sloja u skip listi dodjeljujući čvorove s vezama u poredak za brisanje obzirom na čvorove koji dolaze nakon--> sličan postupak kao u link listama, osim što ovdje imamo nizove likova prema čvorovima unaprijed koji moraju biti vođeni- jednom kad je sve ono napravljeno, čvor je izbrisan--> jedina stvar koja nam preostaje jest ažurirati trenutni cjelokupni sloj liste ako je potrebno

ZAKLJUČAK*za većinu aplikacija, izvršitelji se općenito slažu da su skip liste znatno jednostavnije za izvođenje nego što su algoritmi za balansirana ili samopodešavajuća stabla

24 | SPA

Page 25: Strukture podataka i algoritmi - bilješke s predavanja

- skip liste su jednostavne strukture podataka koje možemo u gotovo svim aplikacijama koristiti umjesto balansiranih stabala- balansirana stabla mogu napraviti sve što i skip liste i pritom imaju zadovoljavajuće vrijeme izvođenja u najgorem slučaju za razliku od skip listi- algoritmi skip listi su jednostavni za implementaciju, izvođenje i modificiranje (implementacija balansiranih stabala je zahtjevan zadatak i zato ih se rijetko koristi)- skip liste su u globalu brže nego klasično implementirani algoritmi balansiranih stabala

25 | SPA