Professional Documents
Culture Documents
Algoritmi Sortiranja
Algoritmi Sortiranja
SORTIRANJE
j=2..15
j=3..15
j=4..15
j=5..15
j=6..15
j=7..15
j=8..15
j=9..15
j=10..15
j=11..15
j=12..15
j=13..15
j=14..15
j=15..15
1
A
(A)
(A
(A
(A
(A
(A
(A
(A
(A
(A
(A
(A
(A
A
2 3
S O
S O
A) O
A E)
A E
A E
A E
A E
A E
A E
A E
A E
A E
A E
A E
4 5
R T
R T
R T
R T
E) T
E G)
E G
E G
E G
E G
E G
E G
E G
E G
E G
6
I
I
I
I
I
I
I)
I
I
I
I
I
I
I
I
7 8 9 10 11 12 13 14 15
N G E X A M P L E Min=1
N G E X A M P L E Min=11
N G E X S M P L E Min=9
N G O X S M P L E Min=15
N G O X S M P L R Min=8
N T O X S M P L R Min=6
N T O X S M P L R Min=14
L) T O X S M P N R Min=12
L M) O X S T P N R Min=14
L M N) X S T P O R Min=14
L M N O) S T P X R Min=13
L M N O P) T S X R Min=15
L M N O P R) S X T Min=13
L M N O P R S) X T Min=15
L M N O P R S T X
(A)
(A)
(E)
(E)
(G)
(I)
(L)
(M)
(N)
(O)
(P)
(R)
(S)
(T)
BUBBLE SORT
Bubble (mjehur) sort se sastoji iz sljedeih koraka:
1. Tokom prolaza kroz listu sortiraj dva susjedna elementa,
2. Ponavljaj ovakve prolaze sve dok se ne doe do prolaza u kome vie nema
sortiranja.
Brzina izvrenja algoritma je N2.
Primjer: E X A M P L E
Prolaz 1:
(E
X)
E
(X
E
A
E
A
E
A
E
A
Prolaz 2:
(E
A)
A
A)
(X
M
M
M
M
M
M
M)
(X
P
P
P
P
P
P
P)
(X
L
L
L
L
L
L
L)
(X
E
E
E
E
E
E
E)
X
Prolaz 3:
Prolaz 4:
Prolaz 5:
Rezultat:
A
A
A
A
A
(A
A
A
A
A
A
(A
A
A
A
A
A
(A
A
A
A
A
A
A
(E
E
E
E
E
E)
(E
E
E
E
E
E)
(E
E
E
E
E
E)
(E
E
E
E
E
E
M)
(M
M
M
M
M
M)
(M
L
L
L
L
L)
(L
E
E
E
E
E)
(E
E
E
E
E
P
P)
(P
L
L
L
L
L)
(M
E
E
E
E
E)
(L
L
L
L
L
L)
(L
L
L
L
L
L
L)
(P
E
E
E
E
E)
(M
M
M
M
M
M)
(M
M
M
M
M
M)
(M
M
M
E
E
E
E)
(P
P
P
P
P
P)
(P
P
P
P
P
P)
(P
P
P
P
P
P)
(P
P
X
X
X
X
X)
X
X
X
X
X
X)
X
X
X
X
X
X)
X
X
X
X
X
X)
X
QUICK SORT
Quick (brzi) sort je algoritam za brzo sortiranje koji je pronaao C.A.Hoare, 1960
goodine.
Algoritam pripada grupi Divide & Conquer algoritama. Brzina ovog algoritma je NlogN.
Sastoji se iz sljedeih koraka:
1. U zadatoj listi nai i-ti element koji je na svojoj finalnoj sortnoj poziciji,
2. Krenuti u lijevu podlistu (Left,i-1) i primjeniti isto,
3. Po istom principu krenuti na desnu podlistu (i+1,Right).
SEKVENCIJALNO PRETRAIVANJE
Najjednostavniji algoritam je sekvencijalno pretraivanje (bez duplikata). Ono se
sastoji u prolasku kroz listu od poetka do kraja dok se ne nae dati element. Kada pronaemo
element vraamo njegovu poziciju. U sluaju da elementa nema u listi vratimo poziciju nula.
Kod sekvencijalnog pretraivanja, ako imamo N podataka u listi, u najgorem sluaju
moraemo proi svih N podataka. U prosjeku treba ispitati N/2 elemenata.
Primjer: Traimo slovo E u listi ASEARCHINGEXAMPLE.
Pretraujemo od pozicije 1. Kad naiemo na slovo E (3. pozicija), onda idemo dalje sa
pretraivanjem od 4. pozicije i pretraujemo da li ima duplikata.
Implementacija pretrage u C-u:
int sekPretraga(int niz[], int duzina, int meta)
{
for(int i = 0; i < duzina; i++)
{
if(niz[i] == meta)
return i;
}
return -1;
}
BINARNO PRETRAIVANJE (BINARY SEARCH)
Binarno pretraivanje pripada grupi Divide & Conquer algoritama. Preduslov je da
lista bude sortirana. Ovaj algoritam ima vrijeme pretraivanja logN.
Algoritam se sastoji iz sljedeih koraka:
1. Podijeli listu na dva jednaka dijela (nalazimo element na poziciji n DIV 2),
2. Ako je ovaj element traeni, pretraivanje je zavreno,
3. Ako nije, onda, ako je element manji od srednjeg pretraujemo lijevu
podlistu (1, (n DIV 2)-1), u protivnom desnu podlistu ((n DIV 2) +1, n),
4. Ako se doe do kraja konstatujemo da nema tog elementa.
14
P
P
P
15
R
R
R
16
S
S
S
17
X
X
X
Nalazimo na 16. poziciji slovo S, ali, ako, na primjer, traimo slovo E ne zna se koji je
duplikat pronaen.
Primjer: Traimo slovo E u prethodnoj listi.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
A A A C E E E G H I L M N P R S X
(1+17) DIV 2 = 9 A A A C E E E G
(1+8) DIV 2 = 4
E E E G
(5+8) DIV 2 = 6
E
Od njega se mora pogledati i lijevo i desno da se vidi ima li jo duplikata.
Implementacija u C-u:
#include<iostream.h>
#include<conio.h>
int binPretraga(int *, int, int);
int main()
{
int duzina;
int meta;
cout<<"Unesite duzinu sortiranog niza:";
cin>>duzina;
int *niz = new int[duzina];
for(int i = 0; i < duzina; i++)
{
cout<<"Unesi broj:";
cin>>niz[i];
}
cout<<"Unesi broj za pretragu:";
cin>>meta;
int index = binPretraga(niz, duzina, meta);
if(index >= 0)
cout<<"Broj je pronadjen na mjestu:"<<index + 1<<endl;
else
cout<<"Meta nije pronadjena!"<<endl;
getch();
}
int binPretraga(int *niz, int duz, int meta)
{
int poc = 0, kraj = duz - 1;
int sredina, razlika;
while(kraj >= poc)
{
sredina = (poc + kraj)/2;
razlika = niz[sredina] - meta;
if(razlika == 0)
return sredina;
else if(razlika > 0)
kraj = sredina - 1;
else if(razlika < 0)
poc = sredina + 1;
}
return -1;
}
LISTA
Def.: Lista je konaan skup od n (n0) elemenata koje moemo oznaiti sa a 1, a2, ...,
an, ija je osnovna strukturna osobina da su linearno ureeni.
Tako, na primjer, ako je n>0 onda je element a 1 prvi element u listi, an je zadnji
element u listi, a za 1<k<n kaemo da je a k k-ti element, pri emu se ispred njega nalazi a k-1 a
iza njega ak+1 element.
U optem sluaju svi elementi liste su istog tipa. Npr. moemo posmatrati listu iji su
elementi slova, brojevi, slogovi, liste itd.
Postoje razliiti naini predstavljanja liste. Odabraemo nain koji listu oznaava sa
zagradama, a elemente liste razdvaja zarezima.
Primjer:
- lista brojeva B=(1, 9, 3, 2, 7, 89),
- lista slova S=(C, A, T, S)
- lista imena I=(Sue, Pamela, John)
- lista listi L=((C, A, T, S), (R, U, N))
Prvi element liste se esto naziva glava liste (eng. head). Po dogovoru uzimamo da je
to prvi element na lijevom kraju liste.
Kada se iz zadate liste odstrani glava liste, dobijamo listu koja se zove rep (eng. tail)
zadate liste.
Primjer: Neka je data lista S=(C, A, T, S), glava liste S je element C, a rep liste je
lista (A, T, S).
Osnovne operacije sa rad na listama moemo grupisati u sljedee tri grupe:
- operacije kreiranja liste (konstruktorske operacije),
- operacije postavljanja upita nad listom (predikatske operacije),
- operacije selekcije dijelova liste (selektorske operacije).
Povezana (jednostruko, dvostruko) ili dinamika alokacija
Kod dinamike alokacije koriste se pokazivai i prostor se alocira po potrebi, tj. nema
alokacije unaprijed, jer veliki broj lista je takav da se ne zna ukupan broj elemenata. Uz svaki
element liste, rezervie se i jedan mali prostor za pokaziva, koji je zanemarljiv. Kod prazne
liste je u pokazivau na listu NIL vrijednost.
Liste, jednostruko i dvostruko spregnute, kod kojih su elementi vezani u krug, zovu se
cirkularne liste.
if(pokCvor == NULL){
cout<<"Greska sa memorijom!"<<endl;
return NULL;
}
pokCvor->broj = broj;
pokCvor->sljedeci = NULL;
return pokCvor;
}
void dodajCvor(Cvor *cvor){
if(glava == NULL){
glava = cvor;
rep = cvor;
}
else{
cvor->sljedeci = glava;
glava = cvor;
}
}
void dodajCvorPoz(Cvor *cvor, int poz){
int brojac = 2;
if(poz > brojClanova() + 1 || poz == 0){
cout<<"Nemoguce unijeti cvor na zadatu poziciju!"<<endl;
}
else{
if(poz == 1){
dodajCvor(cvor);
return;
}
else if(poz == brojClanova() + 1){
rep->sljedeci = cvor;
rep = cvor;
}
else{
Cvor *pret, *sljed;
pret = glava;
sljed = pret->sljedeci;
while(brojac != poz)
{
pret = pret->sljedeci;
sljed = pret->sljedeci;
brojac++;
}
cvor->sljedeci = sljed;
pret->sljedeci = cvor;
}
}
}
void ispis(){
if(praznaLista()){
cout<<"Lista je prazna!"<<endl;
}
else{
Cvor *tmp = glava;
while(tmp != NULL){
cout <<tmp->broj<<endl;
tmp = tmp->sljedeci;
}
}
}
int brojClanova(){
int brojac = 0;
Cvor *tmp = glava;
while(tmp != NULL)
{
brojac++;
tmp = tmp->sljedeci;
}
return brojac;
}
bool praznaLista(){
if(glava == NULL)
return true;
else
return false;
}
void isprazniListu(){
if(praznaLista())
cout<<"Lista je vec prazna!"<<endl;
else{
Cvor *tmp = glava;
while(glava != NULL){
tmp = glava;
glava = glava->sljedeci;
delete tmp;
}
}
}
void brisiCvor(){
if(praznaLista())
cout<<"Lista je vec prazna!"<<endl;
else{
Cvor *tmp = glava;
glava = glava->sljedeci;
delete tmp;
}
}
void brisiCvorPoz(int poz){
if(praznaLista())
cout<<"Lista je vec prazna!"<<endl;
else if(poz == 0 || poz > brojClanova()){
{
int broj;
Cvor *sljedeci;
};
Cvor *glava = NULL;
Cvor *iniCvor();
int brojClanova();
bool prazan();
void push(Cvor *cvor);
void pop();
void ispis();
void isprazniStek();
void main()
{
Cvor *cvor = NULL;
int opcija = 1;
while(opcija != 0)
{
cout<<"\t 1. Dodaj cvor u stek"<<endl;
cout<<"\t 2. Brisi cvor iz steka"<<endl;
cout<<"\t 3. Isprazni stek"<<endl;
cout<<"\t 4. Ispis"<<endl;
cout<<"\t 0. Izlaz"<<endl;
cout<<"\t Opcija:";
cin>>opcija;
switch(opcija)
{
case 1:
cvor = iniCvor();
push(cvor);
break;
case 2:
pop();
break;
case 3:
isprazniStek();
break;
case 4:
if(prazan())
cout<<"Stek je prazan!"<<endl;
else
ispis();
break;
}
}
}
Cvor *iniCvor()
{
int broj;
cout<<"Unesite broj:";
cin>>broj;
Cvor *cvor = new Cvor();
if(cvor == NULL)
{
cout<<"Nije moguce kreirati novi cvor!"<<endl;
return NULL;
}
else
{
cvor->sljedeci = NULL;
cvor->broj = broj;
return cvor;
}
}
void push(Cvor *cvor)
{
if(glava == NULL)
{
glava = cvor;
}
else
{
cvor->sljedeci = glava;
glava = cvor;
}
}
void pop()
{
Cvor *tmp = glava;
glava = glava->sljedeci;
cout<<"Cvor sa brojem:"<<tmp->broj<<endl;
delete tmp;
}
void ispis()
{
Cvor *tmp = glava;
while(tmp != NULL)
{
cout <<"Cvor: "<<tmp->broj<<endl;
tmp = tmp->sljedeci;
}
}
void isprazniStek()
{
Cvor *tmp;
while(glava != NULL)
{
tmp = glava;
glava = glava->sljedeci;
delete tmp;
}
}
bool prazan()
{
if(glava == NULL)
return true;
else
return false;
}
2. QUEUE - Lista tipa QUEUE ima dva kraja, na jednom kraju (IN) se mogu vriti operacije
dodavanja (insert) a na drugom (OUT) operacije brisanja (delete) i uzimanja vrijednosti
(fetch) elemenata. Drugi naziv za QUEUE je FIFO (First In First Out) struktura.
3. DEQUE - (D)ouble (E)nded (QUE)ue - Lista tipa DEQUE ima dva kraja, A i B, gdje se
mogu vriti operacije dodavanja (insert), brisanja (delete) i uzimanja vrijednosti (fetch)
elemenata. DEQUE se ponaa kao dva STACK-a, kod kojih su dna spojena.
rep = cvor;
}
}
void dequeue(){
Cvor *temp = glava;
cout<<"Uzimam prvi element:"<<temp->broj<<endl;
glava = glava->sljedeci;
delete temp;
}
void ispis(){
Cvor *temp = glava;
while (temp != NULL){
cout<<"Broj:"<<temp->broj<<endl;
temp = temp->sljedeci;
}
}
Implementacija DEQUEUE u C-u:
#include<iostream.h>
struct Cvor{
int broj;
Cvor *sljedeci;
};
Cvor *rep = NULL, *glava = NULL;
Cvor *iniCvor();
void enqueueFromBack(Cvor *);
void enqueueFromFront(Cvor *);
void dequeueFromFront();
void dequeueFromBack();
void ispis();
void main(){
int opc = 1;
Cvor *cvor;
while (opc != 0){
cout<<"\t 1. Dodaj element na pocetak"<<endl;
cout<<"\t 2. Dodaj element na kraj"<<endl;
cout<<"\t 3. Brisi element sa pocetka"<<endl;
cout<<"\t 4. Brisi element sa kraja"<<endl;
cout<<"\t 5. Ispis"<<endl;
cout<<"\t 0. Izlaz"<<endl;
cout<<"Opcija:";
cin>>opc;
switch(opc){
case 1:
cvor = iniCvor();
enqueueFromFront(cvor);
break;
case 2:
cvor = iniCvor();
enqueueFromBack(cvor);
break;
case 3:
if(glava == NULL)
cout<<"Red je prazan"<<endl;
else
dequeueFromFront();
break;
case 4:
if(glava == NULL)
cout<<"Red je prazan"<<endl;
else
dequeueFromBack();
break;
case 5:
if(glava == NULL)
cout<<"Red je prazan"<<endl;
else
ispis();
break;
}
}
Cvor *iniCvor(){
int br;
cout<<"Unesi broj:";
cin>>br;
Cvor *cvor = new Cvor();
if(cvor == NULL){
cout<<"Greska u memoriji!"<<endl;
return NULL;
}
else{
cvor->broj = br;
cvor->sljedeci = NULL;
return cvor;
}
}
void enqueueFromBack(Cvor *cvor){
if(glava == NULL){
glava = cvor;
rep = cvor;
}
else{
rep->sljedeci = cvor;
rep = cvor;
}
}
void enqueueFromFront(Cvor *cvor)
{
if(glava == NULL){
glava = cvor;
rep = cvor;
}
else{
cvor->sljedeci = glava;
glava = cvor;
}
}
void dequeueFromFront(){
Cvor *temp = glava;
cout<<"Uzimam element:"<<temp->broj<<endl;
glava = glava->sljedeci;
delete temp;
}
void dequeueFromBack(){
cout<<"Uzimama element:"<<rep->broj<<endl;
Cvor *temp = glava;
Cvor *prethodni = temp;
while(temp->sljedeci != NULL)
{
prethodni = temp;
temp = temp->sljedeci;
}
rep = prethodni;
rep->sljedeci = NULL;
delete temp;
}
void ispis(){
Cvor *temp = glava;
while (temp != NULL){
cout<<"Broj:"<<temp->broj<<endl;
temp = temp->sljedeci;
}
}