Bubble sort Razmotrimo još jedan vrlo popularan algoritam sortiranja podataka, vrlo sličan prethodnom algoritmu. Algoritam je poznat pod nazivom Bubble sort algoritam (algoritam mehurastog sortiranja), jer u njemu mali brojevi kao da isplivavaju na vrh, a vrh je početak liste. Polazimo sa desne strane, uporedjujemo poslednja dva člana i manji pomeramo u levo. Zatim, taj manji element uporedjujemo sa elementom sa njegove leve strane i, opet, manji pomeramo u levo. Postupak nastavljamo dok ne stignemo do prvog elementa. Postupak ponavljamo, polazeći sa desne strane, sve dok ne dodjemo do drugog člana liste, čime drugi po veličini element izbija na drugu poziciju. Proces ponavljamo sve dok ne sortiramo celu listu.
Bubble sort(cont.) Problem implementacije je u tome što se kroz listu prolazi u obratnom smeru. Zato uvodimo oblik iskaza sa negativnim korakom "step -1". Procedure BubbleSort END; Napomena for i := 2 to n do for j := n to i step 1 IF a j < a j 1 THEN zameniti mesta za a j i a j 1 Kompleksnost ovog algoritma ista je kao kod sortiranja selekcijom, tj. O(n 2 ).
Quick sort Naredni algoritam je Quick sort algoritam (algoritam brzog sortiranja). Ovaj algoritam ćemo definisati rekurzivno. Postupak se zasniva na uzimanju poslednjeg elementa liste a l, a zatim sve elemente manje ili jednake a l pomeramo levo od njega. Novodobijenu listu označimo sa S 1. Svaki element veći od a l pomeramo desno od njega i dobijenu listu označimo sa S 2. Primenjujući postupak brzog sortiranja na S 1 dobijamo još dve liste S 11 i S 12. Ponavljamo proceduru na listu S 11 i tako dalje, sve dok ne dobijemo listu S x, koja kada se podeli daje liste S x1 i S x2, pri čemu je S x1 ili sortirana ili prazna. Zatim, postupak primenjujemo na S x2 deleći je na levu i desnu stranu i prelazimo na levu stranu.
Quick sort(cont.) Postupak opet nastavljamo dok se segment liste, recimo, S y ne podeli na levu i desnu listu S y1 i S y2, pri čemu je S y1 ili sortirana ili prazna. Potom se algoritam brzog sortiranja primenjuje na S y2 itd. Kada se i leva i desna strana neke podliste sortiraju, vraćamo se na listu u kojoj ona predstavlja levu ili desnu stranu i primenjujemo istu proceduru. QuickSort(S, levi, desni) Gotovo = false IF (levi desni) THEN error pogrešni podaci v = S[desni] i = levi + 1 j = desni
Quick sort(cont.) REPEAT REPEAT i = i + 1 UNTIL (S[i] v) REPEAT j = j 1 UNTIL (j levi) or (S[j] v) IF (i j) THEN Gotovo = true ELSE razmeniti S[i] i S[j] UNTIL Gotovo razmeniti S[i] i S[desni] QuickSort(S, levi, i 1) QuickSort(S, i 1, desni)
Merge sort Merge sort ( je algoritam sortiranja sličan prethodnom, ali nešto jednostavniji. Procedura se sastoji iz deljenja liste elemenata koje sortiramo na polovine ili što je moguće bliže polovinama. Zatim svaku od ovih polovina delimo još na pola i postupak nastavljamo sve dok se svaki skup ne svede na jednoelementni. Sada se proces obrće i liste se spajaju na isti način na koji su podeljene, ali se usput učešljavaju. Promenljive l, m, r označavaće levi, desni i srednji element tekuće liste, redom, a procedura sortiranja koristi rekurziju. U toku rada ove procedure, koristćemo još jednu proceduru Merge.
Merge sort(cont.) Procedura Merge jednostavno uporedjuje prve elemente dve liste koje su već sortirane i manji od njih uklanja iz te liste i postavlja na mesto prvog elementa nove liste u kojoj će svi razmatrani elementi biti sortirani. Postupak se, zatim ponavlja, pri čemu se svaki uklonjeni element dodaje na kraj nove sortirane liste, sve dok se jedna od listi ne isprazni. Tada se ostatak druge liste dodaje novoj, sortiranoj listi.
Merge sort(cont.) PROCEDURE Merge(l, m, r) Neka je A = {a l, a l+1,... a m } i B = {a m+1, a m+2,... a r } i neka je C nova učešljana lista. IF obe liste A i B sadrže elemente THEN uporedititi prve i ukloniti manji od njih Dodati uklonjeni element na kraj liste C. IF jedna od A i B je prazna THEN ostatak neprazne liste dodati listi C. Promeniti imena elemenata liste C = {a l, a l+1,... a r }
Merge sort(cont.) PROCEDURE MergeSort(l, r) IF l < r THEN m = [l + r ] 2 Call MergeSort(l, m) Call MergeSort(m + 1, r) Call Merge(l, m, r) Primer: Neka je c, b, a, v, h, d, x, e lista koju sortiramo. Delimo je na pola: c, b, a, v h, d, x, e. Pozivamo proceduru MergeSort za sortiranje leve strane i dobijamo c, b a, v h, d, x, e, a njenim ponovnim pozivanjem je c b a, v h, d, x, e.
Merge sort(cont.) Primer: Sada više ne možemo da delimo ni levu ni desnu stranu, te procedurom Merge spajamo c i b i dobijamo b, c a, v h, d, x, e lista koju sortiramo. Vraćamo se na MergeSort koja je podelila levi deo na b, c i kako je završena MergeSort(l,m), pozivamo MergeSort(m+1,r)kojom se a, v deli na a v, a zatim ih spajamo i time smo završili poziv za c, b a, v,a zatim spajamo i ove liste a, b, c, v h, d, x, e. Isti postupak ponavljamo za desni deo i dobijamo h, d, e, x, a ponovnim spajanjem listi dobijamo a, b, c, d, e, h, v, x.
Merge sort(cont.) predstavlja najefikasniji algoritam sortiranja (kao i qick sort) po pitanju broja izvršenih poredjenja. Da bismo to pokazali, bez umanjenja opštosti, pokazaćemo da je n = 2 m, za neku vrednost m, jer je ovakav broj elemenata najlakše podeliti. Odavde dobijamo da je m = log 2 n. Ako posmatramo učešljavanje izvršeno u okviru inicijalnog poziva procedure sortiranja, ona učešljava dve liste od kojih svaka sadrži 2 m 1 elemenata. Ako ovo smatramo prvim nivoom, u k-tom nivou imamo 2 k listi od kojih svaka sadrži 2 m k elemenata. Svako poredjenje parova listi od kojih svaka sadrži 2 m k elemenata, zahteva najviše 2 m k+1 1 poredjenja, pošto poslednji element ne poredimo ni sa čim. Na k-tom nivou, tada moramo da izvršimo 2 k 1 poredjenja, tj. vrši se najviše 2 k 1 (2 m k+1 1) = 2 k 1 (2 m (k 1) 1).
Merge sort(cont.) Prema tome, najveći broj poredjenja neće biti veći od m 2 k 1 (2 m (k 1) 1) = k=1 m 1 i=0 2 i (2 m i 1) = m 1 i=0 2 m 2 i = m2 m (2 m 1) = n log 2 n (n 1) = n log 2 n n + 1, tako da u narednom slučaju imamo O(n log 2 n) uporedjivanja.
Insert sort Poslednji algoritam sortiranja koji ćemo posmatrati je insert sort (sortiranje umetanjem). Ovaj postupak je vrlo jednostavan i u ovom sortiranju elementi podataka se uzimaju jedan po jedan i stavljaju na odgovarajuće mesto, u već formiranu listu. Dakle, za svaki element se pronalazi mesto, tako da su svi elementi manji od umetnutog elementa levo od njega, dok su svi veći desno od njega. Posmatrajmo opet niz elemenata iz prethodnog primera c, b, a, v, h, d, x, e. Najpre biramo element c i stavljamo ga u novu listu, a potom pošto je b manji od c, stavljamo ga ispred c u novoj listi i dobijamo b, c. Zatim a ide ispred b itd. U najgorem slučaju, broj poredjenja na svakom nivou je kao u Bubble sort algoritmu, tj. O(n 2 ).
Zavadi pa vladaj Kao što smo videli, većina algoritama sortiranja uključuje deljenje skupova na manje skupove, njihovo sortiranje i ponovno kombinovanje. Zavadi pa vladaj Tehnika razbijanja skupova u osnovne skupove, izvršavanja operacija nad njima i njihovog ponovnog sklapanja naziva se Zavadi pa vladaj. Procedure koje se zasnivaju na metodi zavadi pa vladaj, često zadovoljavaju rekuretnu jednačinu oblika Q n = cq n + f(n), 2 gde Q n može da predstavlja broj operacija, broj poredjenja, vremenski period ili bilo koju drugu meru. Mi ćemo Q n koristiti za oznaku broja operacija.
Zavadi pa vladaj(cont.) Funkcija f(n) predstavlja broj operacija potrebnih za deljenje nekog skupa u dva dela, a zatim, za njihovo ponovno spajanje. Oblik n pretpostavlja da skup na kome se izvršava operacija 2 delimo na dva jednaka dela. Ovaj je postupak uobičajen kod binarnih stabala, pri čemu su operacije binarne, pa se pretpostavlja da je n stepen broja 2. Interesuju nas, pre svega, slučajevi u kojima je vrednost f(n) konstantna ili je f(n) = Dn, za neku konstantu D. Slučaj f(n) = Dn znači da je broj operacija potrebnih za deljenje liste od n objekata i njihovo ponovno spajanje direktno srazmeran broju elemenata u listi. Tako rekurentna jednačina postaje Q n = cq n + Dn. (U Quick 2 sort algoritmu važi Q n = 2Q n + n.) 2