Upload
ddrabic
View
246
Download
0
Embed Size (px)
DESCRIPTION
Algoritam sortiranja koji je osmislio John von Neumann 1945. godineSloženost O(n log n)
Citation preview
Merge sort i
primjene
Što je to?
Algoritam sortiranja koji je osmislio John von Neumann
1945. godine
Složenost O(n log n)
Divide and conquer tip algoritma
Osnovni princip
Podijeli niz na n podnizova koji imaju samo 1 element
(koji se smatra sortiranim)
Spajaj podnizove u veće podnizove i sortiraj elemente
prilikom spajanja
Primjer
31 24 47 1 6 78 12 65
31 24 47 1
31 24
31 24
24 31
47 1
47 1
1 47
1 24 31 47
6 78 12 65
6 78 12 65
6 78 12 65
6 78 12 65
6 12 65 78
1 6 12 24 31 47 65 78
Zadatak – brojanje inverzija
Za zadani niz a[] ispiši koliko ima inverzija, tj. koliko
postoji parova brojeva (i,j) tako da je i<j => a[i]>a[j] .
Primjer: unosimo broj elemenata i elemente niza
5
2, 4, 1, 3, 5
Rješenje: imamo 3 inverzije: (2, 1), (4, 1), (4, 3)
Uputa
Pretpostavimo da znamo broj inverzija na lijevoj
polovici i na desnoj polovici niza i neka su to brojevi
inv1 i inv2
Njima još treba dodati broj inverzija prilikom spajanja
U procesu spajanja neka je i indeks lijevog podniza, a j
indeks desnog podniza. U svakom koraku spajanja, ako
je a[i] > a[j], onda ima (mid-i) inverzija (jer ako su
lijevi i desni podniz sortirani, svi elementi u lijevom
podnizu a[i+1], a[i+2] … a[mid] su veći od a[j])
Što nam sve treba?
Treba napisati dvije funkcije
Za spajanje
int merge(int arr[], int temp[], int left, int mid, int right);
niz koji
sortiramo pomoćni
niz u koji
spajamo
dva
podniza
lijeva
granica
desna
granica
sredina
Što nam sve treba?
I za dijeljenje niza u podnizove rekurzivno te zvanje merge-a
za spajanje
int mergeSort(int arr[], int temp[], int left, int right, int N)
veličina
niza Sve isto
kao kod
merge-a
Kako izgleda mergeSort
Alociramo memoriju za pomoćno polje
temp = (int *)malloc(sizeof(int)*N);
Ako je right>left izračunamo mid = (right + left) / 2
Izračunamo broj inverzija u lijevoj polovici
inv_count = mergeSort(arr, temp, left, mid, N);
Te dodamo još i broj inverzija u desnoj
inv_count += mergeSort(arr, temp, mid+1, right, N);
I spojimo ta dva podniza i dodamo na inv_count
inv_count += merge(arr, temp, left, mid+1, right);
na kraju vratimo inv_count
return inv_count;
Kako izgleda merge?
Inicijaliziramo indekse
i = left; /* i indeks lijevog podniza*/
j = mid; /* j indeks desnog podniza*/
k = left; /* k indeks rezultirajuceg niza*/
Krećemo se po lijevom i desnom podnizu tako dugo dok
jedan od njih ne dođe do kraja
while ((i <= mid - 1) && (j <= right))
Ako je lijevi element manji, kopiramo ga u temp, a ako
nije kopiramo desni i brojimo inverzije
inv_count = inv_count + (mid - i);
Na kraju kopiramo ostatak lijevog ili desnog podniza u
temp
Kopiramo sve iz temp u originalno polje arr te vratimo
inv_count
Zadatak - Rally
U Zagrebu se, tradicionalno, sve prestupne godine održava rally utrka. Vozači i ekipe se skupljaju u Donjeg gradu, gdje izlažu svoje automobile zainteresiranoj publici. Zatim svaki igrač dobiva startni broj i trka počinje. Vozači kreću ka Gornjem gradu prema startnim brojevima u razmacima po 3 minute. Nakon završetka utrke u Gornjem se gradu održava veliko slavlje nakon kojega i vozači i publika peru suđe. Tek nakon što je suđe oprano, proglašava se pobjednik utrke. Legenda kaže da će zavladati glad do sljedeće trke ako se pobjednik proglasi prije nego li je oprano svo posuđe.
Međutim, Ministarstvo prometa i veza smatra da je trka preopasna i želi ju zabraniti uz obrazloženje da je raspon od 3 minute premali i dovodi do mnogo jako rizičnih pretjecanja. Ako bi se interval povećao na 7 minuta, trka bi trajala do kasno u noć i nitko ne bi ostao prati suđe. Potrebno je uvjeriti predstavnike Ministarstva da i pored raspona od 3 minute ne dolazi do velikog broja pretjecanja.
Poznati su podaci vezani uz zadnju održanu trku, tj. broj vozača N (1 ≤ N ≤ 100000) i redoslijed kojim su vozači stizali u Gornji grad. Od vas se očekuje da odredite minimalan broj pretjecanja koji se mogao dogoditi na danoj trci.
Ulaz i izlaz
Ulaz: U prvoj liniji nalazi se broj vozača N. U svakoj od
sljedećih N linija nalazi se po jedan broj - u i+1-oj liniji,
startni broj vozača koji je i-ti stigao u Gornji grad.
Izlaz: U prvoj i jedinoj liniji potrebno je ispisati ostatak
minimalnog broja pretjecanja pri dijeljenju sa 10000.
Napomena: Automobili su obilježeni startnim brojevima
od 1 do N, i tim redom kreću sa starta. U prilog trci ide i
podatak da u svakom pretjecanju sudjeluju samo dva
vozača. Još se nije dogodilo da neko od vozača ne završi
trku!
Test primjeri
Ulaz
5
4
3
2
1
5
Izlaz
6
Ulaz
2
2
1
Izlaz
1
Uputa
Očito je da se u zadatku traži broj zamjena mjesta
susjednih elemenata potrebnih za sortiranje danog niza.
Broj zamjena potrebnih za sortiranje niza jednak je
zbroju zamjena potrebnih za sortiranje dva podniza i
zamjena potrebnih za raspoređivanje elemenata.
Zadatak - Ribari
Stanovnici jednog malog sela bave se ribarenjem i programiranjem. Nakon završenog ribolova, ribari svoje čamce ostavljaju duž jedne obale uskog kanala. Svaki ribar ima jedan čamac i svoj stupić negdje duž kanala koji mu služi za privezivanje čamca, pri čemu smije vezati svoj čamac isključivo za svoj stupić. Čamci moraju biti ostavljeni tako da svaki čamac bude točno uz svoj stupić, što znači da stupić mora biti negdje neposredno pored čamca, tj. između dva kraja čamca (dozvoljeno je i da stupić bude neposredno pored nekog kraja čamca). Pošto je kanal uzak, najviše jedan čamac se može nalaziti na svakom poprečnom presjeku kanala, odnosno svi čamci moraju biti privezani neposredno do obale. Čamci se mogu dodirivati svojim krajevima.
Zbog ovakvog vezivanja čamaca nije obavezno moguće da čamci svih ribara budu vezani istovremeno. Zato su ribari zamolili svoje prijatelje programere da im izračunaju koliko najviše čamaca može istovremeno biti vezano. Međutim, programerima je ovo bio pretežak zadatak, pa su se i oni počeli baviti ribarenjem, a zadatak su prepustili vama.
Ulaz i izlaz
Ulaz:
U prvom redu zapisan je samo broj ribara n (1 ≤ n ≤ 10000).
U svakom od sljedećih n redova zapisani su prirodni brojevi li i pi (1 ≤ li, pi ≤ 100000) razdvojeni jednim razmakom, koji redom označavaju dužinu čamca i položaj (koordinatu) stupića i-tog ribara. Bilo koja dva stupića nemaju istu koordinatu.
Izlaz:
Ispisati samo jedan broj - koliko najviše čamaca može biti privezano istovremeno.
Test primjeri
Primjer1:
ulaz
5 9
2 17
6 10
3 11
2 16
4 13
5 6
izlaz
5
Primjer2:
ulaz
10
4 7
2 5
1 9
5 6
1 3
2 10
1 4
3 8
4 1
5 2
izlaz
7
Objašnjenje1:Najviše je moguće 5 čamaca da bude
istovremeno vezano, na primjer čamci 1, 2, 4, 5 i 7.
Ideja Dva su moguća rješenja
Pohlepni algoritam: Punimo skup privezanih
čamaca S. Jedan po jedan čamac pokušavamo
ubaciti u taj skup idući s lijeva na desno po
koordinatama stupića. Na početku skup S sadrži
samo najljeviji čamac privezan maksimalno u lijevo.
Neka su l i r koordinate lijevog i desnog kraja
posljednjeg ubačenog čamca, i neka trenutno
promatramo čamac opisan parom (li, pi). Ako
je pi ≥ r, tada ubacujemo i-ti čamac u skup S i
privežemo ga tako da ga postavimo što je moguće
više lijevo. Ako je pi <r, tada provjeravamo je
li li < r - l i ako jest izbacujemo posljednji čamac
iz S, i umjesto njega u S ubacujemo i-ti čamac,
također što je moguće više lijevo, a ako ne
vrijedi, i-ti čamac preskačemo.
Dinamičko programiranje: razmislite sami
Zadatak - filmovi
Kako se mali Mirko nije proslavio u matematici niti programiranju, roditelji su mu smanjili džeparac. Zato je on odlučio iskoristiti svoju veliku kolekciju DVD filmova i prodati ih po niskim cijenama. Svaki film se nalazi na jednom DVD-u, a na Mirkovom hard disku može stati najviše k filmova. Procedura prženja je sljedeća: ukoliko se traženi film nalazi na hard disku, Mirko odmah počinje sa prženjem; u suprotnom on mora naći odgovarajući DVD i presnimiti ga na hard disk. Ako na disku nema slobodnog prostora, on mora obrisati neki film. Traženje DVD-a i presnimavanje iziskuje puno vremena, i zato Mirko želi smanjiti taj broj. Na početku je njegov disk prazan.
On je napravio spisak filmova i zna točno redoslijed n kupaca koji dolaze spržiti omiljeni film. Mirko je uspio minimizirati broj prebacivanja filmova na HDD (a samim tim i čekanje kupaca). Vaš je zadatak izračunati koliko će najmanje puta Mirko ipak morati presnimiti neki film na hard disk.
Ulaz i izlaz
Ulaz:
U prvom redu se nalaze dva prirodna broja n i k. Broj n predstavlja broj naručenih filmova, a broj kj e broj filmova koji može stati na disk. U sljedećih n redova nalaze se redni brojevi filmova a[i] koje kupci uzimaju, poredani po vremenu dolaska.
Izlaz:
U prvom i jedinom redu ispisati minimalan broj presnimavanja DVD-a na hard disk.
Ograničenja:
1 ≤ n ≤ 10000
1 ≤ k ≤ 500
1 ≤ a[i] ≤ 10000
vremensko ograničenje za izvršavanje programa je 1 s.
Test podaci Primjer 1:
Ulaz
2 5
1
2
2
4
1
Izlaz
3
Primjer 2:
Ulaz
3 10
2
3
2
1
5
2
4
5
3
2
Izlaz
6
Objašnjenje:
Kako je hard disk na početku prazan, Mirko
mora presnimiti film s rednim brojem 1. Zatim,
mora presnimit film broj 2. Sljedeći kupac
naručuje film koji se već nalazi na disku, tako
da ga Mirko odmah sprži. Sljedeći kupac traži
film 4, tako da Mirko briše film broj 2 i
presnimava film broj 4. Posljednji film koji se
traži je broj 1, tako da ga Mirko ne mora
tražiti, jer se na hard disku nalaze filmovi 4 i 1.