You are on page 1of 20

3.

Strukture podataka

Strukture podataka su openito gradivni blokovi od kojih su algoritmi sastavljeni. One su


u sutini sastavljene od struktura za pohranu podataka, metoda za kreiranje, modificiranje
i pristup tim podacima. Formalno govorei, strukture podataka sastoje se iz tri dijela:

Skupa operacija za manipuliranje odreenim tipovima apstraktnih objekata


Struktura za pohranu u kojima se apstraktni tipovi podataka uvaju
Implementacije svake od operacije u pogeldu strukture za pohranu podataka

Skup operacija nad apstraktnim tipovima objekata zvat emo jednim imenom apstraktni
tipovi podataka (ATP). Za razliku od njih, strukture podataka za pohranu, kao i njihovu
impelementaciju zvat emo strukture podataka za implementaciju. Kao primjer
moemo uzeti jedan niz apstraktnih tipova podataka, koji podrava manipulaciju nad
nekim skupom vrijednosti istog tipa, ukljuujui operacije za pristup lanovima tog niza,
kao i za njihovo modificiranje preko odreenog indeksa. Takoer, poznato je da programski
jezik C++, strukturu podataka za implementaciju kao to je niz brojeva, storira u
kontinualnim blokovima memorije, i koristi pokazivaku aritmetiku tako da zapravo sada
indeks pokazuje na adresu nekog bloka u memoriji raunara. Vano je napomenuti da
uvoenjem apstraktnih tipova podataka zapravo specificiramo o kojoj se strukturi radi,
koje operacije ista podupire, bez da ulazimo u detaljno funkcioniranje te struktura
podataka u smislu njene realizaciji u memoriji. Stoga, ukoliko se desi da dodje do pada
programa tokom njegovog izvravanja, programer se ne mora sputati na najnii nivo da
bi otklonio greke koje su se dogodile u memoriji raunara, ve e svoju panju fokusirati
na rad i implementaciju apstraktnih tipova podataka neophodnih za izvravanje programa.
Dakle, dobra je praksa da se rad algoritma odvoji od struktura podataka za njegovu
implementaciju, to je u literaturi poznato kao apstrakcija podataka (AP). Apstrakcija
podataka pravi razliku izmeu razliitih nivoa abstraktnog razmiljanja. Kao primjer moe
posluuti cjelobrojni tip podataka kao jedan vid apstraknog tipa podataka koji je
podran u skoro svim programskim jezicima. Kod ovog tipa, cjelobrojna aritmetika nam
dozvoljava da razmiljamo na nivou sabiranja, mnoenja, relacija uporeivanja, bez da
pretjerano razmiljamo o tome kako su brojevi predstavljeni u raunaru, kao i to kako se
vri proces mnoenja i sabiranja na niem nivou. Takoer, uvoenje apstraktnih tipova
podataka podstie modularan proces programiranja, na nain da se program razbija na
module sa dobro definiranim interfejsom. Ope je poznato da modularnost ima velike
prednosti, jer razliiti timovi programera mogu potpuno nezavisno od drugih timova pisati
i debagirati module, to nee uticati na ostatak programa. Sem toga, moduli se mogu
mijenjati drugim modulima, koji funkcioniraju slino ili ak bolje, koji su robusniji, i koji u
velikom broju sluajeva su napredniji u poreenju sa originalima.

Strukture podataka koje odreeni algoritam koristi, znaajno utiu na njegovu efikasnost,
kao i na jednostavnost njegovog razumijevanja i programiranja. Zbog ovoga je od
krucijalne vanosti koja e se struktura podataka koristiti tokom rjeavanja nekog
geometrijskog problema. Ope je poznato da objektno-orjentisani jezici, kao to su C++ i
Java, obezbjeuju odreen broj predifiniranih struktura podataka. U ovoj knjizi akcenat e
biti stavljen na C++, iako e se za rjeavanje nekih drugih geometrijskih problema koristiti
pored C++, Java i Python ija je brzina izvravanja za neke instance malo vea. Za veliki
broj problema komparativnom analizom bie pokazano da je u odnosu na CPU, Python
KOMPJUTERSKA GEOMETRIJA

superiorniji u odnosu na ostale ope poznate odnosno koritene programske jezike koji su
zastupljeni danas na tritu. Neke od predifiniranih struktura podataka su recimo cijeli
brojevi, zajedno sa operacijama za njihovo manipuliranje, kao to su aritmetiki operatori
za sabiranje, mnoenje, relacijski operatori, operatori dodjeljivanja, itd. Drugi primjeri
predefiniranih struktura su floating-point brojevi, karakteri, pokazivai, reference,
itd. Predefenirani tipovi podataka se mogu koristiti samostalno ili u kombinaciji sa drugim
strukturama podataka u cilju stavaranja kompleksnijih struktura podataka neophodnih za
rjeavanje odreenih tipova problema. U nastavku glave emo prezentirati neophodne
apstraktne tipove podataka, kao i njihove implementacije, a koje e biti osnova za rad sa
geometrijskim algoritmima. Dakle, prezentirat emo i implementirati ATP-a kao to su:
liste, stekovi i binarna stabla pretraivanja. Glavna motivacija zbog ega se uvode
ba ovi tipovi podataka lei u njihovoj efikasnosti tokom rjeavanja nekoliko geometrijskih
problema koji e biti detaljno istraeni i implementirani u ovoj knjizi. Bliskost sa
apstraktnim tipovima podataka doputa nam da opiemo problem na visokom i
apstraktnom nivou u pogledu apstraktnih operacija. Sem toga, poznavajui kako je neki
apstraktni tip podataka implementiran, dobijamo veu slobodu da se upustimo u analizu
nekih drugih struktura podataka za koje bi se moglo aproksimativno naslutiti da e biti od
koristi tokom rjeavanja nekih nepoznatih problema.

3.1 Povezane liste


Jednostruko povezane liste su su odlina dinamina struktura podataka koja se sastoji
od malih kontejnera dizajniranih da svuda mogu da se smjeste i da mogu meusobno da
se povezuju (linkuju) kada se ukae potreba za tim. Kontejneri se obino nazivaju vorovi.
vorovi unutar liste su sekvencijalno ureeni. Prvi vor u listi se naziva glava (eng. head),
dok se posljednji naziva rep (eng. tail) i ovaj vor obino pokazuje na nita, odnosno na
null. Ukoliko je lista prazna, posljednji vor pokazuje na samog sebe. Kod ovih lista svaki
vor ukazuje unaprijed na sljedei, ali ne i na prethodni. Da bismo pronali odreeni vor,
poinjemo iz poetka kreui se od vora do vora kao npr. u lovu na blago. Jedan primjer
povezane liste je niz koji se obino koristi za manipulaciju nad stavkama liste. Grafika
ilustracija jednostruko povezane liste prikazana je na slici 3.1.1.

Slika 3.1.1. Jednostruko povezana lista

Prednosti jednostruko povezane liste kao dinamike strukture podataka u poreenju sa


fiksnim kontejnerima, kao to su nizovi, ogleda se u tome to auriranje poretka stavki
odnosno vorova unutar liste je veoma brzo i lahko, i obino nas kota (1) vremena. Na
primjer, da bismo unijeli novi vor iza vora , neophodno je da alociramo novi prostor
za vor , i da izvrimo preusmjeravanje pokazivaa sa vora na vor , potom sa vora
na vor na koji je prije pokazivao vor . Da bismo obavili ove operacije treba nam
konstantno vremena. Meutim, ovakva situacija nije sa nizovima. Naime, ukoliko imamo

2 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

niz koji se sastoji od elemenata, i elimo da na -tom mjestu (0 < ) ubacimo neki
element , morali bismo da pomjerimo elemenata udesno. Dakle, ukoliko bismo trebali
postavi novi lan na nultom mjestu, morali bismo pomjeriti svaki od lanova za po jedno
mjesto udesno poevi od zadnjeg lana niza. Dakle, ova operacija nas kota u najgorem
sluaju () vremena. Dakle, koritenje jednostruko povezane liste nad nizovima ima
veliku prednost, posebno kada unaprijed ne znamo broj lanova neke strukture ili da li e
se taj broj poveavati ili smanjivati za vrijeme trajanja programa. Primjeuje se kod fiksnih
kontejnera kao to su nizovi, da se unaprijed treba alocirati prostor u memoriji, to je
sasvim nepotrebno, jer nekada se unaprijed ne zna koliko kontejnera je neophodno.
Ukoliko se desi da alociramo niz koji ima 100.000 lanova, za vrijeme trajanja programa,
niti jedan od lanova nee dopustiti memorijsku lokaciju nekom drugom procesu, bez
obzira da li se isti koristi ili ne. Ovo je veliki nedostatak upotrebe nizova, i preporuka ih je
izbjegavati kad god se za to ukae potreba zbog poveavanja performansi i utede
alocirane memorije.

Napomenimo jo da kod jednostruko povezane liste, svaki vor koji ukazuje odnosno
linkuje na sljedei vor se zove sljedbenik. Vano je istai da kod krune jednostruko
povezane liste, posljednji vor linkuje na prvi vor.

Za razliku od jednostruko povezane liste, esto je u upotrebi i dvostruko povezana lista,


ija je grafika ilustracija data na slici ispod.

Slika 3.1.2. Dvostruko povezana lista

Kod dvostruko povezane liste, svaki vor je povezan i sa prethodnim vorom i sa sljedeim
vorom. Kod ove liste svaki vor koji linkuje na prethodni vor se zove prethodnik. Za
potrebe rjeavanja problema iz kompjuterske geometrije, najee je u upotrebi kruna
dvostruko povezana lista, ija je grafika ilustracija data na slici 3.13. U nastavku emo
koristiti krune dvostruko povezane liste, i zbog jednostavnosti emo ih naprosto zvati
listama. Ovakve liste najee emo koristiti za predstavljanje poligona, i vorova koji
ustvari predstavljaju vrhove poligona. U C++ implementaciji, vor emo predstaviti kao
instancu odnosno objekat klase Cvor, kao to se moe vidjeti iz koda koji prilaemo u
nastavku ovog odjeljka.

3 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

Slika 3.1.3. Kruna dvostruko povezana lista

//C++ za klase Cvor

class Cvor
{
protected:
Cvor * sljedeciC; // pokazivac na sljedbenik
Cvor * prethodniC; // pokazivac na prethodnik
public:
Cvor();
virtual ~Cvor(){};
Cvor * sljedeci();
Cvor * prethodni();
Cvor * ubaci(Cvor *);
Cvor * ukloni();
void spoji(Cvor *);
};//kraj definicije klase Cvor

U gornjem kodu dali smo samo definiciju klase Cvor. U nastavku emo implementirati
konstruktor, destruktor i ostale metode ove klase. Tokom implementacije konstruktora,
trebamo natjerati da instance te klase upuuje na samu sebe. To emo postii tako to
emo inicijalizirate privatne lanice odnosno atribute sljedeciC i prethodniC na this.
Implementacija konstruktora data je ispod:

//Implementacija konstruktora klase Cvor

Cvor::Cvor(): prethodniC(this), sljedeciC(this){}; //kraj implementacije

Jasno je da unutar konstruktora, pokaziva this e pokazivati na objekat koji e biti


kreiran. Na primjer, Cvor * novi =new Cvor(); pokaziva this se odnosi na objekat novi,
pa je sada sljedei i prethodni vor od vora novi zapravo on sam. Destruktor je zaduen

4 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

da po izlasku iz programa dealocira kreirane objekte ili da reagira prilikom poziva naredbe
delete novi. Konkretno, u gornjem sluaju, destrukor je zaduen da dealocira objekat
novi. Razlog zbog ega je stavljeno da destruktor za klasu Cvor bude virtuelni, lei u
injenici da isti treba osloboditi objekte odnosno instance klasa koje e naslijediti klasu
Cvor, kao npr. klasa Lista koja e biti definirana i impelementirana u nastavku odjeljka. Da
bismo skakali sa jednog vora na drugi, u nastavku dajemo dvije implementacije funkcija
lanica prethodni i sljedeci.

//Implementacija metode prethodni

Cvor * Cvor :: prethodni()


{
return prethodniC;
}
//kraj implementacije metode prethodni

//Implementacija metode sljedeci

Cvor * Cvor :: sljedeci()


{
return sljedeciC;
}
//kraj implementacije metode sljedeci

Da bismo implementirali metodu ubaci koja e biti u stanju da umetne novi vor u listu
(misli se na krunu dovstruko povezanu listu), posmatrajmo sliku ispod:

Slika 3.1.4. Ubacivanje vora u listu

Pretpostavimo da se nalazimo na voru A i da trebamo da dodamo u listu vor B. S obzirom


da se radi o krunoj dvostruko povezanoj listi, sljedbenik voru A predstavlja vor B, dok
je A prethodnik voru B. Takoer, sljedbenik voru B je vor A, dok je prethodnik voru A
vor B. Na osnovu ovoga impelementacija metode ubaci data je sa:

//Implementacija metode ubaci

Cvor * Cvor :: ubaci(Cvor *b)


{
Cvor * c = sljedeciC;
b->sljedeciC = c;
b->prethodniC = this;
sljedeciC = b;

5 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

c->prethodniC = b;
return b;
}//kraj implementacije metode ubaci

Da bismo implementirali metodu ukloni, posluit emo se slikom ispod:

Slika 3.1.5. Uklanjanje vora iz liste

Na osnovu slike 3.1.5. implementacija metode ukloni data je sa:

//Implementacija metode ukloni

Cvor * Cvor :: ukloni(Cvor *b)


{
prethodniC->sljedeciC =sljedeciC;
sljedeciC->prethodniC =prethodniC;
sljedeciC=prethodniC = this;
return this;
}//kraj implementacije metode ukloni

Ostala je jo da se implementira metoda spoji. Motivacija za uvoenje ove metode je


sljedea. Neka imamo dva vora A i B. Ukoliko se vorovi A i B nalaze u istoj listi, onda se
primjenom metode spoji, data lista dijeli na dvije manje povezane liste. Meutim, ukoliko
vorovi A i B ne pripadaju istoj listi, onda se primjenom metode spoji dobija jedna vea
povezana lista. Da bismo implementirali ovu metodu, posluit emo se slikom 3.1.6. Na
osnovu ove slike vidimo da je operacija spajanja vorova inverzna. Naime, ukoliko se
vorovi A i B nalaze u istoj listi (slika 3.1.6 na desnoj strani), spajanje vorova prouzorkuje
da se dobiju dvije manje liste (slika 3.1.6 na lijevoj strani). Obrnuto, ukoliko se vorovi A
i B nalaze u disjunktnim listama (slika 3.1.6. na lijevoj strani), onda se dobija jedna vea
lista (slika 3.1.6 na desnoj strani).

6 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

Slika 3.1.6. Spajanje vorova

Na osnovu slike 3.1.6 dajemo implementaciju metode spoji:

//Implementacija metode spoji

void Cvor :: spoji(Cvor * b)


{
Cvor * a = this;
Cvor * pom1 = a->sljedeciC;
Cvor * pom2 = b->sljedeciC;
a->sljedeciC = pom2;
b->sljedeciC = pom1;
pom1->prethodniC = b;
pom2->prethodniC = a;
}//kraj implementacije metode ukloni

Vano je primjetiti da ukoliko vor A prethodi voru B u povezanoj listi, onda operacija
spajanja utie na uklanjanje vora B. tavie, spajanje liste moe uticati da se vor B ubaci
nakon vora A. Na osnovu ovoga moe se zakljuiti da su metode za ubacivanje i uklanjanje
vorova iz liste samo specijalni sluajevi metode spoji. Dakle, ova metoda je generalizacija
spomenutih metoda. Takoer, ukoliko bismo probali pozvati metodu spoji tako da vor A
spoji sa samim sobom, vidjeli bismo da ne bismo dobili nikakav efekat.

3.2 Liste vorova


U ovom odjeljku emo definirati i implementirati novu klasu ListaCvorva. Poznato je da je
lista ureen skup konano mnogo elemenata, kao i to da je njena duina jednaka broju
elemenata koje sadri. Lista duine nula se zove prazna lista. Smatraemo da svaki
element liste zauzuima po jedno mjesto, tako da se prvi element nalazi na prvom mejstu,
drugi na drugom mjestu i tako dalje. Glava lista se na samom poetku nalazi na nultom
mjestu tako da tada uvijek pojavljuje ispred prvog elementa liste. Takoer, kada doemo
do kraja liste, glava liste se nalazi iza posljednjeg elementa u listi. Pristup elementima liste
bie obezbijeeno preko trenutnog pokazivaa ili prozora (eng. window). Koristei
trenutni pokaziva, moemo se kretati unutar liste na prethodnu ili sljedeu poziciju, kao i
ubacivati, brisati ili itati sadraj nekog vora na koji taj pokaziva ve pokazuje. Takoer,
na osnovu njega moemo se pomjeriti na kraj lili poetak liste. U nastavku emo prvo dati

7 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

definiciju generike klase (templejta) ListaCvorova koju emo javno naslijediti iz klase
Cvor.

//Ovim emo obavijestiti kompajler da emo u nastavku koristiti klasu Lista


template<class T>
class Lista;

//Definicija generike klase ListaCvorova

template<class T>
class ListaCvorova : public Cvor
{
public:
T elementG; // genericki element
ListaCvorova(T element);
ListaCvorova();
friend class Lista<T>;
}//kraj implementacije metode ukloni

pri emu emo klasu Lista neto klasnije definirati i implementirati. Kao to se moe vidjeti
iz gornjeg C++ koda, stavili smo da je elementG javni, zbog jednostavnije pristupa njemu.
Bez umanjenja openitosti, mogli smo ga proglasiti privatnim, s tim da bi u tom sluaju
morali imati geter i seter metode. Takoer, proglasili smo da je klasa Lista prijatelj klasi
ListaCvorova, da bismo i u ovom sluaju izbjegli uvoenje dodatnih metoda za pristup
atributima. Sem ovoga, primjetimo da je T generiki tip podataka, to nam omoguava
da sada radimo sa raznim tipovima podataka tokom rjeavanja raznovrsnih geometrijskih
problema. U nastavku dajemo C++ implementaciju konstruktora sa i bez parametara.

//Implementacija konstruktora generike klase ListaCvorova

template<class T>
ListaCvorova<T>::ListaCvorova(T element):elementG(element){}

template<class T>
ListaCvorova<T>::ListaCvorova(){}

Jasno je da e konstruktor klase ListaCvorova prilikom inicijalizacije pozvati konstruktor


bez parametra klase Cvor. Za klasu ListaCvorova neemo definirati destruktor
~ListaCvorova, jer kadgod se uniti neka instance ove klase, automatski e biti pozvan
destruktor klase Cvor. Jedna upotreba klase ListaCvorova je data sa:

ListaCvorova<int> * listaC=new ListaCvorova<int>();

U nastavku emo dati definiciju klase Lista.

//Definicija generike klase Lista

template<class T>

8 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

class Lista
{
private:
ListaCvorova<T> *glavaL;
ListaCvorova<T> *trenutniC; // glava na trenutnom cvoru liste
int duzinaL; //duzina liste
public:
Lista();
T prviE();
T ukloniE();
~Lista();
T posljednjiE();
T ubaciE(T);
T prethodniE();
T sljedeciE();
bool jelPrviE();
bool jelPosljednjiE();
int vratiDuzinuL();
bool jelGlavaL();
T dodajNaPocetakE(T);
T dodajNaKrajE(T);
void postaviE(T);
T vratiE();
Lista *spojiL(Lista*);
};

Prije nego to implementiramo bilo koju od metoda klase Lista, usvojit emo da se lanovi
liste dodaju u smjeru kazaljke na satu (negativna orjentacija), dok se itaju u
suprotnom smjeru kazaljke na satu (pozitivna orjentacija). U nastavku emo bez
detaljnijeg objanjenja date imeplementacije konstruktora, destruktora, i ostalih metoda
klase Lista.

//Implementacija konstruktora generike klase Lista

template<class T>
Lista<T> :: Lista(): duzinaL(0)
{
glavaL = new ListaCvorova<T>(0);
trenutniC = glavaL;
}

Nakon kreiranog konstruktora, jedna upotreba klase lista je data sa:

Lista<int> * lista=new Lista<int>();

Da bismo implementirali destruktor, prvo emo implementirati metode prviE() i ukloniE().

//Implementacija metode prviE()

template<class T>
T Lista<T> :: prviE()

9 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

{
trenutniC = (ListaCvorova<T>*)glavaL->prethodni();
return trenutniC->elementG;
}

Implementirajmo sada metodu ukloniE().

//Implementacija metode ukloniE()

template<class T>
T Lista<T>::ukloniE()
{
if (trenutniC == glavaL) return 0;
void *el = trenutniC->elementG;
trenutniC = (ListaCvorova<T>*)trenutniC->prethodni();
delete (ListaCvorova<T>* )trenutniC->sljedeci()->ukloni();
--duzinaL;
return el;
}

Implementirajmo sada destruktor klase Lista.

//Implementacija destruktora generike klase Lista

template<class T>
Lista<T> :: ~Lista()
{
while (duzinaL > 0)
{
prviE();
ukloniE();
}
delete glavaL;
}
Implementacija metode posljednjiE() je data sa:

//Implementacija metode posljednjiE()

template<class T>
T Lista<T> :: posljednjiE()
{
trenutniC = (ListaCvorova<T>*)glavaL->sljedeci();
return trenutniC->elementG;
}
Implementacija metode ubaciE() je data sa:

//Implementacija metode ubaciE()

template<class T>
T Lista<T> :: ubaciE(T el)
{
trenutniC->ubaci(new ListaCvorova<T>(el));
++duzinaL;
10 3. Strukture podataka | Doc. dr. Adis Alihodi
KOMPJUTERSKA GEOMETRIJA

return el;
}

Implementacija metode prethodniE() je data sa:

//Implementacija metode prethodniE()

template<class T>
T Lista<T> :: prethodniE()
{
trenutniC = (ListaCvorova<T>*)trenutniC->prethodni();
return trenutniC->elementG;
}

Implementacija metode sljedeciE() je data sa:

//Implementacija metode sljedeciE()

template<class T>
T Lista<T> :: sljedeciE()
{
trenutniC= (ListaCvorova<T>*)trenutniC->sljedeci();
return trenutniC->elementG;
}

Implementacija metode jelPrviE() je data sa:

//Implementacija metode jelPrviE()

template<class T>
bool Lista<T>::jelPrviE()
{
return ((trenutniC == glavaL->prethodni()) && (duzinaL > 0));
}

Implementacija metode jelPosljednjiE() je data sa:

//Implementacija metode jelPosljednjiE()

template<class T>
bool Lista<T> :: jelPosljednjiE()
{
return ((trenutniC == glavaL->sljedeci()) && (duzinaL > 0));
}

Implementacija metode vratiDuzinuL() je data sa:

//Implementacija metode vratiDuzinuL()

template<class T>
int Lista<T> :: vratiDuzinuL()
{

11 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

return duzinaL;
}

implementacija metode jelGlavaL() je data sa:

//Implementacija metode jelGlava()

template<class T>
bool Lista<T> :: jelGlavaL()
{
return trenutniC == glavaL;
}

Implementacija metode dodajNaPocetak():

//Implementacija metode dodajNaPocetakE()

template<class T>
T Lista<T> :: dodajNaPocetakE(T el)
{
glavaL->prethodni()->ubaci(new ListaCvorova<T>(el));
++duzinaL;
return el;
}

Implementacija metode dodajNaKrajE():

//Implementacija metode dodajNaKraj()

template<class T>
T Lista<T> :: dodajNaKrajE(T el)
{
glavaL->ubaci(new ListaCvorova<T>(el));
++duzinaL;
return el;
}

Implementacija metode postaviE():

//Implementacija metode postaviE()

template<class T>
template<class T>
void Lista<T> :: postaviE(T el)
{
if(trenutniC!=glavaL)trenutniC->elementG=el;
}

Implementacija metode vratiE():

//Implementacija metode vratiE()

12 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

template<class T>
T Lista<T> :: vratiE()
{
return trenutniC->elementG;
}

Implementacija metode spojiL():

//Implementacija metode

template<class T>
Lista<T> * Lista<T> :: spojiL(Lista<T> *l)
{
ListaCvorova<T> *a = (ListaCvorova<T>*)glavaL->prethodni();
a->spoji(l->glavaL);
duzinaL+=l->duzinaL;
l->glavaL->ukloni();
l->duzinaL= 0;
l->trenutniC=glavaL;
return this;
}

3.2.1 Primjeri upotrebe klase Lista

U ovom odjeljku emo dati par primjera koritenja definirane i implementirane klase Lista.
Pretpostavimo da smo definirali i implementirali jednu prostu klasu Tacka, kao ispod:

//Definicija i implementacija klase Tacka

class Tacka
{
private:
double x,y;
public:
Tacka(){};
Tacka(double, double);
double dajX() const{return x;}
double dajY() const{return y;}
};

Tacka::Tacka(double x, double y)
{
this->x=x;
this->y=y;
}

Sljedei jednostavan primjer demonstrira dodavanje tacki u listu.

Lista<Tacka* > * lista=new Lista<Tacka* >();


Tacka ** niz= new Tacka*[5];
for(int i=0;i<5;i++) niz[i]=lista->ubaciE(new Tacka(i,i));

13 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

itanje elemenata iz liste emo uraditi na sljedei nain:

while(!lista->jelPosljednjiE()){
Tacka * el=lista->sljedeciE();
cout<<el->dajX()<<" "<<el->dajY()<<endl;
}

Na kraju emo osloboditi memoriju sa:

for(int i=0;i<8;i++){
delete [] niz[i];
niz[i]=NULL;
}
delete [] niz;
niz=NULL;
delete lista;

Analogno se mogu iztestirati preostale metode. U nastavku emo dati testni primjer koji
e pomou metodu spojiL() spojiti dvije liste u jednu:

Lista<Tacka* > * lista1=new Lista<Tacka* >();


Tacka ** niz1= new Tacka*[5];
for(int i=0;i<5;i++) niz1[i]=lista1->ubaciE(new Tacka(i,i));

Lista<Tacka* > * lista2=new Lista<Tacka* >();


Tacka ** niz2= new Tacka*[5];
for(int i=5;i<10;i++) niz2[i-5]=lista2->ubaciE(new Tacka(i,i));

Lista<Tacka* > *lista3=lista2->spojiL(lista1);

Proitajmo lanove nove liste lista3:

while(!lista3->jelPosljednjiE()){
Tacka * el=lista3->sljedeciE();
cout<<el->dajX()<<" "<<el->dajY()<<endl;
}

Potom oslobodimo memoriju:

for(int i=0;i<5;i++){
delete [] niz1[i];
delete [] niz2[i];
niz1[i]=niz2[i]=NULL;

14 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

}
delete [] niz1;
delete [] niz2;
niz1=niz2=NULL;
delete lista1, lista2, lista3;

Pored ovih upotreba klase Lista, navest emo jo jedan primjer. Pretpostavimo da elimo
da elemente nekog niza konvertujemo u listu, koju emo nakon toga vratiti iz funkcije. To
moemo uraditi tako to emo prvo definirati prototip sljedee funkcije:

template<class T>
Lista<T> * nizUListu(T a[], int n);

Implementacija ove funkcije je data ispod:

template<class T>
Lista<T> * nizUListu(T a[], int n)
{
Lista<T> *s = new Lista<T>;
for (int i = 0; i < n; i++) s->dodajNaKrajL(a[i]);
return s;
}

Primjer upotrebe napisane funkcije je dat sa:

Lista<double> * l;
double niz[5]={1,2,3,4,5};
l=nizUListu(niz,5);
while(!l->jelPosljednjiE()) cout<<l->sljedeciE()<<endl;
delete l;

Sljedei primjer bi bio:

Lista<char* > * l1;


char *niz1[4]={"Huso","Haso", "Akif", "Mule"};
l1=nizUListu(niz1,4);
while(!l1->jelPosljednjiE()) cout<<l1->sljedeciE()<<endl;
delete l1;

Sljedea upotreba funkcija se odnosi na funkciju koja e vratiti najmanji element iz liste u
odnosu na rastui poredak poredanih elementa. Funkciju emo nazvati
najmanjiElement(), iji je prototip dat sa:

template<class T>

15 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

T najmanjiElement(Lista<T> & l, int (*fun) (T,T));

Implementacija ove funkcija data je sa:

template<class T>
T najmanjiElement(Lista<T> & l, int (*fun) (T,T) )
{
if (l.vratiDuzinuL() == 0) return NULL;
T e = l.prviE();
for (l.prviE(); !l.jelGlavaL(); l.sljedeciE())
if (fun(l.vratiE(), e) < 0)
e = l.vratiE();
return e;
}

Primjer upotrebe je dat ispod:

Lista<const char* > * imenaL;


const char * imena[4]={"Ado", "Huko", "Bejo", "Mule"};
imenaL=nizUListu(imena,4);
cout<<najmanjiElement(*imenaL, strcmp);

Primjeujemo da je ovdje kao parametar proslijeena funkcija za poreenje strcmp iz


biblioteke string.h. Ukoliko bismo umjesto fun(l.vratiE(), e) < 0 posmatrali
fun(l.vratiE(), e) > 0, dobili bismo sortiranje u opadajuem poretku.

3.3 Stek
Ope je poznato da su liste neograniene strukture podataka, jer se moe bilo kojem
elementu iste proizvoljno pristupiti. Pored lista, postoje strukture podataka ijim
elementima se pristupa sa odreenim ogranienjem. Takve strukture podataka zovemo
stek. Naime, kod steka se prvi lan koji je dodat posljednji skida sa njega, dok se zadnji
dodat na steku, prvi skida. Zbog ovoga su poznati kao liste sa LIFO (eng. Last In First
Out) strukturom. Dvije osnovne operacije kod steka su: dodaj i skini. Jasno je da
operacija dodaj svaki put dodaje element na vrh steka, dok operacija skini jedino moe
skinuti element sa vrha steka. Stoga, jedini element koji je dostupan na steku je onaj koji
se nalazi na samom vrhu, tj. najvii (prvi za skidanje) element (eng. topmost element).
Pored ove dvije operacije, postoje jo operacije kao to su, jel prazan, koja vra tano
ukoliko je stek prazan, velicina steka, najvii element, do najvieg elementa, donji
element. Jasno je da jednostavna statika implementacija steka moe da se realizira
preko niza. Meutim, jedini problem kod ove implementacije jeste taj to bi duina niza
ograniavala duinu steka. Stoga emo umjesto niza kao fiksnog kontejnera koristiti liste
kao dinamike strukture podataka koje smo uveli u prethodnom odjeljku ove glave.
Koristei liste za realizaciju steka, posljednji element liste e predstavljati najvii element
steka, dok e prvi element liste predstavljati donji element steka odnosno prvi element
koji je dodat na steku. Zbog jednostavnosti implementacije steka, u nastavku emo dati
definicije i implementacije klase Stek.
16 3. Strukture podataka | Doc. dr. Adis Alihodi
KOMPJUTERSKA GEOMETRIJA

U nastavku emo dati definiciju klase Stek.

//Definicija generike klase Stek

template<class T>
class Stek
{
private:
Lista<T> *s;
public:
Stek();
~Stek();
void dodaj(T);
T skini();
bool jelPrazan();
int velicinaS();
T najvisiE();
T doNajvisegE();
T donjiE();
};

U nastavku emo bez detaljnijeg objanjenja dati imeplementacije konstruktora,


destruktora, i ostalih metoda generike klase Stek.

Implementacija konstruktora Stek():

//Implementacija konstruktora generike klase Stek

template<class T>
Stek<T>::Stek(): s(new Lista<T>){}

Implementacija destrukotra ~Stek():

//Implementacija destruktora generike klase Stek

template<class T>
Stek<T>::~Stek()
{
delete s;
}

Implementacija metode dodaj():

//Implementacija metode dodaj()

template<class T>
void Stek<T>::dodaj(T el)
{
s->dodajNaKrajE(el);
}

Implementacija metode skini():

17 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

//Implementacija metode skini()

template<class T>
T Stek<T>:: skini()
{
s->posljednjiE();
return s->ukloniE();
}

Implementacija metode najvisi():

//Implementacija metode najvisi()

template<class T>
T Stek<T>:: najvisi()
{
return s->posljednjiE();
}

Implementacija metode donji():

//Implementacija metode donji()

template<class T>
T Stek<T>:: donji()
{
return s->prviE();
}

Implementacija metode doNajviseg():

//Implementacija metode doNajviseg()

template<class T>
T Stek<T>:: doNajviseg()
{
s->posljednjiE();
return s->prethodniE();
}

Implementacija metode jelPrazan():

//Implementacija metode jelPrazan()

template<class T>
bool Stek<T>::jelPrazan()
{
return (s->vratiDuzinuL()==0);
}

Implementacija metode dajVelicina():

18 3. Strukture podataka | Doc. dr. Adis Alihodi


KOMPJUTERSKA GEOMETRIJA

//Implementacija metode dajVelicinu()

template<class T>
int Stek<T>::dajVelicina()
{
return s->vratiDuzinuL();
}

Stek se moe koristi u sluaju kada se eli postii obrnut redoslijed lanova, kao to je
realizirano funkcijom ispod:

void obrni(char * niz[], int n)


{
Stek<char *> s;
for(int i=0;i<n;i++) s.dodaj(niz[i]);
for(int i=0;i<n;i++) niz[i]=s.skini();
}

Primjer upotrebe funkcije obrni() je dat ispod:

char * niz[4]={"aki", "maki", "laki", "raki"};


obrni(niz,4);
for(int i=0;i<4;i++) cout<<niz[i]<<endl;

Jasno je da je Stek apstraktan tip podataka, pri emu je klasa Lista sakrivena unutar
privatnih lanica klase Stek. Stoga, klasi Lista se ne moe pristupiti izvana, niti se ista
moe modificirati. Dakle, Stek ovdje ima ulogu interfejsa. Funkcije koje koriste Stek,
nemaju potrebe da vode rauna kako je on implementiran odnosno da li je implementiran
preko liste ili obinog niza.

3.4 Binarna stabla pretraivanja


Binarno stablo je usmjeren graf kod koga iz vora maksimalno izlaze dvije grane. Binarno
stablo je dinamiki tip podataka koji nam omoguava da podatke uvijek drimo sortiranim
i efikasno podupire operacije ubacivanja novog elementa u stablo i brzo nalaenje elementa
iz stabla. Obilazak vorova u binarnom stablu moe se vriti na tri naina:

Inorder;
Postorder;
Preorder.

Kod Inorder-a prvo se posjeuje lijevo podstablo zatim vor pa desno podstablo, tj.
L--D.

Kod Postorder-a prvo se posjeuje lijevo podstablo zatim desno podstablo pa vor, tj.
L-D-.

Kod Preorder-a prvo se posjeuje vor zatim lijevo podstablo pa desno podstablo, tj.
-L-D. Vrlo je vano napomenuti, da emo binarno stablo koristiti za prikazivanje Beach
linija kod Voronoi dijagrama, pri emu e potomci binarnog stabla T (vidi grafiku
ilustraciju binarnog stabla T na slici 8.) odgovarati lukovima na Beach liniji.
19 3. Strukture podataka | Doc. dr. Adis Alihodi
KOMPJUTERSKA GEOMETRIJA

Slika 3.4.1. Jedan prikaz binarnog stabla T

20 3. Strukture podataka | Doc. dr. Adis Alihodi

You might also like