You are on page 1of 6

Veleučilište Velika Gorica

Algoritmi i strukture podataka – a.g. 2019/2020.


Upute za 8. vježbu – složeni algoritmi za sortiranje

Nakon što se odradili vježbu potrebno je rješenja svih zadataka predati na Gaudeamusu i javiti se
nastavniku za pregled i obranu vježbe, u suprotnom za vježbu neće biti dodijeljen bod.

1. Merge sort

Merge sort u svojoj prvoj fazi dijeli listu na dva dijela dok ne dođe do liste dužine jednog člana.

Za početak napišimo definiciju funkcije i provjerimo da radimo sa listom koja ima više od jednog
člana:

def mergeSort(lst):

if len(lst)>1:

Listu treba podijeliti na dva dijela.

sredina = len(lst)//2

Lpol = lst[:sredina]

Dpol = lst[sredina:]

Kada imamo polovice možemo napravit rekurzivni poziv funkcije. Prvo za lijevu pa za desnu stranu.

mergeSort(Lpol)

mergeSort(Dpol)
Kada je podjela gotova, ulazimo u drugu fazu merge sorta u kojoj počinjemo sortirati liste. Trebaju
nam tri varijable koje će čuvati indekse. Indeks lijeve liste (Lb), desne liste(Db) i položaj na koji
zapisujemo članove u rezultirajućoj, spojenoj listi(Sb).

Lb=0

Db=0

Sb=0

Jedan po jedan uspoređujemo sve članove lijeve i desne liste.

while Lb < len(Lpol) and Db < len(Dpol):

Ako je član "lijeve" liste manji od desnog u rezultirajuću listu zapisujemo lijevi član i povećavamo
indeks lijeve liste.

if Lpol[Lb] < Dpol[Db]:

lst[Sb]=Lpol[Lb]

Lb=Lb+1

U suprotnom zapisujemo i povećavamo brojač desne liste (ovo će se dogoditi i u slučaju kada su
članovi obje liste jednaki).

else:

lst[Sb]=Dpol[Db]

Db=Db+1

Zadnji korak u ovoj petlji (ne u if upitu!) je povećati brojač mjesta za zapis.

Sb=Sb+1
Gornja petlja će trajati samo dok je Lb < len(Lpol) i Db < len(Dpol). U gornjoj petlji samo će jedan
brojač doći do kraja (onaj koji u ovom koraku mora biti kopiran u rezultirajuću listu).

Trebamo dodati još dvije petlje koje će, ako je potrebno (tj. ako se to nije dogodilo u prethodnoj
petlji) pomaknuti brojač druge liste i kopirati preostale članove u rezultirajuću listu. Za lijevu listu ovo
bi bilo:

while Lb < len(Lpol):

lst[Sb]=Lpol[Lb]

Lb=Lb+1

Sb=Sb+1

Iza ove petlje treba još dodati petlju koja radi isto za desnu listu. Ovu petlju napišite sami.

2. Quick sort

Za implementaciju quick sorta napisati ćemo tri funkcije koje se međusobno pozivaju.

• quickSort() - koja će pripremiti indekse liste za sortianje i, jednom, pozvati quickSortMain.

• quickSortMain() – koja će odraditi rekurzivne pozive sebe i funkcije koja odrađuje sortiranje.

• QuickSortSplit() - koja će odraditi samo sortiranje (usporedbu članova sa pivotom) i vratiti


novu točku podjele.

Funkcija quickSort samo priprema pokazivače, tj. ulazne parametre za funkciju quickSortGlavni:

def quickSort(lst):

quickSortMain(lst,0,len(lst)-1)
Na ovaj način smo pripremili pokazivače da ne bi morali raditi isječke (splice) liste. U funkciji
quickSortMain umjesto isječaka možemo predati indekse granica liste.

def quickSortMain(lst,prvi,zadnji):

if prvi<zadnji:

tocka = quickSortSplit(lst,prvi,zadnji)

quickSortMain(lst,prvi,tocka-1)

quickSortMain(lst,tocka+1,zadnji)

Ova funkcija radi rekurzivne pozive dok se indeksi, prvi i zadnji, ne preklope (tada smo gotovi sa
sortiranjem). U prvom koraku pozvati će se funkcija quickSortSplit koja će nam vratiti novu točku
podjele.

Napišimo funkciju quickSortSplit.

def quickSortSplit(lst,prvi,zadnji):

Trebaju nam četiri varijable. Za pivot uzmimo prvi član liste.

pivot = lst[prvi]

Nakon pivota trebaju nam indeksi članova za usporedbu. Lijevi i desni.

Lc = prvi+1

Dc = zadnji

Dodajmo još i kontrolnu varijablu "gotov" koja će prekinuti while petlju kada se indeksi prekriže.

gotov = False
Najvažniji dio quickSorta je slijedeća petlja. Petlja pomiče indekse dok god su oni manji (tj. veći
ovisno govorimo li o lijevom ili desnom) i na kraju im (ako je potrebno) mijenja mjesta da bi s desne
strane pivota bili svi članovi koji su veći a s lijeve svi koji su manji.

while not gotov:

U glavnu petlju dodajmo petlju koja pomiče lijevi indeks dok god su članovi sa te strane manji od
pivota ili je lijevi indeks postao veći od desnog.

while Lc <= Dc and lst[Lc] <= pivot:

Lc = Lc + 1

Iza ove petlje treba nam petlja koja će to odraditi za desnog člana. Vaš zadatak je napisati tu petlju
samostalno. Pazite, ova petlja se ponavlja dok su članovi sa desne strane veći od pivota i desni indeks
je veći ili jednak lijevom.

Kada su obje petlje gotove provjerimo jesu li se indeksi prekrižili. Ako jesu možemo završiti glavnu
petlju. Ne koristimo break jer ovaj if ima else izraz.

if Dc < Lc:

gotov = True

Ako su petlje koje pomiču indekse gotove a članovi se nisu prekrižili, to znači da smo našli članove
koje treba zamijeniti. Ovu zamjenu obavimo u else izrazu gornjeg if upita.

else:

temp = lst[Lc]

lst[Lc] = lst[Dc]

lst[Dc] = temp
Na kraju moramo još postaviti pivot na indeks na kojem su se članovi prekrižili te vratiti desni indeks,
njega ćemo iskoristi kao granicu za podjelu liste pri idućem rekurzivnom pozivu.

temp = lst[prvi]

lst[prvi] = lst[Dc]

lst[Dc] = temp

return Dc

Ako se sjećate funkcije quickSortGlavni znate da će ona primiti ovaj indeks i prema njemu napraviti
rekurzivni poziv koji će glavnu listu pretvoriti u dvije manje.

3. Mjerenja

Kada su funkcije gotove odradite mjerenja vremena izvršavanja. Funkcije ugradite u vježbu 6 ili 7
(jednostavni algoritmi za sortiranje ili analiza algoritama) te usporedite vrijeme izvršavanja s
jednostavnim algoritmima za sortiranje.

Rezultat bi mogao biti:

Unesite velicinu liste: 10000

['bubble', 11.49, 11.22, 11.5, 11.44]


['select', 5.52, 5.25, 5.44, 5.43]
['insert', 6.28, 6.09, 6.17, 6.22]
['merge', 0.07, 0.06, 0.06, 0.06]
['quick', 0.03, 0.04, 0.04, 0.04]

You might also like