You are on page 1of 25

ALFA BK UNIVERZITET

Redovi, stekovi I stabla u programskom jeziku Python

Seminarski rad iz predmeta: Algoritmi I strukture podataka 2

Beograd,2019
Sadržaj

1. Uvod 3
2. Stekovi i redovi 5

 2.1 Stekovi 5
 2.2 Redovi 11
3. Stabla 18

 3.1 Korenska stabla 19


 3.2 Stablo kao struktura podataka 21
 3.3 Binarna stabla 22
 3.4 Binarno stablo pretrage 22
 3.5 BSP operacije 23
4. Literatura 25

2
1.Uvod

Svaki programer pise programski kod u nekom programskom jeziku. Razliciti


programski jezici podrzavaju razlicite stilove programiranja. Razliciti programski jezici
zahtevaju razlicite nivoe znanja, umeca i detalja koje programer treba posedovati. Jedini
programski jezik koji racunar moze direktno izvrsavati je masinski jezik (masinski kod ili binarni
kod).

Do danas napravljeno je hiljade programskih jezika, dok je samo nekoliko od njih postalo
poznatoi dostupno sirokom krugu korisnika. Neki su vise usmereni za resavanja odredjenog
zadatka, dok su sveobuhvatniji programski jezici mnogo poznatiji I cesci u primeni.

Programiranje je slozen proces a vrsi se iz vise razloga. Jedan I najvazniji jeste “prevodjenje”
koda odredjenog programskog jezika u binarni kod, koji je razumljiv racunaru. Takodje kao
razlog mozemo navesti I krajnji product-novi fajl koji je moguce pokrenuti , laicki receno, sa
“dva klika” (executable file). Pri izradi svakog programa potrebno je proci kroz 4 faze:

-Analiza problema
-Kreiranje algoritma (crtanje dijagrama toka)
-Pisanje programskog koda
-Unos programskog koda u racunar I pokretanje programa
U matematici I racunarskoj nauci algoritam je odredjeni skup definisanih naredbi za
obavljanje nekog zadatka. Algoritmi se koriste u racunarskim programima kao nacin
resavanja nekog zadatka. Algoritam takodje moze da znaci graficki prikaz toka obrade ili
skup instrukcija racunarskog programa. On predstavlja vodilju za programera koji
pomocu algoritma predstavlja viziju programa koji zeli napisati u programskom jeziku.
Python je prevodjeni programski jezik kojeg je stvorio Guido van Rossum 1990 godine.
Objekat orijentisano, strukturno I aspekt orijentisano programiranje su stilovi dozvoljeni
koriscenjem Pythona. Ne treba napominjati da ova fleksibilnost cini Python programski
jezik sve popularnijim. Python se najvise koristi na Linux-u, no postoje I verzije za druge
operativne sisteme. Python je vrlo mocan programski jezik. Koriste ga mnoge firme I
pojedinci, prvenstveno radi toga sto je multifunkcionalan te moze izvesti I najzahtevnije
zadatke. Python omogucava kako pravljenje jednostavnih programa, tako I programa sa
GUI-em (Graphic User Interface), pravljenje igrica, integraciju u web stranice itd.
Nazalost, Python je vrlo poznat kao “hakerski programski jezik” iz razloga sto je vrlo
lako sa istim napraviti hakerske alate, kao sto su SQLinjector, DDoS alatke I drugo.
Kodiranje u Python-u mozete svugde izravno u Python terminal (shell) ili u nekom
obicnom tekst editoru. Za jednostavnije programe, koji nemaju takvu strukturu da bi
mogli prouzrokovati vece greske pri kodiranju kodira se direkto u terminalu, dok za
zahtevnije se koriste neki IDE (Integrated development environment ili “radno okruzenje
programera”) programi. IDE programi omogucavaju olaksice pri kodiranju, za Python
samo neki od njih su:

3
-eclipse +pydev
-komodo
-netbeans
-pyscripter
Mnogi Python oznacavaju kao dobar programski jezik za pocetnike, zbog toga sto je vrlo
jednostavan za koriscenje. Ne koristi pomalo cudne I zbunjujuce metode “uvlacenja” kao
Java, nego to radi sasvim jednostavno. Python ima I svojih mana, on kao I Java, ne
priznaje uvlacenje tipkom “TAB”,pa zbog toga mnogi pocetnici imaju errore koje ne
znaju resiti, a resenje je jednostavno.

4
2. Stekovi i Redovi
Veliki broj realnih problema koriscenje struktura podataka kao sto su redovi I stekovi.
Tipican primer koriscenja stekova je stek koji programski jezik koristi da bi implementirao
pozivanje funkcija I povratak iz njih. Sa druge strane, jedna od najcescih primena redova je red
za upravljanje redosledom procesa koje je potrebno izvrsiti. Obe ove strukture podataka su u
formi liste, tako da je za njihovu implementaciju moguce iskoristiti nizove ili povezane liste.

2.1 Stekovi
Stekovi (engleski stack) su liste elemenata u kojima je moguce dodavanje I oduzimanje
elemenata samo na jednom kraju, koji se naziva vrh steka. To prakticno znaci da se elementi sa
steka uklanjaju obrnutim redosledom u odnosu na redosled kojim su dodavani na stek. Iz tog
razloga se ova struktura podataka cesto naziva i LIFO, sto je skracenica od engleskih reci Last In
First Out ( poslednji unutra prvi napolje). Operacija dodavanja elementa na stek se najcesce
naziva Push (gurnuti), dok se operacija skidanja elemenata sa steka naziva Pop ( skinuti).

Stek mozemo zamisliti kao cev zatvorenu na jednom kraju u koju se na drugom kraju dodaju
kuglice koje predstavljaju elemente. Prilikom vadjenje kuglica iz cevi uvek moramo prvo
izvaditi onu kuglicu koja je posednja ubacena u cev I tako redom. Kuglica koja je prva ubacena u
cev bice poslednja izvadjena. Zahvaljujuci ovoj osobini, stekovi se cesto u srpskom jeziku
nazivaju I stogovi. S obzirom da su stekovi u osnovi liste, oni se mogu implementirati
koriscenjem nizova ili povezanih listi.

Implementacija steka pomocu niza

Kada se za implementaciju steka koristi niz, operacije dodavanja I skidanja elementa sa steka se
realizuju koriscenjem osnovnih operacija nad nizom. Ogranicenje implementacije pomocu niza
je nemogucnost prosirenja I skracenja niza u zavisnosti od broja elemenata na steku.

Za implementaciju steka koristi se niz konstantne velicine, koja mora biti dovoljna da se u nju
smesti maksimalan broj elemenata koji se u jednom trenutku moze naci na steku. Pored toga, u
svakom trenutku je neophodno znati broj elemenata na steku ili index elemenata na vrhu steka.
Index -1 oznacava da je stek prazan. Prilikom dodavanja elementa na stek, povecava se index
vrha steka I na tu poziciju u nizu upisuje novi element. Suprotno, prilikom skidanja elementa sa
steka umanjuje se index na vrhu steka.

Primer :

#include <studio.h>

#define MAX 100/*maksimalna velicina steka*/

5
#include <stdlib.h>

Void push (int stack[] , int*top, int value)

{ if (top*<MAX)

{*top: *top+1,

Stack[*top]:value,}

Else

{ printf(“stek je pun I ne moze da primi novu vrednost./n”);

Exit(0);

Void pop (int stack[], int*top, int*value)

If(*top>=0)

*value=stack[*top];

*top=*top-1;

Else

Print(“stek je prazan I ne moze se skinuti vrednost sa njega.\n”);

Exit(0);

Void main ()

6
{

Int stack[MAX];

Int top=-1;

Int n,value;

Do

Do

Print f(“unesite elemenat koji zelite da dodate na stek:\n”);

Scanf (“%d”, value);

} while (n=1);

Printf(“unesite 1 za skidanje elemenata sa steka:\n”);

Scanf(“%d”,n);

Printf(“unesite 1 za dodavanje novog elementa na stek:\n”);

Scanf(“%d”, n);

} while (n=1);

Prethodni primer sadrzi funkcije push I pop za dodavanje I skidanje elemenata sa steka. U
glavnom program omoguceno je dodavanje I skidanje elementa sa steka proizvoljan broj puta
odabirom odgovarajucih komandi.

Implementacija steka pomocu liste

Stek se moze veoma efikasno implementirati koriscenjem povezanih listi tako sto bi se novi
element dodavao uvek na pocetku liste. Tkodje, u slucaju skidanja elementa sa steka skidao bi se
uvek prvi element u listi, odnosno onaj koji je poslednji dodat. Napocetku, lista je prazna pa je I

7
pokazivac (TOP) na pocetku liste jednal NULL. Funkcija push uzima pokazivac na postojecu
listu kao prvi parameter I vrednost koju treba dodati kao drugi parameter, kreira novi element I
dodaje ga na pocetak liste. Funkcija pop uzima pokazivac na pocetak liste kao prvi parameter I
pokazivac na promenljivu koju ce smestiti vednost skinutog elementa kao drugi parameter.
Nakon toga, funkcija vraca vrednost prvog elementa u listi I pomera pokazivac top na sledeci
elemenat u listi. Na kraju se unistava element koji je bio na pocetku listi.

Primer :

#include<stdio.h>

#include<stdlib.h>

Struct node

Int data;

Struct node *link;

};

Struct node * push (struct node* p, int value)

Struct node *temp;

/*kreiranje novog cvora koriscenjem poslednje vrednosti*/

Temp=(struct node*)malloc(sizeof(struct node));

Inf(temp==NULL)

Printf( “greska pri alociranju memorije.\n”);

Temp->data=value;

Temp->link=p;

8
P=temp;

Return(p);

Struct node * pop(struct node *p, int*value)

Struct node *temp;

If(p==NULL)

Printf(“greska. Stek je prazan\n”);

Exit (0);

*value=p->data;

Temp=p;

P=p->link;

Free(temp);

Return(p);

Void main ()

Struct node *top=Null;

Int n, value;

Do

9
Do

Printf(“unesite element koji zelite da dodate na stek:\n”);

Scanf (“%d”, value);

Top = push (top, value);

Printf (“unesite 1 za dodavanje novog elementa na stek:\n”);

Scanf (“%d”, value);

} while (n==1);

Printf (“unesite 1 za skidanje elementa sa steka:\n”);

Scanf (“%d”, n);

While (n==1)

Top =pop (top, value);

Printf( “skinuta vrednost je %d\n”, value);

Printf (“unesite 1 za skidanje elementa sa steka:\n”);

Scanf (“%d”, n);

Printf (“ unesite 1 za dodavanje novog elementa na stek :\n”);

Scanf (“%d”,n);

} while(n==1);

10
2.2 Redovi

Redovi (engleski queu) su liste elemenata u kojima se elementi dodaju na kraju liste, koji se
naziva kraj reda, a oduzimaju se na drugom kraju liste, koji se naziva pocetak reda. To prakticno
znaci da se elementi sa reda uklanjaju istim redosledom kao sto su I dodavani u red. Iz tog
razloga se ova struktura podataka cesto naziva I FIFO, sto je skraceno od engkeskih reci First In
first Out (prvi unutra prvi napolje). Operacija dodavanja elemenata u red se najcesce naziva
Insert (ubaciti), dok se operacija brisanja elemenata iz reda naziva Delete (obrisati). Red
mozemo zamisliti kao cev otvorenu na oba kraja u koju se na jednom kraju ubacuju kuglice koje
predstavljaju elemente. Prilikom vadjenja kuglica iz cevi uvek se prvo vadi kuglica koja je prvo
ubacena u cev I tako redom. Kuglica koja je poslednja ubacena u cev bice poslednja izvadjena.
Upravo ovoj osobini redovi duguju svoj niz, jer podsecaju na cekanje u redu gde se prvo
usluzuju oni koji su prvi stigli. S obzirom da su stekovi u osnovi liste, oni se mogu
implementirati koriscenjem nizova ili povezanih listi.

Implementacija reda pomocu niza

Kada se za implementaciju reda koristi niz, operacije dodavanja I brisanja elemenata iz reda se
realizuju koriscenjem osnovnim operacijama nad nizom. Ogranicenje implementacije pomocu
niza je nemogucnost prosirenja I skracivanja niza u zavisnosti od broja elemenata u redu. Za
implementaciju reda koristi se niz konstantne velicine, koja mora biti dovoljna da se u nju smesti
ukupan broj elemenata koji se dodaje u red, bez obzira na to koliko je njih obrisano iz reda.
Pored toga, u svakom trenutku je neophodno znati indekse prvog I poslednjeg elemenata u redu.
Indexi -1 oznacavaju da je red prazan. Prilikom dodavanja elemenata u red, povecava se index
poslednjeg elementa I na tu poziciju u redu upisuje se novi element. U slucaju brisanja elemenata
iz reda, povecava se index prvog elemenata u redu. Moguca je I drugacija implementacija koja bi
zahtevala samo onoliku velicinu niza koliko je potrebno da se smeste elementi koji su u jednom
trenutku u redu, medjutim takva realozacija zahteva stalno pomeranje preostalih elemenata
prilikom brisanja prvog elementa iz reda.

Primer :

#include<stdio.h>

#define MAX 100/*maksimalna velicina reda*/

#include <stdlib.h>

Void insert (int queue[], int * rear, int value)

11
If(*rear<max-1)

*rear=*rear+1;

Queue[*rear] =value;

Else

Printf( “red je pun. Ne moze se dodati vrednost.\n”);

Exit (0);

Void delete (int queue [], int *front, int rear, int*value)

If(*front==rear)

Printf (“red je prazan. Ne moze se obrisati vrednost.\n”);

Exit(0);

*front=*front+1;

*value=queue [*front];

Void main <>

12
Int queue [MAX];

Int front, rear;

Int n, value;

Front=rear=(-1);

Do

Do

Printf( “unesite elemenat koji zelite da dodate u red:\n”);

Scanf(“%d”, value);

Insert ( queue, rear, value);

Printf( “unesite 1 za dodavanje novog elementa u red:\n);

Scanf(“%d”,n);

} while (n==1);

Printf (“unesite 1 za brisanje elementa iz reda:\n”);

Scanf (“%d”,n);

While (n==1);

Delete (queue, front, rear, value);

Printf ( “obrisana vrednost je %d\n,value”);

Printf (“unesite 1 za brisanje elemenata iz reda:\n”);

13
Scanf (“%d”,n);

Printf (“unesite 1 za dodavanje novog elementa u red:\n”);

Scanf(“%d”,n);

} while (n==1);

Implementacija reda pomocu listi

Red se moze veoma efikasno implementirati koriscenjem povezanih lista tako sto bi se novi
element dodavao uvek na kraj liste. Takodje, u slucaju brisanja elemenata iz reda skidao bi se
uvek prvi eleemnat u listi, odnosno onaj koji je prvi dodat. Na pocetku, lista je prazna, pa su I
pokazivaci na pocetak I kraj liste jednaki NULL. Funkcija insert kreira novi element I dodaje ga
na kraj liste. Funkcija delete vraca vrednost prvog elementa u listi I pomera pokazivac front na
sledeci element u listi. Na kraju se unistava element koji je bio na pocetku liste.

Primer :

#include <stdio.h>

#include<stdlib.h>

Struct node

Int data;

Struct node *link;

};

Void insert (struct node **front, struct node **rear, int value)

Struct node *temp;

14
/*kreiranje novog cvora koriscenjem poslednje vrednosti*/

Temp = (struct node *) malloc(sizeof(struct node));

If (temp==NULL)

Printf(“greska pri alociranju memorije.\n”);

Exit(0);

Temp->data =value;

Temp->link=NULL;

If (*rear==NULL)

*rear=temp;

*front=*rear;

Else

(*rear)->link=temp;

*rear = temp

Void delte ( struct node **front, struct node **rear, int * value)

Struct node *temp;

15
If ((*front== *rear) ``(*rear ==NULL)

Printf(“red je prazan. Ne moze se obrisati vrednost.\n”);

Exit (0);

*value = (*front)->data;

Temp= *front;

*front = (*front)->link;

If (*rear==temp)

*rear = ( *rear) ->link;

Free (temp);

Void main ()

Struct node *front = NULL, *rear = NULL;

Int n, value;

Do

Do

Printf(“unesite elemenat koji zelite da dodate u red:\n”);

Scanf (“%d”,value);

Insert (front, rear, value);

16
Printf(“unesite 1 za dodavanje novog elementa u red:\n”);

Scanf (“%d”,n);

} while (n==1);

Printf (“unesite 1 za brisanje elementa iz reda :\n”);

Scanf (“%d”,n);

While ( n==1);

Delete ( front, rear, value);

Printf(“obrisana vrednost je %d\n”,value);

Printf(“unesite 1 za brisanje elemenata iz reda:\n”);

Scanf (“%d”,n);

Printf ( “unesite 1 za dodavanje novog elementa u red:\n”);

Scanf (“%d”,n);

} while (n==1);

17
3.Stabla

Stablo se cesto koristi kao glavni oblik nekog nekog spremista podataka, zbog lakog
pisanja odgovarajuceg koda koriscenje rekurzije, brzog upisivanja podataka I brzog pristupa
trazenim podacima. Najcesce korisceno stablo je stablo u kojem svaki cvor mora imati tacno dve
grane, tj binarno stablo. U terminologiji stabla kao strukture podataka koriste se slicni pojmovi
kao kod obicnog stabla. Tako, svor koji ne sadrzi granu nijednog drugog cvora a koji posredno ili
neposredno sadrzi sve druge cvorove naziva se “koren”. Cvorovi koji ne sadrze ni jednu granu, tj
nalaze se na “vrhu” stable, nazivaju se “listovima”. Stablo se u programiranju ostvaruje
koriscenjem pokazivaca da bi se usmerio ka odgovarajucim granama. Naime, svaki cvor se
konstruise tako da poseduje mogucnost cuvanja jedne ili vise adrese drugih cvorova, sto
omogucava “prelazenje” iz jednog cvora u drugi. Buduci da stablo moze imati neogranicen broj
cvorova, iterativno resenje konstrukcije I koriscenja stabla najcesce nije dobro niti lako resenje.
Umesto toga, pisu se funkcije koje se rekurzivno pozivaju dok jedna od funkcija ne primi trazeni
cvor kao argument. Tada se izvrsi zeljena radnjai rekurzivni lanac seodmotava I zavrsava.
Slabost rekurzivnog resenja lezi u situacijama kada je stablo veliko, te dolazi do prenatrpavanja
funkcijskog steka procesa sto moze dovesti do usporenosti ili naglog prekidanja celog programa.
dok se binarno stablo ostvaruje relativno jednostavno, koriscenjem tacno dva pokazivaca,
neogranicen broj grana po cvoru se implementira na nesto slozeniji nacin. Potrebno je u svakom
cvoru cuvati neku strukturu podataka koja podrzava neogranicen broj pokazivaca, sto se najcesce
cini koriscenjem liste ili obicne nizove koji seprosiruju po potrebi.

Stablo je nelinearna struktura podataka koja predstavlja hijerarhijski odnos između elemenata.
Dobro poznati primeri strukture stabla iz svakodnevnog života su izgled sadržaja neke knjige na
njenom početku, rodoslovi familija i razne organizacione šeme. Stabla se u raznim oblicima vrlo
često koriste i u računarstvu. Na primer, skoro svi operativni sistemi organizuju sistem datoteka i
foldera na način koji odgovara strukturi stabla. Druga primena strukture stabla je za
predstavljanje izraza u programima prilikom njihovog prevodenja od strane prevodilaca. Ove
sintaksne kategorije se kod prevodilaca interno predstavljaju u obliku stabla izraza. Pored ovih
neposrednih primena stabala, važna je i njihova indirektna primena za predstavljanje drugih
struktura podataka kao što su disjunktni skupovi, redovi sa prioritetima i tako dalje.

3.1 Korenska stabla

Najopštije govoreći, stabla su samo specijalni slučaj grafova. Međutim, u ovom poglavlju
ne ćemo punu pažnju posvetiti ovim opštim stablima, nego njihovoj ogranicenoj verziji koja se
nazivaju binarna stabla. Ipak radi potpunosti, pojmove u vezi sa stablima navodimo u opštijem
slučaju korenskih stabala (ili stabala sa korenom). Korensko stablo se sastoji od skupa elemenata
koji se nazivaju čvorovi , kao i skupa uređenih parova različitih čvorova povezanih linijama koje

18
se nazivaju grane. Jedan od čvorova korenskog stabla je poseban po tome što označava koren
stabla. Na crtežima se čvorovi stabla obično označavaju kružićem, a koren stabla se obično
prikazuje na vrhu hijerarhijske strukture koju čini stablo. Na slici je prikazan primer korenskog
stabla sa 11 čvorova, gde je čvor v1 koren stabla. Pošto u nastavku ovog poglavlja govorimo
isključivo o korenskim stablima, radi jednostavnosti ćemo ih kraće zvati prosto stablima.

Koreno stablo

Stablo se neformalno najlakše predstavljaju crtežom njihovih čvorova i grana koje ih


povezuju, ali je potrebno razjasniti još neke detalje u vezi sa stablima. Pre svega, jedna grana
stabla je uređen par dva različita čvora x i y. U tekstu se ta grana označava sa ( x, y), a na
crtežima linijom koja spaja čvorove x i y. Primetimo da bi pravilnije bilo da na crtežima
koristimo strelicu od x do y, jer je važno koji čvor je prvi a koji drugi u uredjenom paru koji
predstavlja granu. Ipak se radi lakšeg crtanja koristi linija za granu, a ne strelica, jer se redosled
čvorova grane ukazuje time što se prvi čvor na crtežima uvek prikazuje iznad drugog čvora.

Terminologija u vezi sa stablima je uglavnom pozajmljena iz njihove primene u


predstavljanju rodoslova neke porodice, gde se granama uspostavlja međusobni odnos roditelj-
dete izmedju pojedinih članova porodice. Tako se u računarstvu za granu ( x, y) u stablu kaže da
je prvi čvor x roditelj čvora y, odnosno da je drugi čvor y dete čvora x. Na primer, u stablu je
čvor v2 roditelj čvora v7 i v7 je dete čvora v2.

Čvor u stablu može imati nula ili više dece, ali svaki čvor različit od korena ima tačno jednog
roditelja i koren stabla je jedini čvor bez roditelja.Ova osobina je upravo ona koja karakteriše
stablo i koristi se za formalnu definiciju (korenskog) stabla: stablo T je skup čvorova i skup
grana izmedju njih (tj. uređenih parova čvorova) sa sledećim svojstvima:

1.Ako je T neprazno stablo, ono ima jedinstven poseban čvor (koren) koji nema roditeljski čvor.

2.Svaki čvor u T osim korena ima jedinstven roditeljski čvor v.

Primetimo da na osnovu ove formalne definicije stablo može biti prazno, što znači da takvo
stablo nema nijedan čvor (i nijednu granu). To omogućava da se stablo definiše i rekurzivno na

19
način kojim se veća stabla konstruišu od manjih: stablo T je prazno ili se sastoji od čvora r, koji
se naziva koren stabla T, i (moguce praznog) skupa stabala T1,T2,...,Tk čiji su koreni deca čvora
r.

Ostali pojmovi u vezi sa stablima su prilično prirodni, mada mnogobrojni. Deca istog
čvora (tj. čvorovi sa zajedničkim roditeljem) nazivaju se braća (sestre). Čvorovi koji imaju bar
jedno dete su unutrašnji, a čvorovi bez dece su spoljašnji. Spoljašnji čvorovi se često nazivaju I
listovi. Na primer, u stablu čvorovi v2, v3, v4 i v5 su braća, a svi listovi tog stabla su v3, v6, v7,
v8, v9 i v11.

Pojam puta u stablu je na neki način uopštenje pojma grane. Put između dva različita
čvora x i y je niz čvorova x = v1,v2,...,vm = y ukoliko postoji grana između svih susednih
čvorova (ˇ vi,vi+1) za 1ˇ≤ i < m. Dužina tog puta je broj grana na putu, odnosno m−1. Za svaki
čvor se podrazumeva da postoji put dužine 0 od tog čvora do samog sebe. Na primer, put u stablu
od čvora v5 do v11 sastoji se od čvorova v5, v10 i v11, a dužina tog puta je dva.

Bitna osobina stabla je da za svaki čvor u stablu postoji jedinstven put od korena do tog
čvora. Da bismo ovo pokazali, lako je najpre videti da uvek postoji put od korena do nekog čvora
x. Naime, ukoliko uzimamo čvorove od čvora x prateci u svakom koraku jedinstvenog roditelja
pojedinih čvorova, dobijamo niz čvorova koji u obrnutom redosledu formira put od korena do
čvora x. Jedinstvenost tog puta se pokazuje kontradikcijom: ako bi postojao još jedan različit put,
onda bi ta dva puta od korena morali da se kod nekog čvora najpre razdvoje i zatim ponovo spoje
u bar jednom zajedničkom čvoru y (inace bi divergirali i jedan od puteva nikad ne bi stigao do
x). Ali to bi značilo da čvor y ima dva roditelja, što je nemoguće kod stabla.Svaki čvor u na
jedinstvenom putu od korena do nekog čvora v se naziva predak čvora v. Obrnuto, čvor v je
potomak čvora u ukoliko je u predak čvora v. Podrazumeva se da je svaki čvor u stablu sam sebi
predak i potomak. Odnos predak-potomak za čvorove stabla se kraće može roditelja definisati
rekurzivno.

Podstablo sa čvorom v kao korenom je stablo koje se sastoji od tog čvora v i svih
njegovih potomaka, zajedno sa nasleđenim granama. Na primer, sva stabla T1,T2,...,Tk su
podstabla stabla T sa korenima, redom, r1,r2,...,rk.

Dubina čvora je dužina jedinstvenog puta od korena do tog čvora. Zato je, rekurzivno, dubina
korena jednaka 0, a dubina svakog drugog čvora je za jedan veca od dubine njegovog
roditelja.Visina čvora se takode može definisati rekurzivno: visina lista je 0, a visina čvora koji
nije list je za jedan veća od maksimalne visine njegove dece.Visina stabla je visina njegovog
korena.

20
3.2 Stablo kao struktura podataka

Slicno kao u slučaju osnovnih struktura podataka (nizova, listi, stekova, redova), da bismo
stabla koristili u programima za organizaciju kolekcije podataka, moramo imati nacin za
predstavljanje stabala u računaru i implementirati skup korisnih operacija nad stablima.

U radu sa stablima se može pojaviti potreba za vrlo raznolikim operacijama. Na primer,


pored osnovnih operacija za dodavanje, uklanjanje ili odredivanje deteta datog čvora, možemo
imati i operacije koje kao rezultat daju roditelja, sasvim levog deteta ili desnog brata datog cvora.
Radi lakšeg programiranja korisno bi bilo realizovati i upitne operacije koje odreduju da li je
dato stablo prazno, ili da li je dati čvor koren, interni, eksterni I slicno. Najzad, treba imati na
umu i pomoćne operacije koje obuhvataju postupke konstruisanja novog stabla, odredivanja
broja čvorova (veličine) stabla, odredivanje visine stabla i tako dalje. Medjutim, ukoliko se
koristi odgovarajuca reprezentacija stabla, sve ove operacije se mogu relativno lako
implementirati i zato necemo ići u konkretne detalje njihove praktične realizacije. Zato ćemo u
ovom odeljku malo detaljnije razmotriti samo nacine za predstavljanje korenskih stabala.Pre
svega, stablo predstavlja kolekciju podataka tako što se pojedinačni podaci u kolekciji nalaze u
čvorovima stabla

Slično kao kod osnovnih struktura podataka, pojedinačni podaci u čvorovima stabla se na
opštem nivou poistovećuju sa jednoznačnom vrednošću koja se naziva njihov kljuc i tako radi
jednostavnosti zanemaruju dodatni podaci koje čvorovi u stvarnosti možda sadrže. Najprirodnija
reprezenta čija stabla, koja najociglednije odražava njegovu logičku strukturu, bila bi da se svaki
čvor stabla predstavlja objektom koji obuhvata polje ključa, više polja u kojima se nalaze
pokazivači na svako dete tog čvora i, eventualno, polje za pokazivač na roditelja čvora.
Međutim, pošto je ovde reč o opštim stablima, odnosno broj dece po čvoru može biti vrlo različit
i nije unapred ograničen, ovaj pristup nije najbolji jer proizvodi loše iskorišćenje memorijskog
prostora. Zato se obično koriste dva druga načina za predstavljanje opštih stabala o kojima
govorimo u nastavku.

Predstavljanje stabla listama dece čvorova.Jedan način za prevazilaženje problema


nepoznatog broja dece nekog čvora u opštem stablu jeˇ formiranje povezane liste dece svakog
čvora. Ovaj pristup je važan, jer se može lako generalizovati za predstavljanje složenijih
struktura kao što su grafovi.

21
3.3 Binarna stabla

Binarno stablo je stablo u kojem nijedan čvor nema više od dvoje dece. Ova deca se zovu
levo dete i desno dete, pošto se na crtežima prikazuju levo i desno od čvora koji je njihov
roditelj. Formalno, binarno stablo je stablo u kojem svaki čvor ili nema decu, ili ima samo levo
dete, ili ima samo desno dete, ili ima i levo i desno dete.

Obratite pažnju na to da pojam binarnog stabla nije isti kao za obično stablo koje smo
definisali u prethodnom odeljku, jer svako dete u binarnom stablu mora biti levo dete ili desno
dete. Ovo zapažanje je ilustrovano na slici gde imamo dva različita binarna stabla i jedno
običnno stablo koje izgleda vrlo slično ovim binarnim stablima.

Primetimo da stabla pod (a) i (b) na slici nisu ista binarna stabla, niti je neko od njih
uporedivo sa običnim stablom pod (c). Na primer, ubinarnom stablu pod (a) čvor 2 je levo dete
čvora 1, a čvor 1 nema desno dete, dok u binarnom stablu pod (b) čvor 1 nema levo dete ali ima
čvor 2 kao desno dete. Sa druge strane, u običnom stablu pod (c) nemamo definisano levo ili
desno dete čvor 2 je samo dete čvora 1, niti levo niti desno.

Razlika između običnih I binarnih stabala

Uprkos ovim malim konceptualnim razlikama, osnovna terminologija opštih stabala


prenosi se i na binarna stabla. Svi osnovni pojmovi koje smo definisali za obična stabla imaju
smisla i za binarna stabla.ˇ

Predstavljanje binarnog stabla je umnogome pojednostavljeno zahvaljujući činjenici da


svaki čvor binarnog stabla ima najviše dvoje dece. U praksi se za predstavljanje binarnih stabala
skoro isključivo koriste pokazivači, jer je takva njihova reprezentacija prirodna i jednostavna.
Preciznije, binarno stablo je organizovano u obliku povezane strukture podataka u kojoj je svaki
čvor predstavljen jednim objektom. Taj objekat ima polje ključ, koje sadrži ključ čvora, kao i dva
pokazivačka polja levo i desno, koja pokazuju na objekte koji predstavljaju levo i desno dete
čvora. Ako neko dete nije prisutno, odgovarajuće pokazivačko polje sadrži vrednost null. Stablu
T se kao celini pristupa preko posebnog spoljašnjeg pokazivača t koji nije deo stabla i koji
pokazuje na koren stabla. Ovaj način predstavljanja binarnog stabla je ilustrovan u desnom delu
na slici za stablo koje je prikazano u levom delu.

22
3.4 Binarna stabla pretrage

Binarno stablo pretrage je binarno stablo u kojem svaki čvor v ima sledeće BSP svojstvo: svi
čvorovi u levom podstablu čvora v imaju ključeve koji su manji od ključa čvora v, a svi čvorovi
u desnom podstablu čvora v imaju kljuceve koji su veći od ključa čvora v. BSP svojstvo
binarnog stabla T možemo dakle izraziti na sledeći način: za svaki čvor v stabla T, ako je u čvor
u levom podstablu čvora v, onda je v.ključ > u.ključ; a ako je w čvor u desnom podstablu čvora
v, onda je v. ključ < w. ključ. (Ovde pretpostavljamo pojednostavljen slučaj da su svi ključevi
različiti.)

Obratite pažnju na to da u binarnom stablu pretrage implicitno podrazumevamo da se ključevi


čvorova mogu međusobno upoređivati. To znači da ključevi pripadaju nekom totalno uređenom
skupu, tj. skupu nad čijim elementima je definisana relacija „manje od”. Primeri ovih skupova
obuhvataju skupove celih i realnih brojeva sa uobičajenom relacijom poretka brojeva, kao i skup
znakovnih stringova sa leksikografskim poretkom.

3.5 BSP operacije

Tipične operacije nad binarnim stablom pretrage su traženje, dodavanje i uklanjanje čvora iz
takvog stabla.

Traženje čvora.Najpre ćemo pažnju posvetiti problemu traženja čvora sa datim ključem x u
binarnom stablu pretrage T. Da bismo brzo locirali čvor sa ključem x u stablu T, ili utvrdili da se
čvor sa tim ključem ne nalazi u stablu, koristimo BSP svojstvo. Naime, ukoliko uporedimo x sa
ključem korena stabla T, razlikuju se tri slučaja.

Prvi, najlakši slucaj je ako je ključ korena stabla T jednak x, jer smo onda našli traženi čvor i
možemo završiti pretragu. U drugom slučaju, ako je ključ korena stabla T veci od x, prema BSP
svojstvu možemo zaključiti da se cvor sa ključem x može naci samo u levom podstablu korena
stable T, jer su u desnom podstablu svi ključevi veći od ključa korena, pa time i od x. Zbog toga
pretragu rekurzivno nastavljamo na isti nacin od korena levog podstabla korena stabla T. Najzad,
u trecem slučaju koji je simetričan drugom, ako je kljuc korena stabla T manji od x, onda se cvor

23
sa ključem x može naci samo u desnom podstablu korena stabla T. Zbog toga pretragu
rekurzivno nastavljamo na isti način od korena desnog podstabla korena stabla T.

Ovaj neformalni opis operacije traženja čvora u binarnom stablu pretrage preciziran je
rekurzivnim algoritmom bst-search u nastavku. Ako su dati pokazivači t na neki čvor u binarnom
stablu pretrage i ključ x, algoritam bst-search kao rezultat vraća pokazivač na čvor sa ključem x,
ukoliko se takav čvor nalazi u podstablu čiji je koren t u suprotnom slučaju, ukoliko takav čvor
ne postoji, ovaj algoritam vraća pokazivač null.

Ilustrovan način rada algoritmaˇ bst-search na primeru jednog binarnog stabla pretrage.

Traženje čvora 13 u datom binarnom stablu pretrage.

Kao što se vidi sa slike u algoritmu bst-search se pretraga zapocinje od korena stabla i prelazi se
određen put nadole duž grana i čvorova u stablu. Za svaki čvor na tom putu, u algoritmu se
upoređuje ključ tog čvora sa traženom vrednošću. Ako su oni jednaki, pretraga se završava. U
suprotnom slučaju, pretraga se nastavlja u levom ili desnom podstablu čvora zavisno od toga da
li je ključ čvora veći ili manji od tražene vrednosti. Pošto čvorovi na koje se rekurzivno dolazi
tokom pretrage obrazuju put u stablu od korena pa do nekog lista u najgorem slučaju, vreme
izvršavanja algoritma bst-search je O(h) za stablo visine h.

24
Literatura

 https://en.wikipedia.org/wiki/Python_(programming_language)
 http://www.vps.ns.ac.rs/Materijal/mat21058.pdf
 http://www.link-university.com/lekcija/Složeni-tipovi-podataka-2/2542
 https://www.scribd.com/document/48560781/stek-red-dek-stabla

25

You might also like