Download as pdf or txt
Download as pdf or txt
You are on page 1of 14

Strukture podataka i algoritmi 2

dr Boban Stojanovi

Stabla
Uvod
Stabla se koriste za predstavljanje hijerarhijske strukture neke kolekcije podataka. Stablo se sastoji od
jednog ili vie vorova koji zadovoljavaju sledee uslove:
1. Postoji jedan vor koji predstavlja koren stabla i
2. Ostali vorovi su podeljeni u n disjunktnih skupova vorova, tako da svaki skup predstavlja stablo.
Na Slici ### je prikazan primer stabla:
A

Slika ### ematski prikaz stabla

Struktura prikazana na prethodnoj slici je stablo iz razloga to je to skup vorova {A, B, C, D, E, F, G, H, I}, pri
emu je vor A koren stabla, a ostali vorovi su podeljeni u tri disjunktna skupa {B, G, H, I}, {C, E, F} i {D}.
Svaki od ova tri skupa je takoe stablo, zato to zadovoljava oba uslova navedena u definiciji.
Struktura prikazana na Slici ### nije stablo, zato to injenica da je vor E podeljen onemoguava
razdvajanje vorova od B do I u disjunktne skupove.
A

Slika ### ematski prikaz strukture koja nije stablo

Stepen vora stabla


Stepen vora stabla je broj podstabala kojima je ovaj vor koren. Drugim reima, stepen je broj naslednika
(dece) vora. Ukoliko je stepen vora nula, takav vor nazivamo list stabla.
Stepen stabla
Stepen stabla se definie kao maksimum stepena svih vorova stabla.
Nivo vora
Nivo vora definiemo tako to uzimamo da je nivo korena stabla jednak 1, a zatim uveavamo ovaj broj za
jedan pri svakom skoku od korena ka podstablima. Tako, nivo svih naslednika korena e biti 2, nivo njihovih
naslednika 3 itd. Dubinu stabla zatim definiemo kao maksimalni nivo vora u stablu.

Strukture podataka i algoritmi 2

dr Boban Stojanovi

Binarno stablo
Binarno stablo je specijalni sluaj stabla u kome ni jedan vor nema stepen vei od 2. To praktino znai
da svaki vor ima najvie dva naslednika. Dakle, binarno stablo je skup od jednog ili vie vorova takvih da:
1. Postoji jedan vor koji je koren stabla i
2. Preostali vorovi su podeljeni u dva disjunktna skupa, tako da svaki skup predstavlja binarno
stablo. Ova dva skupa se nazivaju levo i desno podstablo.
Na Slici ### je prikazano binarno stablo:

Slika ### Binarno stablo

Za binarno stablo vai:


1. Maksimalni broj vorova na i-tom nivou je 2i1
2. Ako je k dubina binarnog stabla, onda je maksimalan broj vorova koje stablo moe da ima je
2k 1 = 2k 1 + 2k 2 + ... + 20
Napomenimo da mogu postojati i iskoena stabla, kao to je to prikazano na Slici ###:
A

C
Iskoeno u levo

Iskoeno u desno

Slika ### Iskoena binarna stabla

Puno binarno stablo je binarno stablo dubine k koje sadri 2k 1 vorova. Ukoliko je broj vorova manji od
2k 1 , binarno stablo je nepotpuno. Primer punog binarnog stabla je prikazan na Slici ###:

Slika ### Puno binarno stablo

Strukture podataka i algoritmi 2

dr Boban Stojanovi

Na prethodnoj slici smo vorove stabla oznaili brojevima od 1 do 7. Ukoliko je binarno stablo puno njegovi
vorovi se mogu numerisati brojevima od 1 do 2k 1 tako to bi se poelo od korena, a zatim numerisao
jedan po jedan nivo sa leva na desno.
Kompletno binarno stablo dubine k je stablo sa n vorova u kome bi se ovih n vorova moglo numerisati
brojevima od 1 do n, kao kada bi to bilo prvih n vorova u punom stablu dubine k.
Na Slici ### je prikazano kompletno binarno stablo dubine k=3:
1

Slika ### Kompletno binarno stablo

Predstavljanje binarnog stabla


Binarno stablo moe biti predstavljeno korienjem niza tako to bi vrednost u svakom voru bila
pridruena elementu niza sa indeksom koji je jednak numeraciji tog vora u odgovarajuem punom
binarnom stablu. Meutim, s obzirom na ozbiljne nedostatke, neemo detaljnije opisivati ovaj nain
predstavljanja binarnog stabla. Umesto toga, pokazaemo kako je mogue predstaviti binarno stablo
korienjem povezanih struktura.
Binarno stablo je mogue veoma efikasno predstaviti korienjem povezanih struktura, tako to bi svaki
vor bio predstavljen strukturom sa tri promenljive: podatak koji se uva, pokaziva na levo podstablo i
pokaziva na desno podstablo, kao to je prikazano na Slici ###:

Slika ### Predstavljanje binarnog stabla korienjem povezanih struktura

Ukoliko vor nema nekog od naslednika, pokaziva na tog naslednika bi u tom sluaju bio NULL.
Deklaracija strukture za predstavljanje vora binarnog stabla u programskom jeziku C bi mogla da izgleda
ovako:
structcvor
{
intpodatak;
structcvor*levi,*desni;
};

Strukture podataka i algoritmi 2

dr Boban Stojanovi

Obilazak binarnog stabla


Pod obilaskom binarnog stabla podrazumevamo prolazak kroz sve njegove vorove odreenim
redosledom, pri emu je istovremeno mogue izvriti i odreenu operaciju nad podacima koji su u njima
zapisani.
U zavisnosti od redosleda obrade odreenog vora i njegovog levog i desnog podstabla, obilazak stabla se
moe izvriti na est naina:
Skraenica
LPD
LDP
PLD
PDL
DLP
DPL

Opis
obilazak levog podstabla, obrada podatka, obilazak desnog podstabla
obilazak levog podstabla, obilazak desnog podstabla, obrada podatka
obrada podatka, obilazak levog podstabla, obilazak desnog podstabla
obrada podatka, obilazak desnog podstabla, obilazak levog podstabla
obilazak desnog podstabla, obilazak levog podstabla, obrada podatka
obilazak desnog podstabla, obrada podatka, obilazak levog podstabla

pri emu
L oznaava obilazak levog podstabla,
D oznaava obilazak desnog podstabla,
P oznaava obradu podatka u trenutnom voru.
Tako, na primer LPD oznaava redosled u kome kreemo od korena, obilazimo levo podstablo, obraujemo
podatak u korenu i na kraju obilazimo desno podstablo. S obzirom na to da su levo i desno podstablo
takoe binarna stabla, potpuno ista procedura se koristi i za njihov obilazak.
Redosled LPD se naziva jo i inorder, redosled LDP postorder, a redosled PLD preorder. Ostala tri
redosleda se nikada ne koriste. Ukoliko prilikom obilaska stabla tampamo podatke koji se nalaze u
vorovima, u zavisnosti od toga da li koristimo inorder, preorder ili postorder, dobijamo rezultate kao to je
prikazano na Slici ###:
Inorder:

D,B,H,E,I,A,F,C,G

Preorder:

A,B,D,E,H,I,C,F,G

Postorder: D,H,I,E,B,F,G,C,A

Slika ### Redosled obilaska binarnog stabla

Tipian primer korienja binarnog stabla je predstavljanje aritmetikih izraza.

Strukture podataka i algoritmi 2

dr Boban Stojanovi

Inorder:

a+b*c+d*e

Preorder:

++a*bc*de

Postorder: abc*+de*+

Slika ### Aritmetiki izraz predstavljen binarnim stablom

Binarno stablo za pretraivanje


Binarno stablo za pretraivanje je binarno stablo koje ima sledee karakteristike:
1. vorovima binarnog stabla su pridruene vrednosti po kojima se obavlja pretraivanje.
2. Za bilo koji vor vai da svi vorovi u levom podstablu imaju vrednost manju od njega, a svi vorovi
u desnom podstablu imaju vrednost veu od njega. I levo i desno stablo su takoe binarna stabla
za pretraivanje.
Primer binarnog stabla za pretraivanje je prikazan na Slici ###

Slika ### Binarno stablo za pretraivanje

Binarno stablo za pretraivanje je u osnovi binarno stablo, tako da se moe obii u inorder, preorder ili
postorder redosledu. Ukoliko binarno stablo za pretraivanje obiemo u inorder redosledu i pri tome
odtampamo vrednosti u vorovima, dobiemo vrednosti sortirane u rastuem redosledu.
Binarno stablo za pretraivanje je veoma vana struktura podataka. Posmatrajmo, na primer, problem
pretraivanja niza. Ukoliko je niz sortiran, pretraivanje moemo znatno ubrzati korienjem binarnog
pretraivanja. Meutim, ukoliko elimo da izvrimo promene u nizu kao to su dodavanje i brisanje
elementa, to e zahtevati pomeranje odreenog broja elemenata svaki put. Ovaj problem moemo reiti
korienjem povezanih lista, zato to one omoguavaju dodavanje i brisanje elemenata vrlo jednostavnim
premetanjem nekoliko pokazivaa. Meutim, problem sa povezanim listama je to to one ne
omoguavaju direktan pristup pojedinim elementima, ve samo sekvencijalno kretanje kroz listu, element
po element. Reenje ovih problema lei upravo u binarnim stablima. Ukoliko se elementi ureenog niza ili
liste smeste u vorove binarnog stabla za pretraivanje, nalaenje odgovarajueg kljua u binarnom stablu
zahteva O (log n) koraka.

Kreiranje binarnog stabla za pretraivanje


Pretpostavimo da svaki vor binarnog stabla sadri celobrojni podatak, kao i pokazivae na levo i desno
podstablo. U tom sluaju struktura koja opisuje vor binarnog stabla bi mogla da izgleda ovako:

Strukture podataka i algoritmi 2

dr Boban Stojanovi

structcvor
{
intpodatak;
structcvor*levi,*desni;
};

U nastavku je dat kompletan program za kreiranje binarnog stabla za pretraivanje:


#include<stdio.h>
#include<stdlib.h>

structcvor
{
intpodatak;
structcvor*levi,*desni;
};

/*funkcijazadodavanjenovogcvoraubinarnostablozapretrazivanje*/
structcvor*dodaj(structcvor*p,intvrednost)
{
structcvor*pom1,*pom2,*novi;

/*kreiranjenovogcvora*/
novi=(structcvor*)malloc(sizeof(structcvor));
if(novi==NULL)
{
printf("Greskaprialociranjumemorije.\n");
exit(0);
}
novi>podatak=vrednost;
novi>levi=novi>desni=NULL;

if(p==NULL)
{
p=novi;
}
else
{
/*prolazakkrozstablokakobisepronasaocvorcijecedetebitinovicvor*/
pom1=p;
while(pom1!=NULL)
{
pom2=pom1;
if(vrednost<pom1>podatak)
pom1=pom1>levi;
else
pom1=pom1>desni;
}

if(vrednost<pom2>podatak)
pom2>levi=novi;
/*dodavanjenovogcvorakaolevogdeteta*/
else
pom2>desni=novi;
/*dodavanjenovogcvorakaodesnogdeteta*/
}

return(p);
}

/*funkcijazastampanjebinarnogstablauinorderredosledu*/
voidstampaj_inorder(structcvor*p)
{
if(p!=NULL)
{
stampaj_inorder(p>levi);
printf("%d\t",p>podatak);
stampaj_inorder(p>desni);
}
}

voidmain()
{
structcvor*koren=NULL;
inti,n,x;

Strukture podataka i algoritmi 2

dr Boban Stojanovi

printf("Unesitebrojcvorova:\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("Unesitevrednost:\n");
scanf("%d",&x);
koren=dodaj(koren,x);
}
stampaj_inorder(koren);

Za kreiranje binarnog stabla za pretraivanje koriena ju funkcija dodaj, koja kreira kreira novi vor,
dodeljuje mu prosleenu vrednost i dodaje ga u postojee stablo. Prva provera koju funkcija obavlja jeste
provera da li je stablo prazno. Ukoliko jeste, novi vor se dodaje kao koren stabla. Ako stablo nije prazno
otpoinje se sa kretanjem kroz stablo korienjem pomonog pokazivaa pom1. Podatak u trenutnom
voru uporeuje se sa novom vrednou. U sluaju da je nova vrednost manja od vrednosti u trenutnom
voru, kretanje se nastavlja kroz levo podstablo. U suprotnom kretanje se nastavlja kroz desno podstablo.
Kretanje se vri sve do trenutka dok se ne doe do kraja stabla, odnosno dok pokaziva na odgovarajue
dete nije NULL. Sve vreme kretanja uva se pokaziva na roditeljski vor pom2, kako bi se na njega na kraju
dodao novi cvor kao dete.
Kada se dospe do kraja stabla, novi vor se dodaje kao levo ili desno dete poslednjem voru, u zavisnosti od
toga da li je nova vrednost manja ili vea od vrednosti poslednjeg vora.
U glavnom programu zadaje se broj vorova, kao i vrednosti u njima. Unete vrednosti se dodaju u drvo
korienjem prethodno opisane funkcije dodaj. Na kraju se vri tampanje vorova stabla korienjem
funkcije stampaj_inorder, koja tampanje obavlja tokom obilaska stabla u inorder redosledu.

Pretraivanje u binarnom stablu za pretraivanje


Pretraivanje u binarnom stablu predstavlja proces u kome se trai vor u stablu, koji zadovoljava unapred
definisane kriterijume. Najee je to pretraivanje u cilju nalaenja vora koji sadri odreeni podatak koji
nazivamo klju.
Da bismo pronali odreeni klju u datom binarnom stablu za pretraivanje, kreemo od korena stabla i
uporeujemo klju sa podatkom u voru. Ukoliko su klju i podatak jednaki, funkcija vraa pokaziva na taj
vor. Ako je klju manji od vrednosti u voru, isti proces ponavljamo za levo podstablo. U suprotnom,
proces ponavljamo za desno podstablo. Pretraga se prekida onog trenutka kada se pronae traeni vor ili
kada je podstablo koje posmatramo prazno. Ukoliko je posmatrano podstablo prazno, funkcija vraa NULL,
kao znak da traeni vor nije pronaen.
U nastavku je data funkcija za pretraivanje u binarnom stablu za pretraivanje:
structcvor
{
intpodatak;
structcvor*levi,*desni;
};

...

/*Funkcijazapretrazivanjeubinarnomstabluzapretrazivanje*/
structcvor*trazi(structcvor*p,intkljuc)
{
structcvor*pom;

pom=p;
while(pom!=NULL)
{
if(pom>podatak==kljuc) return(pom);
else
if(pom>podatak>kljuc)
pom=pom>levi;
else

Strukture podataka i algoritmi 2

dr Boban Stojanovi

pom=pom>desni;
}

return(NULL);
}

Odreivanje broja vorova u binarnom stablu


Broj vorova bilo kog stabla koje nije list jednak je zbiru broja vorova u njegovom levom i desnom
podstablu, koji se uveava za jedan kako bi se uraunao i koren stabla. Ukoliko je stablo list (nema
potomaka), onda je broj vorova u njemu jednak jedan. Ovaj opis ukazuje na potrebu rekurzivnog prolaska
kroz stablo sve dok se ne doe do njegovih listova.
Naredna rekurzivna funkcija vri prebrojavanje vorova u binarnom stablu.
structcvor
{
intpodatak;
structcvor*levi,*desni;
};

...

intbroj(structcvor*p)
{
if(p==NULL) return(0);
else
if(p>levi==NULL&&p>desni==NULL)
return(1);
else
return(1+(broj(p>levi)+broj(p>desni)));
}

Zamena mesta levim i desnim podstablima


Elegantan metod za zamenu mesta levim i desnim podstablima unutar binarnog stabla je korienje
rekurzivnog algoritma. Funkcija zamenjuje mesta levom i desnom podstablu, a zatim na njima rekurzivno
primenjuje isti postupak.
structcvor
{
intpodatak;
structcvor*levi,*desni;
};

...

voidzameni(structcvor*p)
{
structcvor*pom;

if(p!=NULL)
{
pom=p>levi;
p>levi=p>desni;
p>desni=pom;

zameni(p>levi);
zameni(p>desni);
}
}

Primenom ovog algoritma na binarno stablo za pretraivanje, koje bi pri inorder tampanju dalo rastui niz,
dobilo bi se binarno stablo koje bi pri inorder tampanju dalo opadajui niz.

Brisanje vora iz binarnog stabla za pretraivanje


Oznaimo pokaziva na vor koji elimo da obriemo sa x (skraeno: vor x), a pokaziva na vor koji je
njegov roditelj sa y. Nakon brisanja vora x, potrebno je izvriti reorganizaciju njegovih potomaka kako bi
oni i dalje formirali binarno stablo za pretraivanje, a zatim novoformirano podstablo povezati na

Strukture podataka i algoritmi 2

dr Boban Stojanovi

odgovarajui nain sa vorom y, u zavisnosti od toga da li je vor x bio levi ili desni potomak vora y. U
sluaju da je vor x bio koren stabla, onda podstablo formirano od njegovih potomaka postaje novi koren.
Oznaimo pokaziva na podstablo formirano od potomaka vora x sa q.
Brisanje vora koji ima dva potomka
Posmatrajmo binarno stablo prikazano na Slici ###:

Slika ### Binarno stablo pre brisanja vora na koji pokazuje x

Korienjem pomonog pokazivaa pom, prolazimo kroz levo podstablo vora x, kako bismo pronali
njegov desni list, a zatim postavljamo desni pokaziva ovog lista da pokazuje na desno podstablo vora x,
kao to je pokazano na Slici ###. Nakon toga, pokaziva q se postavlja da pokazuje na levo podstablo vora
x, a vor x se brie iz memorije. Ukoliko pokaziva y nije NULL, ostaje samo da se pokaziva q postavi za
odgovarajueg potomka vora y. Ako pokaziva na vor y jeste NULL (obrisan je koren), onda novi koren
postaje pokaziva q.

Slika ### Binarno stablo nakon brisanja vora na koji pokazuje x

Drugi nain brisanja vora je da se prolazi kroz desno podstablo vora x kako bi se pronaao njegov levi list,
a zatim se levi pokaziva tog lista postavlja da pokazuje na levo podstablo vora x, kao to je prikazano na

Strukture podataka i algoritmi 2

dr Boban Stojanovi

Slici ###. Naravno, na kraju je potrebno obrisati vor x iz memorije. Nakon toga, pokaziva q se postavlja da
pokazuje na desno podstablo vora x, a vor x se brie iz memorije. Ukoliko pokaziva y nije NULL, ostaje
samo da se pokaziva q postavi za odgovarajueg potomka vora y. Ako pokaziva na vor y jeste NULL
(obrisan je koren), onda novi koren postaje pokaziva q.

Slika ### Binarno stablo nakon brisanja vora na koji pokazuje x

Brisanje vora koji ima jednog potomka


Posmatrajmo binarno stablo prikazano na Slici ###:

Slika ### Binarno stablo pre brisanja vora na koji pokazuje x

Ukoliko elimo da obriemo vor x, dovoljno je da postavimo pokaziva q da pokazuje na podstablo vora x
koje postoji, a zatim iz memorije obriemo vor x, kao to je prikazano na Slici ###. Ukoliko pokaziva y nije
NULL, ostaje samo da se pokaziva q postavi za odgovarajueg potomka vora y. Ako pokaziva na vor y
jeste NULL (obrisan je koren), onda novi koren postaje pokaziva q.

10

Strukture podataka i algoritmi 2

dr Boban Stojanovi

Slika ### Binarno stablo nakon brisanja vora na koji pokazuje x

Brisanje vora koji nema ni jednog potomka


Posmatrajmo binarno stablo na Slici ###:

Slika ### Binarno stablo pre brisanja vora na koji pokazuje x

Da bismo obrisali vor x iz binarnog stabla, potrebno je samo da pokazivau q dodelimo NULL, a zatim,
ukoliko pokaziva y nije NULL, ostaje samo da se pokaziva q postavi za odgovarajueg potomka vora y.
Ako pokaziva na vor y jeste NULL (obrisan je koren), onda novi koren postaje pokaziva q.

Slika ### Binarno stablo nakon brisanja vora na koji pokazuje x

11

Strukture podataka i algoritmi 2

dr Boban Stojanovi

Primer
#include<stdio.h>
#include<stdlib.h>

structcvor
{
intpodatak;
structcvor*levi,*desni;
};

/*Funkcijakojavracapokazivacnacvorsatrazenomvrednoscuipokazivacnanjegovogroditelja*/
structcvor*pronadji(structcvor*p,intkljuc,structcvor**y)
{
structcvor*pom;

if(p==NULL) return(NULL);

pom=p;
*y=NULL;
while(pom!=NULL)
{
if(pom>data==kljuc)
return(pom);
else
{
*y=pom;/*pamcenjeroditelja*/
if(kljuc<pom>data)
pom=pom>levi;
else
pom=pom>desni;
}
}

return(NULL);
}

/*Funkcijazabrisanjecvorakojisadrzizadatuvrednost*/
structcvor*obrisi(structcvor*p,intvrednost)
{
structcvor*x,*y,*q,*pom,;

x=pronadji(p,vrednost,&y);

if(x==NULL)
{
printf("Cvornepostoji.\n");
return(p);
}

if(x>levi!=NULL&&x>desni!=NULL)/*brisanjecvorakojiimaobapotomka*/
{
pom=x>levi;
while(pom>desni!=NULL)pom=pom>desni;
pom>desni=x>desni;
q=x>levi;
}
elseif(x>levi==NULL&&x>desni!==NULL)/*brisanjecvorakojiimasamodesnogpotomka*/
{
q=x>desni;
}
elseif(x>levi!=NULL&&x>desni==NULL)/*brisanjecvorakojiimasamolevogpotomka*/
{
q=x>levi;
}
elseif(x>levi==NULL&&x>desni==NULL)/*brisanjecvorakojinemanijednogpotomka*/
{
q=NULL;
}

if(y!=NULL)
{
if(y>levi==x)
y>levi=q;
else

12

Strukture podataka i algoritmi 2

dr Boban Stojanovi

y>desni=q;
}
else p=q;

free(x);
return(p);
}

/*funkcijazadodavanjenovogcvoraubinarnostablozapretrazivanje*/
structcvor*dodaj(structcvor*p,intvrednost)
{
structcvor*pom1,*pom2,*novi;

/*kreiranjenovogcvora*/
novi=(structcvor*)malloc(sizeof(structcvor));
if(novi==NULL)
{
printf("Greskaprialociranjumemorije.\n");
exit(0);
}
novi>podatak=vrednost;
novi>levi=novi>desni=NULL;

if(p==NULL)
{
p=novi;
}
else
{
/*prolazakkrozstablokakobisepronasaocvorcijecedetebitinovicvor*/
pom1=p;
while(pom1!=NULL)
{
pom2=pom1;
if(vrednost<pom1>podatak)
pom1=pom1>levi;
else
pom1=pom1>desni;
}

if(vrednost<pom2>podatak)
pom2>levi=novi;
/*dodavanjenovogcvorakaolevogdeteta*/
else
pom2>desni=novi;
/*dodavanjenovogcvorakaodesnogdeteta*/
}

return(p);
}

/*funkcijazastampanjebinarnogstablauinorderredosledu*/
voidstampaj_inorder(structcvor*p)
{
if(p!=NULL)
{
stampaj_inorder(p>levi);
printf("%d\t",p>podatak);
stampaj_inorder(p>desni);
}
}

voidmain()
{
structcvor*koren=NULL;
intn,i,x;

printf("Unesitebrojcvorovastabla:\n");
scanf("%d",&n);

for(i=0;i<n;i++)
{
printf("Unesitevrednost:\n");
scanf("%d",&x);
koren=dodaj(koren,x);
}

13

Strukture podataka i algoritmi 2

dr Boban Stojanovi

printf("Stabloprebrisanjaje:\n");
stampaj_inorder(koren);
printf("\n");
printf("Unesitevrednostkojutrebaobrisati:\n");
scanf("%d",&x);
koren=obrisi(koren,n);
printf("Stabloposlebrisanjaje:\n");
stampaj_inorder(koren);

14

You might also like