Upload
others
View
8
Download
3
Embed Size (px)
Citation preview
VISOKA ŠKOLA STRUKOVNIH STUDIJA ZA INFORMACIONE TEHNOLOGIJE
STRUKTURE PODATAKA I
ALGORITAMSKO MODELOVANJE skripta
Aleksandar Kostić
2
Sadržaj
Sadržaj .......................................................................................................................... 2
1 OSNOVNI POJMOVI .......................................................................................... 4
2 O ALGORITMIMA ............................................................................................. 7
2.1 Pojam algoritma ............................................................................................ 7
2.2 Grafički simboli .......................................................................................... 10
2.3 Vrste algoritamskih šema ............................................................................ 13
2.4 Predstavljanje algoritama pomoću blok dijagrama ....................................... 19
3 POLJA ............................................................................................................... 30
3.1 Uvod ........................................................................................................... 30
3.2 Memorijska reprezentacija polja .................................................................. 31
3.3 Dinamička polja .......................................................................................... 33
3.4 Višedimenzionalna polja ............................................................................. 33
3.5 Matrice ........................................................................................................ 34
3.6 Primeri primene .......................................................................................... 35
4 LANČANE LISTE ............................................................................................. 40
4.1 Uvod ........................................................................................................... 40
4.2 Memorijska reprezentacija jednostruko ulančane liste ................................. 42
4.3 Dvostruko ulančane liste ............................................................................. 47
4.4 Liste sa preskokom ...................................................................................... 49
5 MAGACIN, RED I DVOSTRANI RED ............................................................. 53
5.1 Uvod ........................................................................................................... 53
5.2 Magacin ...................................................................................................... 53
5.3 Memorijska reprezentacija .......................................................................... 56
5.4 Primeri primene .......................................................................................... 57
5.5 Red ............................................................................................................. 60
3
5.6 Memorijska reprezentacija .......................................................................... 64
5.7 Dvostrani red............................................................................................... 65
5.8 Osnovne operacije ....................................................................................... 65
5.9 Memorijska reprezentacija .......................................................................... 66
6 STABLA ............................................................................................................ 67
6.1 Uvod ........................................................................................................... 67
6.2 Binarna stabla ............................................................................................. 68
6.3 Memorijska reprezentacija .......................................................................... 72
6.4 Primeri primene .......................................................................................... 79
7 ALGORITMI SORTIRANJA ............................................................................. 82
7.1 Sortiranje izborom najmanjeg elementa (Selection sort) .............................. 82
7.2 Sortiranje zamenom susednih elemenata (bubble sort) ................................. 84
7.3 Sortiranje umatanjem (insertion sort) ........................................................... 86
7.4 Brzo sortiranje (quick sort) .......................................................................... 88
7.5 Višestruko sortiranje umetanjem (Shell sort) ............................................... 90
8 PRETRAŽIVANJE ............................................................................................ 94
8.1 Sekvencijalno pretraživanje ......................................................................... 94
8.2 Binarno pretraživanje .................................................................................. 95
8.3 Binarno stablo za pretraživanje .................................................................... 96
8.4 Kreiranje binarnog stabla za pretraživanje ................................................... 97
8.5 Pretraživanje u binarnom stablu za pretraživanje ......................................... 98
8.6 Umetanje vrednosti u binarno stablo za pretraživanje .................................. 99
8.7 Brisanje čvora iz binarnog stabla za pretraživanje...................................... 100
8.8 Pretraživanje po binarnom stablu za pretraživanje ..................................... 104
9 Literatura ......................................................................................................... 105
4
1 OSNOVNI POJMOVI
Izuzetno brz razvoj savremenih informacionih tehnologija nameće pred programere
jasan ali i težak zadatak, da svoj posao obavljaju kvalitetno i efikasno. Da generišu originalne
ideje, realizuju ih i brzo plasiraju na veoma zahtevno i izbirljivo tržište softverskih proizvoda.
Proces kojim se dolazi do pravog rezultata možemo opisati sa nekoliko koraka, a to su:
precizan opis problema, definisanje modela i izbor metoda za njegovo rešavanje,
projektovanje algoritama, pisanje i testiranje programa, i izrada prateće dokumentacije.
Znanje iz ovog predmeta trebalo bi da nam omogući da bolje programiramo. Naime,
razvoj programa (metodom postepenog profinjavanja) može se posmatrati u skladu sa
sledećim dijagramom.
Slika 2.1-1 Postupak rešavanja problema.
Iz ovog dijagrama vidi se uloga apstraktnih tipova podataka, struktura podataka i
algoritama u postupku rešavanja problema. Takođe se vidi da se programiranje u podjednakoj
meri sastoji od razvijanja struktura podataka kao i od razvijanja algoritama.
Znači možemo na neki način sažeto reći, u računarstvu, njegovom delu koji se odnosi na
programiranje, susrećemo se sa dva osnovna pojma:
• strukture podataka koje predstavljaju “statički” aspekt nekog programa. Ili,
drugačije rečeno predstavljaju ono sa čime se radi.
• algoritmi sa svoje strane predstavljaju “dinamički” aspekt programa. Odnosno,
ono šta se radi.
5
Strukture podataka i algoritmi kao pojmovi egzistiraju u neraskidivoj vezi: naime,
nemoguće je govoriti o jednom a da se ne spomene drugi pojam. U okviru predmeta Strukture
podataka i algoritamsko modelovanje proučavaćemo baš tu vezu: osnovni cilj je da
posmatramo kako odabrana struktura podataka utiče na algoritme za rad s njom, odnosno
kako odabrani algoritam sugerira pogodnu strukturu za prikaz svojih podataka. Ishod ovakvog
učenja je upoznavanje niza važnih ideja i pojmova , koji čine osnove računarstva.
Sama reč algoritam vodi poreklo od imena jednog od deset najcenjenijih matematičara
svih vremena, Abu Ja'far Mohammed ibn Musa al Khowarizmi (Muhamed, otac Jafarov, sin
Muse iz Khwarizma) koji je rođen u mestu Khwarizm, danas Khiva, Uzbekistan, oko 780.
god. (umro u Bagdadu, oko 850 godine). On je verovao da
se bilo koji matematički problem može rasčlaniti na
korake, tj. niz pravila. U latinskom prevodu njegove
knjige (12. vek) ispred svakog pravila piše Dixit
Algorizmi - rekao je Al Kowarzimi, odnosno
�
algoritam glasi
U početku algoritmom se nazivaju samo pravila
računanja s brojevima kasnije i pravila obavljanja ostalih
zadataka u matematici. U XX veku, pojavom računara,
pojam se proširuje na računarstvo, a zatim i na druga naučna područja. Interesantno je da se i
reč algebra i, uopšte neka pravila računanja, vezuju za ovog matematičara.
Uz “strukture podataka” i “algoritme”, ovaj predmet koristi još nekoliko naizgled
sličnih pojmova. Objasnićemo njihovo značenje i međusobni odnos.
• tip podataka je skup vrednosti koje neki podatak može poprimiti (npr. podatak
tipa int može imati samo vrednosti iz skupa celih brojeva koji se mogu prikazati
u nizu).
• apstraktni tip podataka (a.t.p.) se zadaje navođenjem jednog ili više tipova
podataka, uz jednu ili više operacija (funkcija). Operandi i rezultati navedenih
operacija su podaci navedenih tipova. Među tipovima postoji jedan istaknuti po
kojem celi apstraktni tip podataka dobija ime.
• struktura podataka je skup promenjljivih u nekom programu i veza među tim
promenjljivima.
6
• algoritam predstavlja konačni niz instrukcija, od kojih svaka ima jasno značenje
i može biti izvršena u konačnom vremenu. Iste instrukcije mogu se izvršiti više
puta, pod pretpostavkom da same instrukcije ukazuju na ponavljanje. Ipak,
zahtevamo da se, za bilo koje vrednosti ulaznih podataka, algoritam mora
završiti posle konačnog broja ponavljanja.
• implementacija apstraktnog tipa podataka je konkretna realizacija dotičnog
apstraktnog tipa podataka u nekom programu. Sastoji se od definicije za
strukturu podataka (kojom se prikazuju podaci iz apstraktnog tipa podataka) i od
potprograma (kojima se operacije iz apstraktnog tipa podataka ostvaruju pomoću
odabranih algoritama). Za isti apstraktni tip podataka obično se može smisliti
više različitih implementacija - one se razlikuju po tome što koriste različite
strukture za prikaz podataka te različite algoritme za izvršavanje operacija.
Prvih nekoliko potpoglavlja obrađuje po jedan apstraktni tip podataka. Posmatraju se
razne implementacije za taj apstraktni tip podataka i njihove prednosti i mane. Na taj način
upoznaćemo više apstraktnih tipova podataka, i još više struktura podataka i algoritama.
Daljnja potpoglavlja obraduju algoritme za sortiranje i pretraživanje. U oblikovanju
algoritama za sortiranje primjenjuju se pojedini apstraktni tipovi odnosno strukture podataka
iz prethodnih poglavlja.
7
2 O ALGORITMIMA
2.1 Pojam algoritma
Pojam algoritma je usko vezan za rešavanje zadataka pomoću računara. Algoritme
možemo posmatrati kao alate za rešavanje zadatih problema (računarski problemi). Osnovne
karakteristike jednog algoritma su: polazne, ili ulazne veličine, način rešavanja zadatka,
postavka zadatka i izlazne veličine ili rezultat. Postavka problema opisuje, u opštem slučaju,
određenu vezu (relaciju) izmedu ulaznih i izlaznih podataka. Algoritam opisuje speciflčan
postupak za dostizanje te veze.
Dovoljno tačna definicija algoritma bi bila: Algoritam je skup pravila formulisanih za
rešavanje nekog zadatka. Neformalno govoreći, algoritam je potpuno (precizno) definisana
procedura (postupak) koji uzima (dobija) jednu ili više ulaznih vrednosti i daje (proizvodi,
generiše) jednu ili više izlaznih vrednosti.
Algoritam mora biti sasvim precizno definisan postupak, bez dvosmislenosti i
nedorečenosti. Zbog toga se obično ne zapisuje na prirodnom jeziku već na potpuno
preciznom jeziku: najčešće na nekom programskom jeziku ili jeziku sličnom programskom
jeziku (pseudoprogramski jezik, pseudojezik). Pseudojezici su jezici nastali izvesnim
modiflkacijama programskih jezika i obezbeđuju da se algoritam zapiše precizno i koncizno.
Pored toga mogu se koristiti i prirodni jezici.
Karakteristike svake algoritamske šeme morale bi biti takve da omoguće: (1) lako
otkrivanje grešaka u strukturi algoritma, (2) kraći i jasniji zapis algoritma, (3)preglednu vezu
(detalji – celina), i (4) nezavisnost od daljeg korišćenja.
Što se tiče formi predstavljanja, algoritmi se mogu, a i najčešće se, predstaviti kao blok
šeme ili u nekom grafičkom zapisu.
Algoritmi predstavljaju deo procesa rešavanja problema pomoću računara, a ceo proces
možemo podeliti u etape, na sledeći način:
• Precizna formulacija ili opis problema
• Izrada matematičkog oblika, ili modela, problema,
• Algoritmizacija problema ili projektovanje algoritama,
• Programiranje ili kodiranje,
• Izrada test primera,
• Testiranje problema, i
8
• Dobijanje i analiza rezultata.
Na sledećoj slici su data dva načina koji opisuju uzajamnu vezu navedenih etapa u
razvoju softverskog paketa. To su razvojni proces tipa vodopad i iterativni model.
Vodopad Iterativni model
Aktivnosti koje se podrazumevaju pod opisom problema, bile bi:
• definisati koje su informacije poznate i dostupne kao ulazni podaci, i
• koja informacija i u kom obliku treba da se dobije kao rezultat.
• u ovu etapu mogu biti uključena i lica koja se ne bave programiranjem (lekari,
tehnolozi, ekonomisti,..., dakle lica koja odlično poznaju tehnologiju problema
ili ga poznaju bolje od programera).
Izrada matematičkog oblika, ili modela, problema. Nakon definisanja problema,
prelazi se na opis problema formalnim aparatom, recimo matematičkim. Znači, započinjemo
sa korišćenjem matematičkih formula i relacija. Odgovarajući primer za to je, npr.
modelovanje sistema linearnih jednačina, kao tipično matematički sistem.
Pored tvz. tačnih metoda za rešavanje, postoje i približne metode. U računarstvu se
veoma često koristi aparat numeričke analize, jer se zahteva dobijanje nekog numeričkog
rezultata. Postoji čitav niz problema koji se ne mogu rešiti klasičnim metodama ili je njihovo
rešavanje isuviše glomazno, kao, recimo, problemi za rešavanje sistema jednačina velikog
reda. Tom prilikom se isključivo koriste numerički metodi, a numerički metodi koriste samo
osnovne aritmetičke operacije.
9
Projektovanje algoritma. Po Niklausu Virtu program se sastoji od algoritama i
podataka. Postoji i njegova definicija da je algoritam “Efektivna procedura za rešavanje
problema u konačnom broju koraka ”.
Dobro projektovan algoritam uvek obezbeđuje neko rešenje, koje ne mora da bude ono
koje očekujete. Rešenje može da bude i da nema rešenja. Dobro projektovan algoritam mora
garantovati završetak rada.
Dobro napisan algoritam mora poštovati sledeća pravila:
• Diskretnost. Algoritam se sastoji od konačnog broja posebnih koraka
(algoritamski koraci). Svaki korak može zahtevati obavljanje jedne ili više
operacija. U zavisnosti od toga koje operacije računar može da obavi, uvode se
ograničenja za tip operacija koje se u algoritmu mogu koristiti (najčešće
sabiranje, oduzimanje, množenje, deljenje).
• Determinisanost. Svaki algoritamski korak mora biti strogo definisan i potpuno
jasan. Na primer, izrazi tipa: izračunaj pet podeljeno sa nulom ili “dodaj 6 ili 7
puta” nisu dozvoljeni. Posle izvršenja tekućeg algoritamskog koraka mora biti
jednoznačno definisano koji je sledeći korak.
• Efektivnost ili konačnost. Sve operacije koje se javljaju u jednom
algoritamskom koraku moraju se izvršiti za konačno, odnosno, razumno kratko
vreme. Vreme izvršenja celog algoritma mora biti konačno, to jest, razumno
dugo.
• Rezultativnost. Svaki algoritam mora posle konačnog broja koraka generisati
traženi rezultat. Algoritam može imati nula ili više ulaznih podataka i može
generisti jedan ili više izlaznih rezultata.
• Masovnost. Svaki algoritam definiše postupak za rešavanje klase problema, a ne
pojedinačnog slučaja. Na primer, rešavanje sistema jednačina bilo kog reda,
množenje matrica proizvoljnog reda, i tako dalje.
• Optimalnost. Na temu optimalnosti, ključne osobine jednog algoritma bile bi:
o Vremenska kompleksnost – koliko brzo?
o Prostorna – koliko memorije?
o Kompleksnost koda - snalaženje u kodu?
o Međusobno povezane i uslovljene
10
Pisanje i testiranje programa. Nakon razrade algoritma prelazi se na pisanje
programa. Program mora biti napisan u formi koju računar “razume”. Svaki algoritamski
korak se zamenjuje nizom instrukcija, jer instrukcije čine računarski program. Svaka
instrukcija mora biti napisana po odredjenim pravilima. Ta pravila čine jezik kojim se izdaju
naredbe računaru odnosno programski jezik.
Svaki programski jezik ima skup pravila kojima se definišu važeće jezičke konstrukcije
i taj skup pravila se naziva sintaksa jezika. S druge strane, značenje ili dejstvo instrukcija čini
semantiku jezika.
Definišimo osnovne karakteristike programskih jezika.
Mašinski jezik je jedini jezik direktno razumljiv računaru. Za računar ovaj jezik
predstavlja niz elektronskih impulsa a programer ovaj jezik simbolički izražava pomoću
binarnih brojeva (niz nula i jedinica). Svaki računar ima svoj mašinski jezik koji je direktno
zavistan od hardvera računara (zovu se još i niži programski jezici).
Viši programski jezici. Viši programski jezici su nezavisni od hardvera računara. Tako
da program napisan na višem programskom jeziku za jedan računar, može se izvršavati i na
drugom računaru. Naravno, zbog ove karakteristike program napisan na višem programskom
jeziku računar ne može direktno “razumeti” i zbog toga mu je potreban prevodilac sa višeg na
niži jezik. Prevodjenje obavljaju posebni programi – prevodioci (kompilatori, compiler-i).
Napomenimo da se u fazi prevodjenja programa vrši sintaksna analiza i otkrivaju formalne
(pravopisne) greške. Greške logičkog tipa računar ne može otkriti.
Izvršavanje na primerima. Nakon faze kompajliranja, programer prelazi na
izvršavanje programa sa test primerima. Testiranje treba obaviti sa poznatim rezultatima, u
prvom redu što jednostavnijim kako bi se otkrile logičke greške. Test primere treba odabrtati
tako da se prodje bar jednom kroz svaku granu algoritma, tj. liniju programa.
Testiranjem se ne dokazuje korektnost, već neispravnost algoritma ili programa. Za
dokaz korektnosti programa koristi se aparat matematičke logike.
2.2 Grafički simboli
Grafičko predstavljanje algoritama je zbog svoje jednostavnosti i preglednosti
najkorišćeniji pristup u projektovanju programskih rešenja. Ovde ćemo navesti nekoliko
osnovnih grafičkih elemenata koji su neophodni za rad.
Najpre, izdvojićemo dva grafi
njima su upisane reči POČETAK i KRAJ).
Pored ovih, postoje i elementi:
• pravougaoni elementi
radnju) koju treba obaviti;
• šestougaoni elementi ozna
li su elementi međusobom
od dve moguće vrednosti (istina ili laž). Zato
biti nastavljeno u jedno
ili laž). Svaki od pravaca je obeležen:
o rečju DA (ili TACNO ili .T.)
izvršavanje, ako je rezultat testiranja istina (ta
o rečju NE (ili NETACN
izvršavanje, ako je rezultat testiranja laž (neta
• Orijentisane duži povezuju elemente koji sadrže delove algoritma koji se izvršavaju
jedan za drugim. Izvršavanje algoritma po
duži određuju tok izvršavanja algoritma. Izvršavanje se prekida kada stignemo do
elementa koji odgovara KRAJ
Na Slika 2.2-1 su dati grafič
Slika
11
dva grafička elementa koja odgovaraju početku i kraju algoritma (u
ČETAK i KRAJ).
Pored ovih, postoje i elementi:
pravougaoni elementi svojim sadržajem označavaju određeno izrač
) koju treba obaviti;
šestougaoni elementi označavaju da je reč o nekom testriranju (poređ
đusobom u određenoj relaciji). Rezultat tog testiranja
e vrednosti (istina ili laž). Zato, od tog elementa izvršenje program
u jednom od dva pravca (u zavisnosti da li je rezultat testiranja istina
ili laž). Svaki od pravaca je obeležen:
ju DA (ili TACNO ili .T.) što označava pravac u kome program nastavlja
, ako je rezultat testiranja istina (tačno);
ju NE (ili NETACNO ili .F.) je obeležen pravac u kome program
ako je rezultat testiranja laž (netačno).
Orijentisane duži povezuju elemente koji sadrže delove algoritma koji se izvršavaju
jedan za drugim. Izvršavanje algoritma počinje od elementa POCETAK. Orijentisane
uju tok izvršavanja algoritma. Izvršavanje se prekida kada stignemo do
elementa koji odgovara KRAJ-u.
su dati grafički simboli koji se koriste za predstavljanje algoritama.
Slika 2.2-1 Grafički simboli za predstavljanje algoritama
četku i kraju algoritma (u
izračunavanje (ili
đenje, provera da
ezultat tog testiranja može biti jedna
izvršenje program može
tat testiranja istina
program nastavlja
program nastavlja
Orijentisane duži povezuju elemente koji sadrže delove algoritma koji se izvršavaju
ETAK. Orijentisane
uju tok izvršavanja algoritma. Izvršavanje se prekida kada stignemo do
ki simboli koji se koriste za predstavljanje algoritama.
2.2.1 Primer – množenje dva broja
Razmotrimo algoritam rešavanja zadatka množenj
prirodnih brojeva i operacije sabiranja i množenja prirodnih brojeva,
(tekstualno i grafički): Naći proizvod prirodnih brojeva X i Y
Tok algoritma
Kao primer je prikazan tok algoritma množenja dva prirodna broja
1. X = 15, Y =3 2. Z = 0 3. Z = Z + X⇒ 0 + 15 = 154. Y = Y – 1 ⇒ 3 – 1 = 25. Y ≠ 0 3. Z = Z + X ⇒ 15 + 15 = 304. Y = Y – 1 ⇒ 2 - 1 = 15. Y ≠ 0 3. Z = Z + X ⇒ 30 + 15 = 454. Y = Y – 1 ⇒ 1 – 1 = 05. Y = 0 6. Z = 45 KRAJ
Grafički prikaz
Na Slika 2.2-2 se vidi
korišćenjem prethodno objašnjenih simbola.
12
dva broja
Razmotrimo algoritam rešavanja zadatka množenja brojeva. Poznavaju
prirodnih brojeva i operacije sabiranja i množenja prirodnih brojeva, treba
ći proizvod prirodnih brojeva X i Y .
Koraci za rešavanje bi bili:
Ulazne veličine su X i Y, prekorak 2
Postaviti da je Z=O, pređUvećaj Z za X, pređi na korak 4Umanji Y za 1, pređi na korak 5Ako je Y≠0 (1,2,3...) vrati se na korak 3
Ako je Y=0 pređi na korak 7 Izlazna veličina je Z. KRAJ
Slika 2.2-2 Množenje dva broja
prikaz
rikazan tok algoritma množenja dva prirodna broja (X = 15, Y =3
0 + 15 = 15 1 = 2
15 + 15 = 30 1 = 1
30 + 15 = 45 1 = 0
se vidi grafički prikaz algoritma za množenje dva prirodna broja,
enjem prethodno objašnjenih simbola.
Poznavajući osobine
treba rešiti zadatak
Koraci za rešavanje bi bili:
ine su X i Y, pređi na
Postaviti da je Z=O, pređi na korak 3 đi na korak 4 đi na korak 5
0 (1,2,3...) vrati se na korak 3 i na korak 7
ina je Z. KRAJ.
Množenje dva broja-grafički
X = 15, Y =3).
ki prikaz algoritma za množenje dva prirodna broja,
2.2.2 Primer - stepenovanje
Sastaviti algoritamsku šemu za stepenovanje prirodnog broja
(Xn), koristeći operaciju množenja
Z = Xn ⇒
Z = X * X * X * X * X *…X (n puta)
2.3 Vrste algoritamskih šema
Algoritamske šeme se mogu podeliti u tri kategorije:
1. Linijske algoritamske šeme,
2. Ciklične algoritamske šeme, i
3. Složene algoritamske šeme.
2.3.1 Linijske šeme
Linijske algoritamske šeme
najviše jedanput u toku izvršavanja algoritma. Mogu biti
algoritamske šeme su šeme kod kojih se svaki algoritamski korak izvršava ta
toku jednog izvršavanja algoritma. Sastoji se od algoritamskih koraka ulaza, obrade i izlaza.
Linijske šeme - primer
Na Slika 2.3-1 je dat jedan primer algorit
zadatak izračunavanja vrednosti Z po slede
tako da u jednom algoritamskom koraku može b
13
stepenovanje
Sastaviti algoritamsku šemu za stepenovanje prirodnog broja X prirodnim brojem n
i operaciju množenja
Z = X * X * X * X * X *…X (n puta)
Slika 2.2-3 Stepenovanje - grafič
Vrste algoritamskih šema
Algoritamske šeme se mogu podeliti u tri kategorije:
Linijske algoritamske šeme,
ne algoritamske šeme, i
Složene algoritamske šeme.
Linijske algoritamske šeme su one šeme kod kojih se svaki algoritamski korak izvršava
najviše jedanput u toku izvršavanja algoritma. Mogu biti proste i razgranate
su šeme kod kojih se svaki algoritamski korak izvršava tač
vršavanja algoritma. Sastoji se od algoritamskih koraka ulaza, obrade i izlaza.
jedan primer algoritma predstavljen u linijskoj šemi
vrednosti Z po sledećoj formuli:
Z = X1 * (X2 – 3X3)
tako da u jednom algoritamskom koraku može biti samo jedna aritmetička operacija.
X prirodnim brojem n
grafički prikaz
su one šeme kod kojih se svaki algoritamski korak izvršava
razgranate. Proste linijske
su šeme kod kojih se svaki algoritamski korak izvršava tačno jednom u
vršavanja algoritma. Sastoji se od algoritamskih koraka ulaza, obrade i izlaza.
predstavljen u linijskoj šemi koji rešava
čka operacija.
Napomenimo da se pored znaka jednakosti (=) koristi se i simbol
dodeljivanje vrednosti promenljivoj.
prvo izračunali vrednosti f(x1, x2, ...xn), a zatim dodelili promenljivoj y
zapisati i u uobičajenom obliku:
2.3.2 Razgranate šeme
Karakteristika razgranate algoritamske šem
najviše jednom (znači jednom ili nijednom) i obavezno sadrži bar jedan uslovni algoritamski
korak.
Slika 2.3-2
14
Slika 2.3-1 Primer linijske algoritmske šeme
ored znaka jednakosti (=) koristi se i simbol ⇐
dodeljivanje vrednosti promenljivoj. Npr. ako napišemo Y ⇐ f(x1, x2, ...xn)
unali vrednosti f(x1, x2, ...xn), a zatim dodelili promenljivoj y.
ajenom obliku: Y = f(x1, x2, ...xn)
azgranate algoritamske šeme je da se algoritamski korak izvršava
či jednom ili nijednom) i obavezno sadrži bar jedan uslovni algoritamski
2 Opšti oblik blok dijagrama razgranate algoritamske šeme
⇐ koji označava
f(x1, x2, ...xn) to znači da smo
. To smo mogli
da se algoritamski korak izvršava
i jednom ili nijednom) i obavezno sadrži bar jedan uslovni algoritamski
Opšti oblik blok dijagrama razgranate algoritamske šeme
U toku jednog izvršavanja algoritma izvrši
Neka od šema P2 ili P3 može biti izostavljena. Algoritam mo
Slika
Na sledećim slikama prikazana su dva primera razgranate algoritamske šeme. U prvom
slučaju treba izračunati Z po formuli:
A u drugom, sastaviti algoritam za izra
matematike, X2 ocena iz informatike, izra
� � ������
15
U toku jednog izvršavanja algoritma izvršiće se samo jedna od prostih šema (P2 ili P3).
Neka od šema P2 ili P3 može biti izostavljena. Algoritam može imati oblik kao na
Slika 2.3-3 Primeri razgranatih algoritamskih šema
im slikama prikazana su dva primera razgranate algoritamske šeme. U prvom
unati Z po formuli:
� � � � � � � � � � ��
astaviti algoritam za izračunavanje vrednosti Z. Ako je X1 ocena iz
matematike, X2 ocena iz informatike, izračunati Z po formuli:
� ������ ����� � ������ �� ����������� � �
�
e se samo jedna od prostih šema (P2 ili P3).
že imati oblik kao na Slika 2.3-3.
im slikama prikazana su dva primera razgranate algoritamske šeme. U prvom
. Ako je X1 ocena iz
�
2.3.3 Ciklične šeme
Ciklične algoritamske šeme
može izvršavati više puta (makar dva ili više), u toku jednog izvršavanja
Uopšte rečeno, ciklične šeme se sastoje od prostih šema P1, P2, P3, P4 i uslovnog
algoritamskog koraka.
Na sledećoj slici prikazane su dve varijante cikli
16
ne algoritamske šeme su one šeme kod kojih se jedan ili više algoritamskih koraka
može izvršavati više puta (makar dva ili više), u toku jednog izvršavanja celog
čne šeme se sastoje od prostih šema P1, P2, P3, P4 i uslovnog
Slika 2.3-4 Ciklične šeme – opšti prikaz
oj slici prikazane su dve varijante cikličnih algoritamskih šema.
su one šeme kod kojih se jedan ili više algoritamskih koraka
celog algoritma.
ne šeme se sastoje od prostih šema P1, P2, P3, P4 i uslovnog
nih algoritamskih šema.
Slika 2.3-5
2.3.4 Konstantne i promenljive šeme
Ciklične algoritamske šeme mogu biti konstantne i promenljive. Konstantne cikli
šeme su šeme kod kojih se zakon obrade unutar ciklusa ne menja.
Primer za konstantne cikli
Sastaviti algoritam koji za poznato n i brojeve x
brojeva.
P = (x1+x2+x3+...+xn)/n
P = S/n S = x1+x2+x3+...+x
2.3.5 Primer za promenljive ciklične šeme
Promenljive ciklične šeme su šeme kod kojih u ciklusu dolazi do promene zakona
obrade u toku izvršavanja algoritma.
17
5 Dve varijante modifikovanih cikličnih algoritamskih šema
Konstantne i promenljive šeme
ne algoritamske šeme mogu biti konstantne i promenljive. Konstantne cikli
šeme su šeme kod kojih se zakon obrade unutar ciklusa ne menja.
e ciklične šeme:
Sastaviti algoritam koji za poznato n i brojeve x1, x2, x3,...xn, računa prose
)/n
+...+xn
romenljive ciklične šeme
čne šeme su šeme kod kojih u ciklusu dolazi do promene zakona
obrade u toku izvršavanja algoritma.
nih algoritamskih šema
ne algoritamske šeme mogu biti konstantne i promenljive. Konstantne ciklične
čuna prosečnu vrednost
ne šeme su šeme kod kojih u ciklusu dolazi do promene zakona
Primer za promjenljive cikli
� � ∑ ��1 !" # $!%!&
Napomenimo da kada je stepen neparan
(minus)
Odnosno, kada je stepen paran
U zadatku ćemo izraz (-
Z = X1 – X2 + X3 – X4
Na sledećoj slici prikazan je blok dijagram rešenja zadatka primenom promenljive
ciklične šeme.
2.3.6 Složene šeme
Složene algoritamske šeme
navedenih šema. Evo primera za složene algoritamske šeme:
poznato n>0 i brojeve x1, x2, x
slučaju da su manji od 100.
18
Primer za promjenljive ciklične šeme: Sastaviti algoritam koji izračunava sumu:
za poznato n>0 i x1, x2, x3, ... xn
je stepen neparan ⇒ (-1)3 = (-1)*(-1)*(-1) dobijamo znak
ada je stepen paran ⇒ (-1)2 = (-1)*(-1) dobija se znak + (plus)
1)i+1 obeležiti sa α, tako da dobijamo sumu:
4 + X5 – X6 …
oj slici prikazan je blok dijagram rešenja zadatka primenom promenljive
Slika 2.3-6 Primer promenljive ciklične šeme
Složene algoritamske šeme su šeme koje se dobijaju kombinacijom prethodno
navedenih šema. Evo primera za složene algoritamske šeme: Sastaviti algoritam koji za
, x3, ...xn, računa sumu brojeva x1, x2, x3, ...xn uveć
čunava sumu:
dobijamo znak -
+ (plus)
oj slici prikazan je blok dijagram rešenja zadatka primenom promenljive
su šeme koje se dobijaju kombinacijom prethodno
Sastaviti algoritam koji za
uvećanih za 5% u
2.4 Predstavljanje algoritama pomoću blok dijagrama
Ovo poglavlje i primeri koji su dati bi trebalo da, u neku ruku, budu zaklju
na jednostavniji način sublimira sve što je re
dijagrama. Pre nego što primerima to i pokažemo, ponovimo nekoliko osnovnih termina koji
su nam neophodni za dalje razumevanje.
Šta je to program ?
• Sasvim je dovoljno znati
izvršavaju nad podacima (operandi, ...).
• Šta su instrukcije, a šta su
� Uzmite najjednostavniji primer: sabiranje dva broja,
operacija, a
• Gde se nalaze instrukcije i podaci ?
19
Slika 2.3-7 Primer složene algoritamske šeme
Predstavljanje algoritama pomoću blok dijagrama
Ovo poglavlje i primeri koji su dati bi trebalo da, u neku ruku, budu zaklju
in sublimira sve što je rečeno o predstavljanju algoritama pomo
dijagrama. Pre nego što primerima to i pokažemo, ponovimo nekoliko osnovnih termina koji
su nam neophodni za dalje razumevanje.
znati da je program niz operacija (naredbi, instrukcija, ...) koje se
izvršavaju nad podacima (operandi, ...).
, a šta su podaci ?
Uzmite najjednostavniji primer: sabiranje dva broja, x
operacija, a x i y su podaci (nad kojima se operacija izvršava).
instrukcije i podaci ?
Ovo poglavlje i primeri koji su dati bi trebalo da, u neku ruku, budu zaključak koji nam
eno o predstavljanju algoritama pomoću blok
dijagrama. Pre nego što primerima to i pokažemo, ponovimo nekoliko osnovnih termina koji
da je program niz operacija (naredbi, instrukcija, ...) koje se
x i y. Sabiranje je
su podaci (nad kojima se operacija izvršava).
20
� I instrukcije i podaci se nalaze (tokom izvršavanja prgrama) u radnoj
memoriji računara (poznatijoj kao RAM).
• Ko izvršava instrukcije ?
� Procesor.
Ima li razlike između algoritama i programa ?
Suštinski nema: i program i algoritam su samo dve, doduše pojavno različite, forme,
koje nas uče jednoj te istoj stvari, a to je da se do rešenja bilo kog problema može doći iz
nekoliko koraka, rešavanjem manjih delova problema.
Kakva je korist od izučavanja algoritama ?
Velika. Ako savladamo algoritme, neuporedivo lakše ćemo moći da pratimo osnovne
pojmove iz programiranja. Stoji činjenica da ukoliko se ne ume da opišete način rešavanja
nekog problema na maternjem jeziku, sigurno je da nema tog programskog jezika u kome će
to moći da se uradi.
2.4.1 Primer 1 – opis rada klima uređaja
Uzmimo jedan jednostavan primer: algoritam za upravljanje radom klima uređaja.
Identifikujmo cilj algoritma: održavanje vrednosti temperature u radnom prostoru
(označimo je Trad).
Identifikujmo ulazni podatak: izmerena temperatura u radnom prostoru (označimo je sa
T izm).
Identifikujmo izlazni podatak: upravljanje grejačem klima uređaja (ili već nekim drugim
termoregulacionim elementom).
Definišimo algoritam u govornom jeziku:
1. zadaj (definiši) vrednost za Trad 2. izmeri temperaturu, to jest učitaj T izm 3. oduzmi ove dve vrednosti temperatura: ∆∆∆∆ = Trad – Tizm 4. da li je ∆∆∆∆ veće od nule ili jednako (≥≥≥≥) nuli ? 5. ako jeste, isključi grejač i vrati se na korak 2. 6. ako nije, uključi grejač i vrati se na korak 2.
Analizirajmo ovaj algoritam (koraci od 1. do 6.).
21
U koraku 1 se definiše vrednost promenljive Trad, a u koraku 2 se, postupkom merenja,
definiše vrednost promenljive T izm. I ovo je veoma važno zapamtiti: prilikom pisanja
programa, svakoj promenljivoj treba dodeliti određenu početnu vrednost, to morate uraditi
programer, inače neće dobiti željene (očekivane) rezultate.
U koraku 3 se oduzimaju dve vrednosti da bi se dobila razlika između željene i stvarne
temperature.
Korak 4 sadrži jedno odlučivanje: pitamo se kakav je rezultat prethodne aritmetičke
operacije (oduzimanja). Na osnovu ispitivanja vrednosti rezultata u koraku 4 sprovešćemo
odgovarajuće akcije – koraci 5 i 6.
Obratite pažnju da i u koraku 5 i u koraku 6 , da tako kažemo, vraćamo na korak 2.
Pošto je proces održavanja temperature radnog prostora kontinualan, to jest, treba da traje sve
dok je klima uređaj uključen, mi moramo stalno PONAVLJATI korake od 2 do 6.
Dakle, već i u ovom jednostavnom algoritmu imamo i sekvencijalne operacije, i
operacije odlučivanja i operacije ponavljanja. Znači, sada možemo reći da postoje TRI
osnovna tipa algoritama: SEKVENCIJALNI , SELEKTIVNI (odlučivanje) i
REPETITIVNI (ponavljanje). Kombinacijom ova tri tipa osnovnih algoritama je moguće
opisati (modelirati) bilo koji sistem, bez obzira na njegovu složenost.
Grafička predstava algoritma rada klima uređaja (pomoću programa Microsoft Visio –
Slika 2.4-1).
22
Slika 2.4-1. Blok dijagram rada klima uređaja
Komentar algoritma
Blok na Slika 2.4-2 služi za unos početnih vrednosti podataka (promenljivih) i odgovara
koraku 2 iz tekstualnog opisa algoritma.
Slika 2.4-2. Zadavanje početnih vrednosti
Blokovi na Slika 2.4-3, Slika 2.4-4 i Slika 2.4-5 predstavljaju simbol obrade podataka
(akcije, izvršenja, ...). Konkretno: merimo trenutnu temperaturu, oduzimamo trenutnu
izmerenu temperaturu od zadane i uključujemo ili isključujemo grejače.
23
Slika 2.4-3. Blok obrade
Slika 2.4-4. Blok obrade
Slika 2.4-5. Blokovi obrade
Slika 2.4-6 prikazuje blok odlučivanja (ili selekcije). Veoma je važno da razumete da se
u realnom sistemu izvršava SAMO JEDNA grana: ili DA ili NE. Dakle, ILI jedno ILI
drugo. Kaže se da se algoritam (a isto tako i program) GRANA na dva (a moguće je i više)
tokova.
Slika 2.4-6. Blok odlučivanja
Blokovi odlučivanja imaju svoju predstavu u svim programskim jezicima, i to najčešće
preko ključnih reči if i else. Ako je (if ) nešto zadovoljeno (ili, TAČNO) uradićemo jednu
akciju, a ako nije (else) zadovoljeno (ili, NETAČNO) uradićemo drugu akciju.
Grafička predstava algoritma pokazuje da je tok obrade standardno u smeru nadole,
osim u slučaju ponavljanja neke akcije (kaže se: ponavljanje dela radnji u algoritmu ili
ponavljanje dela koda u programu). U slučaju ponavljanja dela radnji u algoritmu, tok obrade
je u smeru nagore.
24
2.4.2 Primer 2 – Projektor (podešavanje)
Slika 2.4-7 predstavlja opis (algoritam) korišćenja nekog modela projektora, kada taj
projektor nije u funkciji (odnosno, ovo je uputstvo kako čuvati projektor kada nije u
eksploataciji). Sama slika predstavlja jedan algoritam (u vizuelnoj i tekstualnoj formi).
Slika 2.4-7. Podešavanje projektora
Opišimo korake:
1. zaokrenite (rotacijom) modul kamere toliko da sočivo bude napred, 2. gurnite modul kamere u nosač dok ne zabravite glavnu ručicu, 3. pomerajte levi i desni modul za osvetljenje, sve dok ne dodirnu podlogu, i 4. tokom skladištenja navucite začtitni poklopac na sočivo kamere.
Odmah se može uočiti da je algoritam SEVENCIJALAN , u smislu da po završetku
koraka 1 prelazimo u korak 2, po završetku koraka 2 u korak 3 i, konačno, po završetku
koraka 3 u korak 4. Verovatno možete uočiti i da u svakom koraku imamo i
ODLUČIVANJE i PONAVLJANJE .
Pročitajmo šta piše u opisu koraka 1: zaokreći (rotiraj) modul kamere tako da sočivo
kamere bude napred. Znači: PONAVLJAJ neku akciju (u ovom slučaju zaokretanje modula
kamere) SVE DOK NIJE ISPUNJEN NEKI USLOV (u ovom slučaju sve dok modul kamere
ne bude postavljen tako da sočivo stoji napred ).
Znači, veoma je važno razumeti da se algoritmi PONAVLJANJA uvek koriste u
kombinaciji sa algoritmima ODLUČIVANJA . Svaki algoritam ponavljanja MORA imati
USLOV IZLASKA (kaže se: uslov izlaska iz petlje). Zašto: pa da bi izbegli beskonačan rad
petlje, to jest, da bi izbegli situaciju da nikada ne izađemo iz petlje.
Algoritam, za početak, možemo predstaviti i ovako (Slika 2.4-8):
25
Slika 2.4-8. Blok dijagram održavanja kamere
Očigledno je da se na dijagramu vide samo moduli (podprogrami): modul možete
razumeti kao grupu akcija kojima se realizuje jedan korak algoritma (to se u programiranju
zove i podprogram, funkcija, procedura, blok, ...) ili grupu akcija (radnji) kojima se opisuje
(definiše) jedna složenija akcija. Na ovaj način blok dijagrami (i algoritmi, a i samo programi)
postaju neuporedivo razumljiviji (kaže se: čitljiviji).
Sada ćemo prikazati kako izgleda svaki modul pojedinačno.
26
Slika 2.4-9. Blok dijagram za modul 1
Slika 2.4-10. Blok dijagram za modul 2
Slika 2.4-11. Blok dijagram za modul 3
Slika 2.4-12. Blok dijagram za modul 4
27
Treba uočiti da smo u svim primerima prvo postavili pitanje da li je uslov (izlaska iz
petlje) zadovoljen pre izvršenja akcije – to se zove provera na vrhu ili na početku. Znači, u
takvom slučaju se može dogoditi i da se akcija i ne izvrši (ako je uslov već u startu
zadovoljen). Na Slika 2.4-9 do Slika 2.4-12 su primeri repetitivnih algoritama koji vam NE
garantuju da će se zahtevana akcija izvršiti makar jednom.
Bilo bi dobro i korisno da usvojimo dva termina: USLOV petlje i TELO petlje. Svaka
petlja se sastoji od uslova i od tela: u zavisnosti od uslova izvršava se, ili ne izvršava, telo
petlje. Recimo, na Slika 2.4-12 uslov je da li je, ili nije, postavljen zaštitni poklopac na sočivu
kamere. Telo petlje je akcija koju treba preduzeti: u našem primeru, akcija se preduzima ako i
samo ako, poklopac nije stavljen.
2.4.3 Primer 3 – određivanje MIN (MAX) člana nekog niza ...
Uzmimo jednostavan primer određivanja najmanjeg (ili, najvećeg) člana niza.
Ulaz (ili, ulazni podaci): postoji niz podataka (ovo niz shvatite kao: više podataka, ili
promenljivih, istog tipa), pri čemu nam je poznato koliko, u tom nizu, ima elemenata.
Akcija: pronaći najmanji (ili, najveći) član niza.
Izlaz: najmanji (ili najveći) član.
Izaberimo, za ovu demosntraciju, traženje najmanjeg člana.
U cilju lakšeg praćenja rešenja, usvojimo sledeću konvenciju za označavanje članova
niza: neka je ime niza, recimo, BROJEVI – onda će se pojedinačnim članovima niza
pristupati pomoću operatora: [i]. Po toj konvenciji, prvi član niza bi bio: BROJEVI[0]
(usvojimo, korisnu, naviku da sve brojimo od nule), drugi član niza bi bio: BROJEVI[1], treći
član niza BROJEVI[2], odnosno, član niza na poziciji i bi bio BROJEVI[i] .
Jedno, uobičajeno, rutinsko rešenje ovog problema glasi:
1. učitaj niz (u smislu, učitaj vrednosti svih elemenata niza),
a. kao što smo već naveli, ime niza će biti: BROJEVI,
2. učitaj broj članova niza,
a. ovu promenljivu ćemo označiti kao N
3. definiši jednu, pomoćnu, promenljivu, koju ćemo označiti kao MIN,
a. svrha ove promenljive: u njoj će se nalaziti vrednost najmanjeg člana niza na
kraju algoritma,
4. zadaj početnu vrednost promenljive MIN = prvi član niza (MIN= BROJEVI[0]),
28
a. PRAVILO: svaka promenljiva MORA imati definisanu POČETNU vrednost,
5. definiši jednu pomoćnu promenljivu, koju ćemo označiti kao BROJAČ,
a. svrha ove promenljive je tekući indeks u nizu (preciznije, da ukazuje na tekući
član niza),
6. zadaj početnu vrednost promenljive BROJAČ da bude jednaka 0 (nuli): BROJAČ=0,
a. PRAVILO: svaka promenljiva MORA imati definisanu POČETNU vrednost,
7. uvećaj vrednost promenljive BROJAČ za 1 (ta operacija se naziva inkrementiranje),
8. da li je vrednost promenljive BROJAČ jednaka vrednosti promenljive N ?
9. ako jeste, to znači da smo ispitali sve članove niza
a. proglasi vrednost promenljive MIN za najmanju vrednost u nizu,
b. KRAJ
10. ako nije, ispitaj da li je vrednost člana niza BROJEVI na poziciji BROJAČ manja od
vrednosti promenljive MIN ( BROJEVI[BROJAČ] < MIN )
a. ako nije, vrati se na korak 7.
b. ako jeste, izmeni vrednost promenljive MIN tako da bude jednaka vrednosti
člana niza na poziciji BROJAČ (MIN = BROJEVI[BROJAČ] ),
i. vrati se na korak 7.
Evo i blok dijagrama (urađenog u Microsoft Visio-u):
29
POČETAK
Učitaj: BROJEVI, N.Pomoćne promenljive:
MIN, BROJAČ
MIN=BROJEVI[0]BROJAČ=0
uvećaj BROJAČ za 1 (BROJAČ = BROJAČ + 1)
da li je BROJAČ = N ?
BROJEVI[BROJAČ] < MIN ?
MIN = BROJEVI[BROJAČ]
NE
DA
NE
DA
prikaži MIN (kao
najmanji)
KRAJ
Slika 2.4-13. Određivanje najmanjeg člana zadanog niza
3 POLJA
3.1 Uvod
Uvešćemo osnovnu strukturu podataka poznatu kao
linearno predstavljanje složenih struktura podataka.
Definišimo najpre polje (engl. array).
se može direktno pristupiti koriš
jednodimenzionalna i nazivamo ih vektorima, dvodimenzionalna polja ili matrice i
višedimenzionalna polja.
Svim elementima polja se može pristupiti koriš
indeksa u srednjim zagradama. Pristup elementima polja ostvaruje se pomo
odnosno lokacije elementa u okviru polja. Na
polja sa deset elemenata indeksiranih od 0 do 9 ( u programskom jeziku C/C++ prvi element
polja uvek ima indeks 0). Na primer, devetom elementu polja
se izrazom a[8].
Slika
Neka je α adresa prvog elementa vektora A=(a
početna vrednost indeksa (u daljem tekstu osnova),
indeksom i izračunava se po slede
U programskom jeziku C/C++ uvek važi da je
Neki programski jezici, na primer
deklarisanje polja, već na činjenicu da je neko polje pridruženo polju ukazuju uglaste zagrade
30
emo osnovnu strukturu podataka poznatu kao polje. Polje se č
linearno predstavljanje složenih struktura podataka.
Definišimo najpre polje (engl. array). Polje predstavlja skup elemenata iste vrste kojima
se može direktno pristupiti korišćenjem numeričkog indeksa. Po tipu polja mogu biti
jednodimenzionalna i nazivamo ih vektorima, dvodimenzionalna polja ili matrice i
a se može pristupiti korišćenjem imena polja i navo
indeksa u srednjim zagradama. Pristup elementima polja ostvaruje se pomo
odnosno lokacije elementa u okviru polja. Na Slika 3.1-1 je dat primer jednodimenzionalnog
polja sa deset elemenata indeksiranih od 0 do 9 ( u programskom jeziku C/C++ prvi element
polja uvek ima indeks 0). Na primer, devetom elementu polja a koji ima vrednost
Slika 3.1-1 Primer celobrojnog polja sa 10 elemenata.
prvog elementa vektora A=(aδ, aδ+1,...., an), σ veličin
vrednost indeksa (u daljem tekstu osnova), u tom slučaju se adresa elementa sa
unava se po sledećoj formuli:
adresa (a[i])= α+ σ(i− δ )
programskom jeziku C/C++ uvek važi da je δ =0, i tada dobijamo da je
adresa (a[i])= α+ σ i
Neki programski jezici, na primer programski jezik C/C++, nemaju
ć činjenicu da je neko polje pridruženo polju ukazuju uglaste zagrade
. Polje se često koristi za
predstavlja skup elemenata iste vrste kojima
Po tipu polja mogu biti
jednodimenzionalna i nazivamo ih vektorima, dvodimenzionalna polja ili matrice i
enjem imena polja i navođenjem
indeksa u srednjim zagradama. Pristup elementima polja ostvaruje se pomoću indeksa,
je dat primer jednodimenzionalnog
polja sa deset elemenata indeksiranih od 0 do 9 ( u programskom jeziku C/C++ prvi element
koji ima vrednost -3 pristupa
veličina elementa, a δ
adresa elementa sa
i tada dobijamo da je:
nemaju ključne reče za
injenicu da je neko polje pridruženo polju ukazuju uglaste zagrade
koje slede za imenom i broj elemenata polja u okviru tih zagrada. Broj u uglastim zagradama
pokazuje koliko ovako definisano
polje promenljive veličine moramo definisati pokaziva
operatorom alocirati potreban memorisjki prostor.
memoriju koja mora biti i dinami
Ukoliko se ovaj proces ne poštuje kod programskog jezika C/C++ javi
memorije’’ koje, ukoliko postane intenzivno, može stvoriti deficit u memorijskom prostoru i
ugroziti izvršavanje ne samo teku
3.2 Memorijska reprezentacija polja
Tipična memorijska reprezentacija jednodimenzionalnog polja prikazana je na
3.2-1. Elementi polja smešteni su u susedne memorijske lokacije,
svakom elementu polja može pristupiti za isto vreme. Ukupni memorijski prostor potreban za
predstavljanje polja od n elemenata tipa
- prostor potreban za smeštanje celobrojne vrednosti, a
smeštanje vrednosti promenljive tipa
3.2.1 Operacije
Programski jezik C/C++ omogu
traversal - obilazak polja, pristupa se svakom elementu polja i nad njim vrši neka
obrada (na primer, štampanje sadržaja polja, provera vredn
search - traži se element zadate vrednosti,
insertion - umetanje, dodaje se novi element polja na zadatu lokaciju,
deletion - iz polja se uklanja element zadate vrednosti ili sa zadate lokacije,
sorting - sortiranje, elementi polja se
(kod numeričkih polja to je obič
alfanumeričkih polja to je alfabetska ili leksikografska ure
31
koje slede za imenom i broj elemenata polja u okviru tih zagrada. Broj u uglastim zagradama
pokazuje koliko ovako definisano polje statički zauzima memorijski prostor.
čine moramo definisati pokazivač na odgovarajući tip podataka a zatim
operatorom alocirati potreban memorisjki prostor. Na ovaj način polju dinamič
biti i dinamički dealocirana, kada prestane potreba za tim poljem.
Ukoliko se ovaj proces ne poštuje kod programskog jezika C/C++ javić
memorije’’ koje, ukoliko postane intenzivno, može stvoriti deficit u memorijskom prostoru i
izvršavanje ne samo tekuće aplikacije, već i čitavog operativnog sistema.
Memorijska reprezentacija polja
na memorijska reprezentacija jednodimenzionalnog polja prikazana je na
. Elementi polja smešteni su u susedne memorijske lokacije, čime je obezbe
svakom elementu polja može pristupiti za isto vreme. Ukupni memorijski prostor potreban za
elemenata tipa type je sizeOf(int) + n*sizeOf(type), gde je
prostor potreban za smeštanje celobrojne vrednosti, a sizeOf(type) - prostor potreban za
smeštanje vrednosti promenljive tipa type.
Slika 3.2-1 Memorijska reprezentacija polja
Programski jezik C/C++ omogućava da se nad poljem mogu izvoditi sledeć
obilazak polja, pristupa se svakom elementu polja i nad njim vrši neka
obrada (na primer, štampanje sadržaja polja, provera vrednosti ili ažuriranje),
traži se element zadate vrednosti,
umetanje, dodaje se novi element polja na zadatu lokaciju,
iz polja se uklanja element zadate vrednosti ili sa zadate lokacije,
sortiranje, elementi polja se reorganizuju prema nekom kriterijumu ure
kih polja to je obično uređenje u rastući ili opadajući redosled vrednosti, kod
kih polja to je alfabetska ili leksikografska uređenost).
koje slede za imenom i broj elemenata polja u okviru tih zagrada. Broj u uglastim zagradama
ki zauzima memorijski prostor. Ukoliko imamo
ći tip podataka a zatim
in polju dinamički dodeljujemo
ki dealocirana, kada prestane potreba za tim poljem.
Ukoliko se ovaj proces ne poštuje kod programskog jezika C/C++ javiće se ’’curenje
memorije’’ koje, ukoliko postane intenzivno, može stvoriti deficit u memorijskom prostoru i
itavog operativnog sistema.
na memorijska reprezentacija jednodimenzionalnog polja prikazana je na Slika
čime je obezbeđeno da se
svakom elementu polja može pristupiti za isto vreme. Ukupni memorijski prostor potreban za
gde je sizeOf(int)
prostor potreban za
ad poljem mogu izvoditi sledeće operacije:
obilazak polja, pristupa se svakom elementu polja i nad njim vrši neka
iz polja se uklanja element zadate vrednosti ili sa zadate lokacije,
reorganizuju prema nekom kriterijumu uređenosti
ći redosled vrednosti, kod
32
Pretraživanje neuređenog vektora vrši se linearnim traženjem. Složenost takvog traženja
je '�� , gde je n broj elemenata vektora. Uređenjem elemenata po vrednosti u rastući ili
opadajući redosled može se značajno ubrzati pronalaženje elemenata korišćenjem binarnog
traženja. Primer implementacije binarnog traženja prikazan je u sledećem programskom
kodu. Funkcija binarySearch pronalazi poziciju elementa čija je vrednost te, u okviru polja
array, uređenog u rastući redosled, pri čemu se vrednost indeksa kreće u granicama od i do
i+n-1. Binarno traženje zasniva se na polovljenju intervala u kome se traži željeni element i
ima složenost '�(�)�� . Prvi korak je da zadatu vrednost tražimo u okviru celog niza (od
prvog do poslednjeg elementa) tako što izdvajamo srednji element tog niza i poredimo ga sa
traženom vrednošću (ako je broj elemenata niza paran, izdvajamo levi od dva srednja
elementa). U slučaju da je tražena vrednost jednaka srednjem elementu, pretraživanje je
okončano. Ako je tražena vrednost manja od vrednosti srednjeg elementa, onda se ona može
nalaziti samo u levoj polovini niza. U suprotnom, tražena vrednost se nalazi u desnoj polovini.
Ovakav postupak se ponavlja u onom delu niza koji se pretražuje. Algoritam binarnog
pretraživanja se prekida onog trenutka kada:
• srednji element i tražena vrednost se poklapaju, ili
• deo niza u okviru koga tražimo vrednost je prazan
public static int binarySearch(int[ ] array,int te, int i, int n) { // U vektoru array traži se elemenat te u opsegu in deksa od i do i+n-1
if(n == 0) throw new IllegalArgumentException ("vektor je praz an");
i f (n==l) {
if (array [i] == te)) return i;
throw new IllegalArgumentException ("elemenat nije nadjen"); { else {
int j = i + n/ 2; if (array [j] <= te)
return binarySearch (array, te, j, n - n/2); else
return binarySearch (array, te, i, n/2); }
}
3.3 Dinamička polja
Vrlo često u procesu izrade programa postoji potreba za promenom veli
Dinamička polja su polja koja mogu menjati veli
dodavanjem i brisanjem elemenata, ve
prostora. Na Slika 3.3-1 prikazana je memorijska reprezentacija dinami
jednodimenzionalnog polja A=(a
Slika 3.3-1 Memorijska reprezentacija dinami
Proces realokacije i prepisivanje svih elemenata u novi memorijski prostor
trenutno alocirani memorijski prostor popunjen elementima, a potrebno je dodati
element. S obzirom da realokacija zahteva zna
učestalost realokacije, zbog toga je
definisanu veličinu, a česte su i implementacije kod kojih se svakom realokacijom duplira
zauzeti memorijski prostor.
3.4 Višedimenzionalna polja
Višedimenzionalno polje dimenzije N je kolekcija podataka kojima se pris
indeksnih izraza (npr. A[i][j]). Memorijska reprezentacija je zapravo jednodimenzionalno
polje, a relativni pomeraj pojedinih elemenata u odnosu na po
osnovu indeksa. Neka je α
indeksima [i0, i1. ... iN-1] izračunava se
gde su faktori[k] unapred pripremljeni faktori da bi se smanjilo vreme izra
indeksa, a računaju se po formuli:
33
esto u procesu izrade programa postoji potreba za promenom veli
ka polja su polja koja mogu menjati veličinu tokom vremena, i to ne samo
dodavanjem i brisanjem elemenata, već promenom celokupnog alociranog memorijskog
prikazana je memorijska reprezentacija dinami
jednodimenzionalnog polja A=(a-1, a0,... a5).
Memorijska reprezentacija dinamičkog jednodimenzionalnog polja
Proces realokacije i prepisivanje svih elemenata u novi memorijski prostor
trenutno alocirani memorijski prostor popunjen elementima, a potrebno je dodati
S obzirom da realokacija zahteva značajno procesorsko vreme neophodno
zbog toga je novoformirano polje veće od prethodnog za unapred
česte su i implementacije kod kojih se svakom realokacijom duplira
Višedimenzionalna polja
lno polje dimenzije N je kolekcija podataka kojima se pris
snih izraza (npr. A[i][j]). Memorijska reprezentacija je zapravo jednodimenzionalno
polje, a relativni pomeraj pojedinih elemenata u odnosu na početak polja izra
početna adresa, a σ veličina elementa, adresa
čunava se koristeći sledeću formulu:
unapred pripremljeni faktori da bi se smanjilo vreme izra
se po formuli:
esto u procesu izrade programa postoji potreba za promenom veličine polja.
inu tokom vremena, i to ne samo
promenom celokupnog alociranog memorijskog
prikazana je memorijska reprezentacija dinamičkog
kog jednodimenzionalnog polja
Proces realokacije i prepisivanje svih elemenata u novi memorijski prostor vrši se kada je
trenutno alocirani memorijski prostor popunjen elementima, a potrebno je dodati novi
ajno procesorsko vreme neophodno je smanjiti
e od prethodnog za unapred
este su i implementacije kod kojih se svakom realokacijom duplira
lno polje dimenzije N je kolekcija podataka kojima se pristupa preko N
snih izraza (npr. A[i][j]). Memorijska reprezentacija je zapravo jednodimenzionalno
etak polja izračunava se na
elementa, adresa elementa sa
unapred pripremljeni faktori da bi se smanjilo vreme izračunavanja
Ovako zadatim formulama najbrže se menja poslednji indeks, a najsporije prvi. U
slučaju dvodimenzionalnih polja, ovakav raspored elemenata polja naziva se smeštanje po
vrstama. Na Slika 3.4-1
višedimenzionalnog polja.
Slika 3.4-1 Memorijska reprezentacija dinami
3.5 Matrice
Najčešće korišćena višedimenzionalna polja su dvodimenzionalna polja realnih brojeva
ili brojeva dvostruke tačnosti i ona se nazivaju
drugi kolona, tj. za element a[i]
koje su obe dimenzije jednake, npr. A
U protivnom naziva se pravougaona matrica
retko posednuta (engl. sparse matrix)
čije su vrednosti jednake nuli. Prostor koji zauzimaju takve matrice može zna
umanjen korišćenjem neke naprednije tehnike za smestanje nenultih elemenata. Matrica se
naziva gusta (engl. dense) ako sadži mnogo
standardni način za njihovo smeštanje.
Matrica se naziva gornja trougaona,
prikazana na Slika 3.5-2, ako svi elementi ispo
Kod donje trougaone matrice dimenzija nxn, maksimalni broj nenulti
je i. Ukupan broj nenultih elemenata tada nije ve
Isto važi i za gornju trougaonu matricu dimenzija nxn. Za veliko n, zna
uštedeti memorijski prostor ukoliko se ne pamte elementi polja
Slika 3.5-1 Gornje trougaona matrica
34
Ovako zadatim formulama najbrže se menja poslednji indeks, a najsporije prvi. U
aju dvodimenzionalnih polja, ovakav raspored elemenata polja naziva se smeštanje po
dat je primer memorijske reprezentacije dinami
Memorijska reprezentacija dinamičkog višedimenzionalnog polja.
ćena višedimenzionalna polja su dvodimenzionalna polja realnih brojeva
čnosti i ona se nazivaju matrice. Prvi indeks se obično naziva
a[i] [j] kažemo da se nalazi u i-toj vrsti i j-toj koloni. Matrica kod
koje su obe dimenzije jednake, npr. Anxn, naziva se kvadratna matrica (engl.
pravougaona matrica (engl. rectangular matrix). Matrica se naziva
sparse matrix) ukoliko sadrži mnogo (obično preko 80%) elemenata
ije su vrednosti jednake nuli. Prostor koji zauzimaju takve matrice može zna
enjem neke naprednije tehnike za smestanje nenultih elemenata. Matrica se
ako sadži mnogo (obično preko 80%) nenultih elemenata i koristi
in za njihovo smeštanje.
gornja trougaona, prikazana na Slika 3.5-1, ili donja trouga
, ako svi elementi ispod, ili iznad glavne dijagonale imaju vrednost 0.
Kod donje trougaone matrice dimenzija nxn, maksimalni broj nenultih elemenata u i
je i. Ukupan broj nenultih elemenata tada nije veći od:
Isto važi i za gornju trougaonu matricu dimenzija nxn. Za veliko n, znač
uštedeti memorijski prostor ukoliko se ne pamte elementi polja čije su vrednosti 0.
Gornje trougaona matrica
Slika 3.5-2 Donje trougaona matrica
Ovako zadatim formulama najbrže se menja poslednji indeks, a najsporije prvi. U
aju dvodimenzionalnih polja, ovakav raspored elemenata polja naziva se smeštanje po
dat je primer memorijske reprezentacije dinamičkog
kog višedimenzionalnog polja.
ena višedimenzionalna polja su dvodimenzionalna polja realnih brojeva
čno naziva vrsta, a
toj koloni. Matrica kod
(engl. square matrix).
Matrica se naziva
no preko 80%) elemenata
ije su vrednosti jednake nuli. Prostor koji zauzimaju takve matrice može značajno biti
enjem neke naprednije tehnike za smestanje nenultih elemenata. Matrica se
no preko 80%) nenultih elemenata i koristi
donja trougaona,
, ili iznad glavne dijagonale imaju vrednost 0.
h elemenata u i-toj vrsti
Isto važi i za gornju trougaonu matricu dimenzija nxn. Za veliko n, značajno se može
ije su vrednosti 0.
Donje trougaona matrica
35
Matrica je simetrična ako je �!* � �*!, i tada je dovoljno memorisati samo elemente
donje ili gornje trougaone matrice.
3.6 Primeri primene
U ovom odeljku biće prikazane neke od primena struktura podataka tipa polje.
3.6.1 Primer: Uređenje linearnih struktura podataka
Jedan od najčešćih zadataka prilikom generisanja izveštaja jeste uredenje podataka koji
se štampaju u rastući ili opadajući redosled. Za rešenje ovog problema potrebno
je odgovarajuće podatke (ili reference na njih) smestiti u vektor, a zatim urediti vektor po
postavljenom kriterijumu.
Sledeći programski kod prikazuje jedan od najjednostavnijih metoda za uređenje
vektora - metod mehurova (engl. bubble sort). U osnovi ovog metoda je formiranje prozora u
kome se posmatraju samo dva elementa a napredovanje u kretanju prozora je za jedan element,
zato se najpre upoređuju prvi i drugi element vektora (array), i ukoliko je prvi veći od drugog,
oni zamenjuju mesta. Zatim se upoređuju drugi i treći, pa treći i četvrti, i tako sve do para koga
čine pretposlednjeg i poslednjeg elementa vektora. Nakon prvog prolaska kroz vektor na
poslednjem mestu se nalazi najveći elemenat. U drugom prolazu ponovo se počinje sa
upoređivanjem prvog i drugog elementa vektora, ali se ide do pretposlednjeg, jer se za
poslednji već zna da je najveci. Drugi prolaz na pretposlednje mesto postavlja drugi po veličini
elemenat vektora. Svakim sledećim prolaskom kroz vektor smanjuje se broj ispitivanih
elemenata za 1 a algoritam se završava posle n-1 prolaza, gde je n broj elemenata vektora.
public static int bubbleSort(int[ ] array) { for (int i = n; i > 1; i--)
for(intj = 0; j < i-1; j++) if (array[1 ] > array[j+1]) {
int tmp = array[j]; array[j] = array[j+l]; array[j+l] = tmp;
} }
Ovaj algoritam uređenja vektora ima složenost '��� , jer je u prvom prolazu potrebno
izvršiti n-1 poređenje, u drugom n-2, i tako dalje sve do n-1 prolaza kada je potrebno
izvrsiti samo jedno poređenje. Ukupan broj poređenja je n(n-l)/2. Postoje mnogo efikasniji
algoritmi za uređenje, ali oni koriste pomoćne strukture, kao što su magacin i gomila.
3.6.2 Primer: Geometrijske transformacije
Vektori i matrice imaju široku primenu u rešavanju brojnih matemati
modeliranju scena u 3D računarskoj grafici, ali i u rešavanju nematemati
što je, na primer, uređenje numeri
Savremena primena računara ne može se zamisliti bez 3D grafike, a ona je zasnovana
na matematičkom modelu koji vrlo ekstenzivno koristi matri
svetu računarske grafike sastavljene su od objekata. Svaki objekat
svaki poligon određen je svojim temenima.
Da bi dati objekat pomerili u prostoru, moramo translirati svako od njegovih temena
Ukoliko teme predstavimo vektorom koordinata V = [v
pravougaone koordinate, pomeranje z
predstavm sledećim sistemom jedna
gde su +,- , +.- i +/- koordinate transliranog temena V.
Ukoliko transformaciju
dobijamo sledeću jednačinu:
Transformacijom translacije menja se samo položaj objekta u odnosu na koordinatni
početak.
Skaliranje (engl. scaling)
matricom. Ako transformaciju skaliranja predstavimo matricom S, n
na koje se primenjuje ova transformacija, dobijaju se slede
36
Primer: Geometrijske transformacije
Vektori i matrice imaju široku primenu u rešavanju brojnih matematič
čunarskoj grafici, ali i u rešavanju nematematičkih problema, kao
đenje numeričkih ili nenumeričkih podataka.
Savremena primena računara ne može se zamisliti bez 3D grafike, a ona je zasnovana
kom modelu koji vrlo ekstenzivno koristi matrični račun. Scene u virtuelnom
unarske grafike sastavljene su od objekata. Svaki objekat čini mnoštvo polig
en je svojim temenima.
Da bi dati objekat pomerili u prostoru, moramo translirati svako od njegovih temena
ko teme predstavimo vektorom koordinata V = [vx vy vz] gde su vx,v
nate, pomeranje za dx, dy i dz, po X, Y i Z-koordinati, respektivno
im sistemom jednačina:
koordinate transliranog temena V.
Ukoliko transformaciju translacije (engl. translation) predstavimo matricom T
Transformacijom translacije menja se samo položaj objekta u odnosu na koordinatni
scaling) u odnosu na koordinatni početak takođe se može predstaviti
matricom. Ako transformaciju skaliranja predstavimo matricom S, nove koordinate temena V,
na koje se primenjuje ova transformacija, dobijaju se sledećom formulom:
Vektori i matrice imaju široku primenu u rešavanju brojnih matematičkih problema,
čkih problema, kao
unara ne može se zamisliti bez 3D grafike, a ona je zasnovana
čun. Scene u virtuelnom
čini mnoštvo poligona a
Da bi dati objekat pomerili u prostoru, moramo translirati svako od njegovih temena.
vy i vz Dekartove
koordinati, respektivno mozemo
predstavimo matricom T
Transformacijom translacije menja se samo položaj objekta u odnosu na koordinatni
đe se može predstaviti
ove koordinate temena V,
gde su koeficijentima a, b i
respektivno. Transformacijom skaliranja deformiše se objekat. Izdužuje se i
nekoj osi.
Rotacija (engl. rotation)
koordinatama temena objekata. Rotacija, za proizvoljni ugao
(suprotnom od kretanja kazaljki na
polazi iz koordinatnog početka i prolazi kroz ta
Za slučaj rotacije oko X-ose za dato a, transformacija je zadata slede
Na sličan način se mogu definisati i rotacije oko ostale dve
dobijaju se kombinovanjem translacije, skaliranja i rotacije. Primena matri
značajno pojednostavljuje izrač
množenje matrica. Na primer, pomeranje objekta za 2
45° i na kraju skaliranje duž Z
temena V matricom M dobijenom slede
3.6.3 Primer: Rešavanje sistema linearnih jednačina
Jedan od načina za rešavanje
eliminacije. Kod ovog metoda, sistem
ili u matričnom obliku:
može se svesti na sledeći oblik:
37
gde su koeficijentima a, b i c predstavljeni faktori skaliranja po X, Y i Z
respektivno. Transformacijom skaliranja deformiše se objekat. Izdužuje se i
rotation) je treća osnovna geometrijska transformacija nad
koordinatama temena objekata. Rotacija, za proizvoljni ugao a u pozitivnom smeru
(suprotnom od kretanja kazaljki na časovniku), može biti zadata oko proizv
četka i prolazi kroz tačku zadatu vektorom položaja W = [w
ose za dato a, transformacija je zadata sledećom jednač
in se mogu definisati i rotacije oko ostale dve ose. Složene transformacije
dobijaju se kombinovanjem translacije, skaliranja i rotacije. Primena matri
ajno pojednostavljuje izračunavanje složenih transformacija svođenjem na kumulativno
množenje matrica. Na primer, pomeranje objekta za 2 duž Y-ose, zatim rotacija oko X
45° i na kraju skaliranje duž Z-ose za koeficijent 3, može se ostvariti množenjem vektora
temena V matricom M dobijenom sledećom formulom:
Primer: Rešavanje sistema linearnih jednačina
čina za rešavanje sistema linearnih jednačina jeste metod
Kod ovog metoda, sistem n linearnih jednačina sa n nepoznatih:
može se svesti na sledeći oblik:
predstavljeni faktori skaliranja po X, Y i Z-osi,
respektivno. Transformacijom skaliranja deformiše se objekat. Izdužuje se ili sakuplja po
a osnovna geometrijska transformacija nad
u pozitivnom smeru
asovniku), može biti zadata oko proizvoljne ose koja
ku zadatu vektorom položaja W = [wx wy wz].
ćom jednačinom:
ose. Složene transformacije
dobijaju se kombinovanjem translacije, skaliranja i rotacije. Primena matričnog računa
đenjem na kumulativno
ose, zatim rotacija oko X-ose za
ose za koeficijent 3, može se ostvariti množenjem vektora
ina jeste metod Gausove
ili u vektorskom obliku:
gde je R gornja trougaona matrica. Rešenja
sledećih formula:
Gausova eliminacija zasniva se na uklanjanju nekih
izračunavanjem faktora mij kojim se množi j
primer, za eliminaciju koeficijenata
sledećoj formuli:
Da bi deljenje bilo moguć
zadovoljen menja se redosled jedna
i-te jednačine, dobija se:
U sledećoj iteraciji računa se
Ukoliko je a22 = 0, na poziciju druge jedna
za koju važi: ai2 = 0. Množenjem druge jedna
(� � 3) eliminišu se faktori a
sledeće formule:
38
ili u vektorskom obliku:
gde je R gornja trougaona matrica. Rešenja ovakvog sistema dobijaju se primenom
Gausova eliminacija zasniva se na uklanjanju nekih članova iz jedna
kojim se množi j-ta jednačina i oduzima od i-te jedna
eliminaciju koeficijenata ai1 (i = 2,...,n) potrebno je izračunati faktore
Da bi deljenje bilo moguće, neophodno je da važi � 1 0. Ukoliko ovaj uslov nije
zadovoljen menja se redosled jednačina. Množenjem prve jednačine sa mi1 i
čuna se mi2 po formuli:
0, na poziciju druge jednačine u sistemu treba postaviti i
= 0. Množenjem druge jednačine sa mi2 i oduzimanjem o
) eliminišu se faktori ai2x2. U k-toj iteraciji za izračunavanje koeficijenata koriste se
ovakvog sistema dobijaju se primenom
članova iz jednačina,
te jednačine. Na
čunati faktore mi1 po
. Ukoliko ovaj uslov nije
oduzimanjem od
ine u sistemu treba postaviti i-tu jednačinu,
i oduzimanjem od i-te jednačine
unavanje koeficijenata koriste se
Zamenom redosleda jednač
39
Zamenom redosleda jednačina treba obezbediti ispunjenje uslova �33�3 1
1 0, za svako k.
40
4 LANČANE LISTE
4.1 Uvod
Uz polja, lančane liste predstavljaju osnovnu strukturu za izgradnju svih složenijih
struktura podataka. U ovom poglavlju prikazane su jednostruko ulančane liste, dvostruko
ulančane liste i liste sa preskokom, njihova memorijska reprezentacija i osnovne operacije sa
njima.
Lista je konačni niz (od nula ili više) podataka istog tipa. Podaci koji čine listu nazivaju
se njeni elementi. U teoretskim razmatranjima listu obično zapisujemo kao:
(a1, a2, . . . ,an).
Ovdje je n≥0 tzv. dužina liste. Ako je n = 0, kažemo da je lista prazna. Za n≥1, a1 je prvi
element, a2 drugi, . . ., an zadnji element. Moguće je da su neki od elemenata liste jednaki;
identitet elementa određen je njegovom pozicijom (rednim brojem) a ne njegovom
vrednošću.
Važno svojstvo liste je da su njeni elementi linearno uređeni s obzirom na svoju
poziciju. Kažemo da je ai ispred ai+1, i da je ai iza ai−1.
Broj elemenata u listi nije fiksiran: elementi se mogu ubacivati ili izbacivati na bilo
kojem mestu
- na taj način lista može rasti ili se smanjivati. Primetimo da lista nije isto što i polje.
U nastavku navodimo nekoliko primera za liste.
- Reč u nekom tekstu je lista znakova. Npr. reč ZGRADA se može interpretirati kao (Z,
G, R, A, D, A). Primetimo da dva različita elementa imaju istu vrednost. Slično, red u tekstu
je lista znakova (uključujući i beline). Celi tekst je lista redova.
- Polinom u matematici beležimo na sledeći način:
P(x) = a1xe1 + a2xe2 + . . . + anxen,
gdje je 0 ≤ e1 < e2 < .. .< en. Zapravo se radi o listi oblika :
((a1, e1), (a2, e2), . . . , (an, en)).
41
- U nekim programskim jezicima lista je osnovni objekt od kojeg se grade svi ostali.
Primer: LISP (List Processing).
- Kao rezultat pretraživanja baze podataka obično se dobiva lista zapisa. Npr. postavimo
upit: ispisati prezimena i imena ljudi koji su rodeni između 1956. i 1980. godine a po
zanimanju su programeri, sortirano po abecedi. Rezultat je oblika:
(Babić Zoran, Kostić Vojkan, Mitrović Nevenka, Vučinić Zoran. . .).
Da bi matematički pojam liste pretvorili u apstraktni tip podataka, treba da definiemo
operacije koje se obavljaju na listama. To se može učiniti na razne načine. Naš a.t.p. je samo
jedna od mogućih varijanti.
Lančane liste su linearne strukture kod kojih svaki element ukazuje na svoje susede u
okviru te strukture. Lančana lista je linearna kolekcija čvorova, gde je linearna uređenost
ostvarena preko pokazivača.
Svaki čvor lančane liste ima jedno info polje, koje sadrži sam element podataka ili
informaciju o elementu, i jedno ili više link polja, koja sadrže pokazivače na susedne čvorove,
ili imaju null vrednost (na primer, kod poslednjeg čvora u listi).
Slika 4.1-1 Struktura čvora lančane liste: a) čvor jednostruko ulančane liste, b) čvor dvostruko ulančane
liste
Ako čvor liste sadrži samo jedan pokazivač, lančana lista je jednostruko ulančana
(engl. singly linked list) ili jednosmerna, a ako sadrži dva pokazivača, tada je lančana lista
dvostruko ulančana (engl. doubly linked list) ili dvosmerna.
Nadalje, koristiće se akronimi SLL (Singly Linked list) za jednostruko ulančanu listu i
DLL (Doubly Linked List) za dvostruko ulančanu listu.
Dakle, lančana lista je lista elemenata koji su proizvoljno raspoređeni u memoriji i koji
su međusobno povezani linkom, tj. smeštanjem adrese svakog elementa (osim prvog) u njegovog
prethodnika.
42
Slika 4.1-2 Povezana lista
Lančane liste imaju primenu u problemima koji koriste kolekcije podataka čiji broj
elemenata nije unapred poznat, ili varira u širokom opsegu.
4.2 Memorijska reprezentacija jednostruko ulančane liste
Prilikom definisanja lančane liste najčešće podrazumevamo jednostruko ulančanu listu
kod koje svaki čvor ukazuje samo na jedan, sledeći čvor u okviru date linearne strukture.
Prvom čvoru pristupa se preko posebnog pokazivača, a svim ostalim čvorovima praćenjem
pokazivača ugrađenih u same čvorove, odnosno linearnim traženjem.
Nizovi su u memoriji predstavljeni korišćenjem sekvencijalnog mapiranja, tako da su
elementi: niza podjednako udaljeni jedan od drugog. Međutim, ovakav pristup ima sledeće
nedostatke:
• Umetanje novog ili brisanje postojećeg elementa iz niza je vremenski veoma
skupa operacija, jer zahteva pomeranje određenog broja postojećih elemenata.
• U slučaju korišćenja statičkih nizova neophodno je poznavanje maksimalnog
broja elemenata još u trenutku pisanja programa. Pored ovog nedostatka, dodatni
problem je i to što bez obzira na stvaran broj elemenata koji će biti smešten u
niz, program uvek alocira maksimalnu veličinu niza, što dovodi do bespotrebnog
trošenja memorije.
• Korišćenje dinamičkih nizova rešava problem poznavanja maksimalnog broja
elemenata u trenutku pisanja programa, ali uvodi i neke nove probleme. Svaka
promena veličine niza zahteva dodatnu alokaciju i dealokaciju memorije, kao i
kopiranje sadržaja elemenata u novi memorijski prostor, što drastično pogoršava
performanse programa,
Da bi se prevazišli navedeni problemi uvodi se koncept povezanih elemenata. U
ovakvom pristupu nije neophodno da elementi budu međusobno na podjednakom rastojanju.
Umesto toga elemente možemo smestiti bilo gde u memoriji, a zatim ih povezati tako da svaki
element (osim prvog) bude povezan sa prethodnim elementom u listi. To se može postići tako što
se u svaki element upiše i adresa njegovog sledbenika, što zahteva da svaki element bude u
mogućnosti da pored svojih podataka čuva i adresu sledećeg elementa. Zbog toga svaki
43
element mora biti struktura koja sadrži dva dela: jedan koji čuva neophodne podatke
(nazovimo ga podatak ili data field) i drugi koji čuva adresu sledbenika (veza ili link).
Za realizaciju koncepta povezanih lista u programskom jeziku C koriste se slogovi
(strukture) i pokazivači (pointeri). Element liste koja će sadržati celobrojne podatke se
definiše na sleded način:
struct element { int podatak; struct element *sledeci; };
Prethodne linije koda definišu struktumi tip element koji će predstavljati element liste.
Svaki element liste sadrži celobrojni podatak i pokazivač na sleded element liste. Podatak
unutar liste može biti i bilo kog drugog prostog ili složenog tipa.
Osnovna varijanta jednostruko ulančane liste (slika) sadrži samo jedan dodatni
pokazivač na početak liste, koji se naziva glava (engl. head) liste. Kod ovakve strukture,
dodavanje na početak liste je vrlo jednostavno i brzo, ali dodavanje na kraj zahteva prolazak
kroz celu lančanu listu, što može biti vrlo zahtevna operacija, pogotovu ako lista sadrži više
stotina ili hiljada čvorova.
Ukoliko je potrebno obezbediti efikasno dodavanje i na kraj liste, jednostruko ulančanoj
listi se dodaje još jedan pokazivač koji se naziva rep (engl. tail) liste, kao što je prikazano na
slici.
Glava i/ili rep jednostruko ulančane liste imaju vrednosti null ako je lista prazna.
Cirkularne liste su varijante lančanih listi kod kojih poslednji čvor ukazuje na početak
liste. Kod ovakvih struktura čitava lista se može obići polaskom iz bilo kog čvora, a obilazak
se završava kada se ponovo stigne do polaznog čvora.
44
Kružne liste se u praksi mogu primeniti na strukture podataka koje su po prirodi kružne. Jedan
od tipičnih primera korišćenja kružne liste je deljenje procesorskog vremena razlidtim
korisnicima od strane operativnog sistema. Kako bi se obezbedila ravnopravnost svih korisnika, oni
su raspoređeni u krug i redom im se dodeljuje deo slobodnog vremena procesora. Operativni sitem
uzima jednog korisnika, dodeljuje mu mali deo procesorskog vremena i prelazi na sledećeg
korisnika. Korisnici koji nemaju više zahteva za procesorskim vremenom isključuju se iz liste. Ovaj
proces se ponavlja sve do trenutka dok više ne postoje korisnici koji zahtevaju procesorsko
vreme.
Lančane liste sa zaglavljem su lančane liste koje kao prvi čvor imaju zaglavlje (engl.
header), koji se od ostalih čvorova razlikuje po tome što u info polju ima specijalnu vrednost
koja nije validan podatak ili oznaku koja ga identifikuje kao čvor zaglavlja. Lančane liste sa
zaglavljem mogu biti necirkularne ili cirkularne (slika)
Na sledećoj slici je prikazan izgled praznih jednostruko ulančanih listi sa zaglavljem.
Čvor zaglavlja se može koristiti za smeštanje sistemskih informacija o strukturi
podataka, kao što su: broj čvorova, datum kreiranja, i slično.
4.2.1 Manipulisanje sa listama
Elementi liste se lagano ubacuju i izbacuju na bilo kojem delu liste. S druge strane nešto
je teže pročitati i-ti element: potrebno je redom čitati prvi, drugi, . . ., i-ti element. Takođe je
teže odrediti kraj liste ili prethodni element. Listu poistovećujemo s pointerom na header.
Dodavanje elementa u listu. Za manipulaciju listom potrebno je da nam njen prvi
element (ukoliko postoji) uvek bude poznat. Kada znamo prvi element, korišćenjem
pokazivača na njegovog sledbenika lako dolazimo do sledećeg elementa u listi. Pošto lista
može biti i prazna, umesto da pamtimo prvi element liste, koristimo pokazivač na prvi
element, glavu liste. Dakle, glava liste je pokazivač na prvi element liste, a u slučaju da je
lista prazna vrednost ovog pokazivača je NULL Veoma je bitno u svakom trenutku imati
informaciju o glavi liste, jer je samo tako moguće pristupiti listi. Iz tog razloga prilikom
45
pisanja programa treba voditi računa da uvek postoji bar jedan pokazivač na početak liste, koji
se neće koristiti u druge svrhe, čime bi se došlo u opasnost da se izgubi informacija o početku
liste.
Prilikom dodavanja novog elementa u listu moramo razlikovati dva slučaja:
• Lista je bila prazna pre dodavanja novog elementa
• Lista nije bila prazna pre dodavanja novog elementa
Pre dodavanja elementa u praznu listu, glava liste je pokazivač koji ima vrednost NULL
(ne pokazuje ni na jedan element). Nakon dodavanja novog elementa, glava liste postaje
pokazivač na taj element. U drugom slučaju lista nije prazna i glava pokazuje na prvi element.
Da bi se dodao element na kraj liste, potrebno je proći kroz sve elemente liste kako bi se
pronašao poslednji element, a zatim iza njega dodao novi element. Dodavanjem novog
elementa na kraj liste očigledno ne dolazi do promene glave liste. Imajući u vidu navedene
postupke dodavanja novog elementa, jasno je da se algoritmi u ova dva slučaja drastično
razlikuju, pa ih iz tog razloga i u programu treba razdvojiti.
Slika 4.2-1 Dodavanje elementa u listu
Prolazak kroz listu. U radu sa listama je često potrebno kretati se kroz listu, od
elementa do elementa. Najčešće je u pitanju obrada podataka u listi, pretraga liste kako bi se
našao odgovarajući element ili traženje kraja liste. U svim ovim slučajevima algoritam je
sličan. Uvodi se pomoćni pokazivač koji je inicijalno jednak glavi liste, odnosno pokazuje na
prvi element liste ukoliko ona nije prazna. Nakon provere da li pokazivač pokazuje na neki
element (ima vrednost različitu od NULL) vrši se obrada podatka u tom element (štampa,
upoređivanje, račun...). Po završetku obrade podatka, pomoćni pokazivač dobija vrednost
pokazivača na sledeći element, a čitav postupak se ponavlja sve dok pomoćni pokazivač ima
nenultu vrednost, tj. dok pokazuje na neki element. Kada pomoćni pokazivač dobije vrednost
NULL, to znači da smo došli do kraja liste.
Brisanje elementa iz liste. Da bismo obrisali određeni element iz liste potrebno je da
znamo njegovu poziciju u listi. Jedan od načina je da navedemo njegov redni broj, uz
pretpostavku da su elementi numerisani redom od 1 do n. Kada znamo redni broj elementa,
krećemo se kroz listu kako bismo pronašli pokazivač na traženi element. Pored toga, potrebno je
da znamo i pokazivač na prethodni element u listi, kako bismo njegovom linku dodelili
pokazivač na element koji sledi elementu koji brišemo. Nakon toga možemo da obrišemo
traženi element, odnosno da oslobodimo memoriju koju on zauzima.
Umetanje novog elementa iza odre
element na određeno mesto u listi, neophodno je da znamo redni broj elementa u
novi element biti umetnut. Pretpostavljamo da su svi elementi liste numerisani rednim
brojevima od 1 do n. Kada znamo broj elementa, kre
pokazivač na element sa zadatim rednim brojem. Zatim kreiramo novi element, a nje
linku dodeljujemo pokazivač na element koji sledi iza elementa sa navedenim rednim brojem.
Nakon toga, elementu sa zadatim rednim brojem postavljamo link tako da pokazuje novi
element.
Slika 4.2-3
Okretanje redosleda u listi
za svaki element znamo pokaziva
pokazivači poznati, onda mož
prethodnika. Nakon toga trenutni element progla
sledbenika za trenutni.
Deo koda koji bi obavljao navedenu proceduru mogao bi da izgleda ovako:
prethodni = NULL;
46
č na prethodni element u listi, kako bismo njegovom linku dodelili
na element koji sledi elementu koji brišemo. Nakon toga možemo da obrišemo
traženi element, odnosno da oslobodimo memoriju koju on zauzima.
Slika 4.2-2 Brisanje elementa iz liste
Umetanje novog elementa iza određenog elementa u listi. Da bismo umetnuli novi
eno mesto u listi, neophodno je da znamo redni broj elementa u
novi element biti umetnut. Pretpostavljamo da su svi elementi liste numerisani rednim
Kada znamo broj elementa, krećemo se kroz listu kako bismo dobili
element sa zadatim rednim brojem. Zatim kreiramo novi element, a nje
na element koji sledi iza elementa sa navedenim rednim brojem.
zadatim rednim brojem postavljamo link tako da pokazuje novi
3 Umetanje novog elementa iza određenog elementa u list
Okretanje redosleda u listi. Da bismo izvršili okretanje redosleda u listi neophodno je da
za svaki element znamo pokazivače na njegovog prethodnika i sledbenika. Kada su nam ovi
žemo link trenutnog elementa da postavimo tako da pokazuje na
prethodnika. Nakon toga trenutni element proglašavamo za prethodnika, a njegovog
Slika 4.2-4Okretanje redosleda u listi
Deo koda koji bi obavljao navedenu proceduru mogao bi da izgleda ovako:
na prethodni element u listi, kako bismo njegovom linku dodelili
na element koji sledi elementu koji brišemo. Nakon toga možemo da obrišemo
Da bismo umetnuli novi
eno mesto u listi, neophodno je da znamo redni broj elementa u listi iza koga će
novi element biti umetnut. Pretpostavljamo da su svi elementi liste numerisani rednim
emo se kroz listu kako bismo dobili
element sa zadatim rednim brojem. Zatim kreiramo novi element, a njegovom
na element koji sledi iza elementa sa navedenim rednim brojem.
zadatim rednim brojem postavljamo link tako da pokazuje novi
sti
ili okretanje redosleda u listi neophodno je da
njegovog prethodnika i sledbenika. Kada su nam ovi
emo link trenutnog elementa da postavimo tako da pokazuje na
avamo za prethodnika, a njegovog
Deo koda koji bi obavljao navedenu proceduru mogao bi da izgleda ovako:
while (trenutni != NULL){ sledeci = trenutni -trenutni- >sledeci = prethodni;prethodni = trenutni;trenutni = sledeci;
}
Sortiranje liste. Da bismo
element sa najmanjom vredno
dodajemo ga na kraj druge liste, koja je inicijalno bila
dok početna lista ne postane prazna. Na kraju ostaje samo da funkcija vrati pokaziva
u koju su prebačeni svi elementi.
Umetanje novog elementa u sortiranu listu
je prethodno sortirana, upoređujemo redom podatke u listi sa
Ovaj proces se ponavlja sve dok ne dobijemo pokaziva
elementa čiji je podatak veći od podatka u novom elem
4.3 Dvostruko ulančane liste
Radeći sa jednostruko povezanim listama mogli smo uo
Jednostruko povezane liste omogu
Brisanje elementa iz liste zahteva stalno
listu, kako bi se znao prethodnik elementa koji je potrebno obrisati.
47
while (trenutni != NULL)
- >sledeci; >sledeci = prethodni;
prethodni = trenutni; trenutni = sledeci;
Da bismo sortirali listu, prvo prolazimo kroz nju kako bismo prona
element sa najmanjom vrednošću podatka. Nakon toga uklanjamo taj element iz liste i
dodajemo ga na kraj druge liste, koja je inicijalno bila prazna. Ovaj proces ponavljamo sve
e postane prazna. Na kraju ostaje samo da funkcija vrati pokaziva
eni svi elementi.
Slika 4.2-5 Sortiranje liste
Umetanje novog elementa u sortiranu listu. Da bismo umetnuli novi element u listu koja
ujemo redom podatke u listi sa vrednošću podatka novog elementa.
Ovaj proces se ponavlja sve dok ne dobijemo pokazivač na element koji se nalazi ispred
i od podatka u novom elementu.
Slika 4.2-6 Umetanje elementa u sortiranu listu
Dvostruko ulančane liste
i sa jednostruko povezanim listama mogli smo uočiti sledeće probleme:
Jednostruko povezane liste omogućavaju kretanje kroz listu samo u jednom pravcu.
Brisanje elementa iz liste zahteva stalno čuvanje prethodnog elementa tokom kretanja kroz
kako bi se znao prethodnik elementa koji je potrebno obrisati.
sortirali listu, prvo prolazimo kroz nju kako bismo pronašli
u podatka. Nakon toga uklanjamo taj element iz liste i
prazna. Ovaj proces ponavljamo sve
e postane prazna. Na kraju ostaje samo da funkcija vrati pokazivač na listu
element u listu koja
u podatka novog elementa.
koji se nalazi ispred
e probleme:
kroz listu samo u jednom pravcu.
uvanje prethodnog elementa tokom kretanja kroz
48
Ukoliko dođe do gubljenja veze u nekom elementu, ostali elementi postaju nedostupni.
Ovi problemi kod jednostruko povezanih lista mogu biti prevaziđeni uvođenjem
pokazivača na prethodnika u svakom elementu. Kada svaki element liste sadrži pokazivač na
svog sledbenika i prethodnika, takvu listu nazivamo dvostruko povezana lista.
Ovim je omogućen obilazak liste i unapred i unazad, kao i olakšano brisanje elemenata
liste bez potrebe za pamćenjem pokazivača na prethodni elemenat.
Dvostruko ulančane liste takođe mogu biti cirkularne, ukoliko prvi čvor ukazuje na
poslednji u listi i obrnuto .
Dvostruko ulančane liste mogu imati i zaglavlje,
Slika 4.3-1 Dvostruko ulančane liste: a)samo sa pokazivačem na početak, b) sa pokazivačima na početak i kraj, c) ciklična dvostruko ulančana lista, d) lista sa zaglavljem i e) ciklična dvostruko ulančana lista sa zaglavljem
Umetanje elementa iza određenog elementa u dvostruko povezanoj listi. Da bismo
umetnuli novi element na određeno mesto u dvostruko povezanoj listi, neophodno je da znamo
redni broj elementa u listi iza koga će novi element biti umetnut. Pretpostavljamo da su svi
elementi liste numerisani rednim brojevima od 1 do n. Kada znamo broj elementa, krećemo se
kroz listu kako bismo dobili pokazivač na element sa zadatim rednim brojem. Zatim kreiramo
49
novi element, a njegovom levom i desnom linku dodeljujemo pokazivače na element sa
navedenim rednim brojem i njegovog desnog suseda. Nakon toga, levom i desnom elementu
novog elementa postavljamo desnu i levu vezu tako da pokazuju na novi element.
Slika 4.3-2 Umetanje elementa iza određenog elementa u dvostruko povezanoj listi
Brisanje elementa iz dvostruko povezane liste. Da bismo obrisali određeni element iz
dvostruko povezane liste potrebno je da znamo njegovu poziciju u listi. Jedan od načina je da
navedemo njegov redni broj, uz pretpostavku da su elementi numerisani redom od 1 do n.
Kada znamo redni broj elementa, krećemo se kroz listu kako bismo pronašli pokazivač na traženi
element. Nakon toga možemo da obrišemo traženi element, odnosno da oslobodimo memoriju
koju on zauzima. Za razliku od brisanja elementa iz jednostruko povezane liste, u ovom slučaju
nije potrebno da znamo i pokazivač na prethodni element u listi, s obzirom da u dvostruko
povezanoj listi svaki element ima pokazivač na svog levog i desnog suseda.
Slika 4.3-3 Šematski prikaz brisanja elementa iz dvostruko povezane liste
4.4 Liste sa preskokom
Osnovni nedostatak lančanih listi jeste neophodnost njihovog sekvencijalnog obilaska
pri traženju elementa. Lista sa preskokom (engl. skip list) ubrzava obilazak uvodenjem
dodatnih (paralelnih) listi.
U listi sa preskokom sa n čvorova, za svako k i i , čvor na poziciji i 2k - 1 ukazuje na
čvor na poziciji (i+1)· 2k - 1. Naime, svaki drugi čvor ukazuje na čvor za dve pozicije ispred
njega, svaki četvrti za četiri pozicije ispred itd.
50
Od ukupnog broja čvorova u listi sa preskokom, 1/2 njih ima samo jedno polje za
referenciranje, 1/4 ima dva polja, 1/8 ima tri polja, itd. Broj polja za referenciranje određuje
nivo čvora.
U programskim jezicima koji ne podržavaju dinamičke strukture, npr. asemblerski jezik,
ili kada je unapred poznat maksimalni broj elemenata liste, lančane liste se mogu predstaviti
korišćenjem polja.
Kod ovakve reprezentacije link polje ne sadrži fizičku adresu susednog elementa, već
njegov indeks u okviru zadatog statičkog polja. Susedni elementi ne moraju imati sukcesivne
vrednosti indeksa, zato je neophodno pratiti link polje prilikom obilaska liste. Svi slobodni
elementi takođe su ulančani i na njih ukazuje lrmp (pokazivač na početak liste raspoloživog
memorijskog prostora).
Slika 4.4-1Statička reprezentacija jednostruko ulančane liste: a) lista predstavljena poljem, b) dinamički
ekvivalent
4.4.1 Primeri primene
Primer: Lan čana reprezentacija polinoma
Polinom jedne promenljive x stepena n je algebarski izraz oblika:
Obzirom da programski jezici opšte namene nemaju ugrađene tipove ili funkcije za rad
sa polinomima, oni se najčešće implementiraju korišćenjem polja ili lančanih listi.
51
Slika 4.4-2 Primer memorijske reprezentacije polinoma 150x5-27x2+7x+5 korišćenjem jednostruko ulančane liste
Ako polinom ima više promenljivih, info polje treba proširititako da mogu biti predstavljeni stepeni svih promenljivih. Na
Slika 4.4-3 dat je primer predstavljanja polinoma sa dve promenljive.
Slika 4.4-3 Primer memorijske reprezentacijepolinoma 7x4y+3x2y2+7y2+2 korišćenjem jednostruko ulančane liste
Primer: Lan čana reprezentacija teksta
Obrada teksta je jedna od najčešćih primena računara danas.
Za predstavljanje linije teksta, u programima za obradu teksta, često se koriste
dvostruko ulančane liste.
Svaki čvor te liste sadrži dva info polja, od kojih prvo ukazuje na samu reč, a drugo
sadrži dužinu te reči u slovima.
Na slici je prikazana lančana reprezentacija jedne linije teksta. Umesto pokazivača na
reči, u čvorovima se mogu pamtiti same reči, ali se time gubi fiksna dužina čvorova liste.
Slika 4.4-4 Primer lančane reprezentacije teksta
52
Primer: Lan čana reprezentacija retko posednute matrice
Retko posednute matrice imaju mnogo nultih elemenata.
Memorijski prostor namenjen smeštanju takvih matrica može se značajno smanjiti
ukoliko se memorišu samo nenulti elementi. Jedan od načina za memorisanje je korišćenje
lančanih listi kod kojih svaki čvor ima strukturu prikazanu na slici, gde i predstavlja indeks
vrste, j indeks kolone, M ij vrednost elementa na poziciji (i, j), link k pokazivač na sledeći
nenulti element date kolone, a link v pokazivač na sledeći nenulti element date vrste.
Slika 4.4-5 Primer implementacije retko posednutih matrica: a) retko posednuta matrica, b) njena memorijska reprezentacija korišćenjem jednostruko ulančanih listi
53
5 MAGACIN, RED I DVOSTRANI RED
5.1 Uvod
Magacin i red su među najprostijim i najčešće korišćenim strukturama podataka. Koriste
se u različitim aplikacijama, uključujući i neke složene strukture podataka. To su strukture
podataka koje su vrlo često implementirane u hardveru centralnih procesora računara, a
takođe su uključene u mnoge standardne programske biblioteke. Veliki broj realnih problema
zahteva korišćenje struktura podataka kao što su stekovi i redovi. Tipičan primer korišćenja
stekova je stek koji programski jezik koristi da bi implementirao pozivanje funkcija i povratak
iz njih. Sa druge strane, jedna od najčešćih primena redova je red za upravljanje redosledom
procesa koje je potrebno izvršiti. Obe ove strukture podataka su u formi liste, tako da je za
njihovu implementaciju moguće iskoristiti nizove ili povezane liste.
5.2 Magacin
Magacin (engl. stack) je linearna struktura podataka kod koje se može pristupiti samo
poslednje dodatom podatku. To je struktura podataka koja radi po principu "poslednji upisan, prvi
pročitan" (eng. last-in, first-out — LIFO).
Linearna lista je struktura podataka koju čini uređeni skup elemenata, pri čemu broj
elemenata liste može varirati. Linearnu listu A od n elemenata obeležićemo na sledeći način:
A= [a1, a2, ..., an]
Ako je n=0, tada se za listu kaže da je prazna ili null lista. Element liste se može brisati
sa bilo koje pozicije u linearnoj listi i može se dodavati na bilo koju poziciju. U toku svog
života lista može da raste ili da se smanjuje.
Magacin je specijalan slučaj linearne liste kod koje se operacije dodavanja i brisanja
vrše samo na jednom kraju, koji se naziva vrh (engl. top) magacina. Operacija dodavanja
elemanta na stek se najčešće naziva Push (gurnuti), dok se operacija skidanja elementa sa
steka naziva Pop (skinuti).
Za grafičku reprezentaciju magacina koristi se jedan od načina prikazan na Slika 5.2-1.
Obzirom da se na vrhu magacina nalazi element koji je poslednji dodat u magacin, on se
prvi i uklanja, pa zato kažemo da magacin radi po principu LIFO (last
Na drugi način, magacin
na drugom kraju dodaju kuglice koje predstavljaju elemente (
kuglica iz cevi uvek moramo prvo izvaditi onu kuglic
redom. Kuglica koja je prva uba
magacini se često u srpskom jeziku nazivaju i
Slika 5.2-
5.2.1 Implementacija steka pomo
Kada se za implementacjju
elemenata iz magacina se realizuju kori
implementacije pomoću niza je nemogu
elemenata u magacinu.
Za implementaciju magacina
da se u nju smesti makslmalan
magacinu. Pored toga, u svakom trenutku je neophodno znati broj elemenata
indeks elementa na vrhu magacina
dodavanja elementa u magacin
upisuje novi element. Suprotno, prilikom skidanja elementa
vrha magacina.
54
Slika 5.2-1 Grafički prikaz magacina
Obzirom da se na vrhu magacina nalazi element koji je poslednji dodat u magacin, on se
žemo da magacin radi po principu LIFO (last-in-first-
in, magacin možemo zamisliti kao cev zatvorenu na jednom kraju u koju se
na drugom kraju dodaju kuglice koje predstavljaju elemente (Slika 5.2-2). Prilikom va
kuglica iz cevi uvek moramo prvo izvaditi onu kuglicu koja je poslednja ubač
redom. Kuglica koja je prva ubačena u cev biće poslednja izvađena. Zahvaljujud ovoj osobini,
esto u srpskom jeziku nazivaju i stogovi.
-2 Šematski prikaz dodavanja i skidanja demenata sa steka
Implementacija steka pomoću niza
Kada se za implementacjju magacina koristi niz, operacije dodavanja i skidanja
se realizuju korišćenjem osnovnih operacija nad nizom. Ograni
u niza je nemogućnost proširenja i skračenja niza u zavisnosti od broja
magacina koristi se niz konstante veličine, koja mora biti dovoljna
da se u nju smesti makslmalan broj elemenata koji se u jednom trenutku mo
. Pored toga, u svakom trenutku je neophodno znati broj elemenata
magacina. Indeks -1 označava da je magacin prazan. Prilikom
u magacin, povećava se indeks vrha magacina i na tu poziciju u nizu
upisuje novi element. Suprotno, prilikom skidanja elementa iz magacina umanjuje se indeks
Obzirom da se na vrhu magacina nalazi element koji je poslednji dodat u magacin, on se
-out).
jednom kraju u koju se
). Prilikom vađenja
čena u cev i tako
ena. Zahvaljujud ovoj osobini,
ematski prikaz dodavanja i skidanja demenata sa steka
koristi niz, operacije dodavanja i skidanja
enjem osnovnih operacija nad nizom. Ograničenje
enja niza u zavisnosti od broja
ine, koja mora biti dovoljna
jednom trenutku može naći u
. Pored toga, u svakom trenutku je neophodno znati broj elemenata u magacinu ili
prazan. Prilikom
i na tu poziciju u nizu
umanjuje se indeks
5.2.2 Implementacija steka pomo
Magacin se može veoma efikasno implementirati kori
bi se novi element dodavao uvek na po
magacina skidao bi se uvek prvi element u listi, odnosno onaj koji je poslednji dodat.
Na početku, lista je prazna, pa je i pokaziva
Funkcija push uzima pokaziva
dodati kao drugi parametar, kreira
uzima pokazivač na početak liste kao prvi parametar i pokaziva
smestiti vrednost skinutog elementa kao drugi parametar. Nakon toga, funkcija vra
prvog elementa u listi i pomera pokaziva
element koji je bio na početku liste.
Na Slika 5.2-3 prikazan je postupak dodavanja elemenata u magacin i brisanja
elemenata iz magacina. Inicijalno (slika a), magacin sadr
element. Operacijom push(5)
elementa sada je 5 (slika b). Nakon toga, dodaje se još jedan element (slika
push(1), a zatim čitaju sukcesivno dva elementa iz magacina (slike
magacin ponovo dovodi u poč
pokaživača, tako da uvek ukazuje na vrh magacina.
Slika 5.2
Na Slika 5.2-4 prikazan je izgled steka predstavljenog povezanom listom prilikom
dodavanja i skidanja elemenata slede
Push(7), Pop().
55
Implementacija steka pomoću liste
e veoma efikasno implementirati korišćenjem povezanih lista tako
se novi element dodavao uvek na početak liste. Takođe, u slučaju skidanja elementa
skidao bi se uvek prvi element u listi, odnosno onaj koji je poslednji dodat.
etku, lista je prazna, pa je i pokazivač na početak liste (top)
uzima pokazivač na postojeću listu kao prvi parametar i vrednost koju treba
dodati kao drugi parametar, kreira novi element i dodaje ga na početak liste. Funkcija
etak liste kao prvi parametar i pokazivač na promenljivu u koju
smestiti vrednost skinutog elementa kao drugi parametar. Nakon toga, funkcija vra
prvog elementa u listi i pomera pokazivač top na sledeći element u listi. Na kraju se uni
etku liste.
prikazan je postupak dodavanja elemenata u magacin i brisanja
elemenata iz magacina. Inicijalno (slika a), magacin sadrži tri elementa, pri č
push(5) dodaje se novi element na vrh magacina i vrednost vršnog
). Nakon toga, dodaje se još jedan element (slika
itaju sukcesivno dva elementa iz magacina (slike d i e), nak
magacin ponovo dovodi u početno stanje. Svakom od operacija ažurira se vrednost
a, tako da uvek ukazuje na vrh magacina.
5.2-3Primer dodavanja i brisanje elemenata iz magacina
prikazan je izgled steka predstavljenog povezanom listom prilikom
dodavanja i skidanja elemenata sledećim redosledom: Push(5), Push(8), Pop(), Push(2),
enjem povezanih lista tako što
aju skidanja elementa iz
skidao bi se uvek prvi element u listi, odnosno onaj koji je poslednji dodat.
(top) jednak NULL
u listu kao prvi parametar i vrednost koju treba
etak liste. Funkcija pop
na promenljivu u koju će
smestiti vrednost skinutog elementa kao drugi parametar. Nakon toga, funkcija vraća vrednost
i element u listi. Na kraju se uništava
prikazan je postupak dodavanja elemenata u magacin i brisanja
ži tri elementa, pri čemu je 6 vršni
dodaje se novi element na vrh magacina i vrednost vršnog
). Nakon toga, dodaje se još jedan element (slika c), operacijom
), nakon čega se
etno stanje. Svakom od operacija ažurira se vrednost top
prikazan je izgled steka predstavljenog povezanom listom prilikom
sh(8), Pop(), Push(2),
Slika 5.2-4 Šematski prikaz dodavanja i skidanja elemenata sa steka predstavljenog povezanom listom
Osnovne operacije
Postoji pet osnovnih operacija za rad sa strukturom tipa magacin, i to
push - dodaje element na vrh magacina,
pop - čita i uklanjanja element sa vrha magacina,
getTop - čita element sa vrha magacina, ali ga ne uklanjanja,
isEmpty - proverava da li je magacin prazan i
numberOfElements - vrać
Operacije push i pop menjaju ukupan broj elemenata sme
dodavanja i brisanja elementa moraju ažurirati i pokaziva
dodaje element (operacija push) u pun magacin, javlja se greška tipa
i emituje se izuzetak SBPException("Stack overflow!
(operacije pop i getTop) javlja se greška tipa
SBPException("Stack underflow!").
5.3 Memorijska reprezentacija
Magacin se može implementirati stati
(Slika 5.3-1a), ili dinamički, koriš
56
ematski prikaz dodavanja i skidanja elemenata sa steka predstavljenog povezanom listom
Postoji pet osnovnih operacija za rad sa strukturom tipa magacin, i to su:
dodaje element na vrh magacina,
ita i uklanjanja element sa vrha magacina,
ita element sa vrha magacina, ali ga ne uklanjanja,
proverava da li je magacin prazan i
vraća broj elemenata smeštenih u magacinu.
Operacije push i pop menjaju ukupan broj elemenata smeštenih u magacinu, pa osim
dodavanja i brisanja elementa moraju ažurirati i pokazivač na vrh magacina. Ukoliko se
dodaje element (operacija push) u pun magacin, javlja se greška tipa prekorač
k SBPException("Stack overflow!"). Prilikom čitanja iz praznog magacina
(operacije pop i getTop) javlja se greška tipa potkoračenja magacina i emituje se izuzetak
SBPException("Stack underflow!").
Memorijska reprezentacija
že implementirati statički, korišćenjem jednodimenzionalnog polja
čki, korišćenjem lančanih listi (Slika 5.3-1b).
ematski prikaz dodavanja i skidanja elemenata sa steka predstavljenog povezanom listom
su:
štenih u magacinu, pa osim
na vrh magacina. Ukoliko se
prekoračenje magacina
itanja iz praznog magacina
i emituje se izuzetak
enjem jednodimenzionalnog polja
Slika 5.3-1 Memorijska reprezentacija magacina: a) stati
Zbog ogrančenog memorijskog prostora kod stati
problema koji zahtevaju dva magacina,
ali tako da vrhovi magacina bu
magacina mogla nesmetano da rastu bez potrebe za pomeranjem dna.
Slika 5.3-2 Statička implementacija više magacina koji dele zajedni
Ukoliko je neophodno smestiti v
unapred proceniti memorijski prostor postreban svakom od magacina za rast i na
odgovarajućim pozicijama postaviti njihova dna (
Kada se dogodi da i-ti magacin popuni dodeljeni prostor, tra
koji još nije popunio njemu dodeljeni prostor, neka je to magacin j, i svi m
i+l-og do j-tog se pomeraju, tako da se poklope vrh prethodnog i dno narednog. Ako se ne
nadje slobodan prostor sa desne strane, kre
nepopunjeni, npr. m-ti, svi magacini, po
Da bi se smanjila učestalost pomeranja magacina neophodno je modifikovati prethodni
algoritam i voditi računa o veli
realokacije prostora pomeraju se svi magacini, tako da se
raspoređuje svima (bez obzira da li je neki magacin popunjen ili ne), proporcionalno porastu
odgovarajućeg magacina u periodu izme
5.4 Primeri primene
Magacin se koristi u re
operativnim sistemima i aplikaci
neke primene magacina.
57
Memorijska reprezentacija magacina: a) statička b) dinamič
enog memorijskog prostora kod statičke reprezentacije, u rešavanju
problema koji zahtevaju dva magacina, često se koristi zajednički memorijski prostor (polje),
ali tako da vrhovi magacina budu okrenuti jedan prema drugom (Slika 5.3-
magacina mogla nesmetano da rastu bez potrebe za pomeranjem dna.
čka implementacija više magacina koji dele zajednički memorijski prostor: a) dva magacina, b) proizvoljan broj magacina
Ukoliko je neophodno smestiti više magacina u okviru jednog polja, potrebno je
unapred proceniti memorijski prostor postreban svakom od magacina za rast i na
im pozicijama postaviti njihova dna (Slika 5.3-2b).
ti magacin popuni dodeljeni prostor, traži se udesno prvi magacin
koji još nije popunio njemu dodeljeni prostor, neka je to magacin j, i svi magacini, po
tog se pomeraju, tako da se poklope vrh prethodnog i dno narednog. Ako se ne
nadje slobodan prostor sa desne strane, kreće se ulevo od i-tog magacina, i kada se nadje prvi
ti, svi magacini, počev od m+l-og do i-tog se pomeraju ulevo.
čestalost pomeranja magacina neophodno je modifikovati prethodni
čuna o veličini i porastu svakog od njih. U tom sluč
realokacije prostora pomeraju se svi magacini, tako da se ukupni slobodni memorijski prostor
uje svima (bez obzira da li je neki magacin popunjen ili ne), proporcionalno porastu
eg magacina u periodu između dve realokacije.
Magacin se koristi u rešavanju velikog broja problema. Koristi se u kompilatorima,
operativnim sistemima i aplikacionim programima. U ovom odeljku biće ukratko prikazane
ka b) dinamička
reprezentacije, u rešavanju
ki memorijski prostor (polje),
-2a), kako bi oba
ki memorijski prostor: a) dva
še magacina u okviru jednog polja, potrebno je
unapred proceniti memorijski prostor postreban svakom od magacina za rast i na
ži se udesno prvi magacin
agacini, počev od
tog se pomeraju, tako da se poklope vrh prethodnog i dno narednog. Ako se ne
tog magacina, i kada se nadje prvi
tog se pomeraju ulevo.
estalost pomeranja magacina neophodno je modifikovati prethodni
ini i porastu svakog od njih. U tom slučaju prilikom
ukupni slobodni memorijski prostor
uje svima (bez obzira da li je neki magacin popunjen ili ne), proporcionalno porastu
Koristi se u kompilatorima,
će ukratko prikazane
5.4.1 Primer: Uparivanje zagrada
Jedan od zadataka kompilatora jeste provera sintaksne ispravnosti programskog koda
koji je unet, a jedno od pravila je da svaka otvorena zagrada mora imati odgovaraju
zatvorenu zagradu. Primenom magacina ovo pravilo se lako može proveriti. Uneti niz
znakova "skenira se" sleva udesno i kada se nai
magacin. Nailaskom na zatvorenu zagradu, proverava se da li na vrhu magacina postoji
otvorena zagrada i ako postoji uklanja se iz magacina. Trenutni broj otvorenih zagrada u
magacinu ukazuje na dubinu ugnježdavanja. Ukoliko izraz nije regularan može se javiti jedan
od sledeća dva slučaja:
• prilikom nailaska na zatvorenu zagradu magacin je prazan, što ukazuje na
nedostatak otvorenih zagrada ili višak zatvorenih zagrada i
• nakog završetka obrade celog niza znakova magacin se nije ispraznio, što
ukazuje na višak otvorenih zagrada ili nedostatak zatvorenih zagrada.
Slika 5.4-1 ilustruje operacije nad magacinom i stanja magacina prilikom provere
uparenosti zagrada u algebarsk
Slika 5.4-1 Sekvenca operacija nad magacinom pri proveri uparenosti zagrada u algebarskom izrazu: a + ( b
Prethodni postupak se mo
bio korektan, pri nailasku na krajnji delimiter, na vrhu magacina mora biti po
istog tipa. U programskom jeziku C++ koriste se slede
srednje zagrade '[' i']', velike zagrade '{' i'}' i del
5.4.2 Primer: Prevođenje aritmetičkih izraza iz inflx u postfix notaciju
Jedna od primena magacina je i prevo
jezicima visokog nivoa. Prilikom pisanja programskog koda uobi
operatori navode između operanada (tzv.
ova notacija nije pogodna pa je neophodno izraz prevesti u oblik kod koga operator prethodi
operandima (tzv. prefix notacija) ili sledi iza operanada (tzv.
58
Primer: Uparivanje zagrada
Jedan od zadataka kompilatora jeste provera sintaksne ispravnosti programskog koda
unet, a jedno od pravila je da svaka otvorena zagrada mora imati odgovaraju
zatvorenu zagradu. Primenom magacina ovo pravilo se lako može proveriti. Uneti niz
znakova "skenira se" sleva udesno i kada se naiđe na otvorenu zagradu ona se smešta u
Nailaskom na zatvorenu zagradu, proverava se da li na vrhu magacina postoji
otvorena zagrada i ako postoji uklanja se iz magacina. Trenutni broj otvorenih zagrada u
magacinu ukazuje na dubinu ugnježdavanja. Ukoliko izraz nije regularan može se javiti jedan
prilikom nailaska na zatvorenu zagradu magacin je prazan, što ukazuje na
nedostatak otvorenih zagrada ili višak zatvorenih zagrada i
nakog završetka obrade celog niza znakova magacin se nije ispraznio, što
k otvorenih zagrada ili nedostatak zatvorenih zagrada.
ilustruje operacije nad magacinom i stanja magacina prilikom provere
uparenosti zagrada u algebarskom izrazu:
Sekvenca operacija nad magacinom pri proveri uparenosti zagrada u algebarskom izrazu: a + ( b * c ) - ( d + e - ( c + g ) * ( b * c ) )
Prethodni postupak se može primeniti na sve uparene delimitere, pri čem
bio korektan, pri nailasku na krajnji delimiter, na vrhu magacina mora biti poč
istog tipa. U programskom jeziku C++ koriste se sledeći delimiteri: male zagrade '(' i ')',
srednje zagrade '[' i']', velike zagrade '{' i'}' i delimiteri komentara '/*' i '*/'.
Primer: Prevođenje aritmetičkih izraza iz inflx u postfix notaciju
Jedna od primena magacina je i prevođenje zapisa aritmetičkih izraza u programskim
jezicima visokog nivoa. Prilikom pisanja programskog koda uobičajena praks
đu operanada (tzv. infix notacija). Sa stanovišta izvršenja u ra
ova notacija nije pogodna pa je neophodno izraz prevesti u oblik kod koga operator prethodi
notacija) ili sledi iza operanada (tzv. postfix notacija). Na primer,
Jedan od zadataka kompilatora jeste provera sintaksne ispravnosti programskog koda
unet, a jedno od pravila je da svaka otvorena zagrada mora imati odgovarajuću
zatvorenu zagradu. Primenom magacina ovo pravilo se lako može proveriti. Uneti niz
e na otvorenu zagradu ona se smešta u
Nailaskom na zatvorenu zagradu, proverava se da li na vrhu magacina postoji
otvorena zagrada i ako postoji uklanja se iz magacina. Trenutni broj otvorenih zagrada u
magacinu ukazuje na dubinu ugnježdavanja. Ukoliko izraz nije regularan može se javiti jedan
prilikom nailaska na zatvorenu zagradu magacin je prazan, što ukazuje na
nakog završetka obrade celog niza znakova magacin se nije ispraznio, što
k otvorenih zagrada ili nedostatak zatvorenih zagrada.
ilustruje operacije nad magacinom i stanja magacina prilikom provere
Sekvenca operacija nad magacinom pri proveri uparenosti zagrada u algebarskom izrazu:
že primeniti na sve uparene delimitere, pri čemu, da bi izraz
bio korektan, pri nailasku na krajnji delimiter, na vrhu magacina mora biti početni delimiter
i delimiteri: male zagrade '(' i ')',
kih izraza u programskim
čajena praksa je da se
notacija). Sa stanovišta izvršenja u računaru
ova notacija nije pogodna pa je neophodno izraz prevesti u oblik kod koga operator prethodi
notacija). Na primer,
izraz koji u infix notaciji ima oblik:
prefix notaciji u izraz oblika: * f +
izvršenja operacija i operande nad kojima se izvršavaju operacije. Zbog toga su mnogo
jednostavniji od infix notacije i ne sadrže zagrade za odre
zavise od prioriteta operacija.
Sledi primer za prevođenje
se "skenira" sleva udesno i pri tome se primenjuju pet osnovnih pravila:
1. Ako je "skenirani" simbol '('
2. Ako je "skenirani" simbol ')', iz magacina se
sa simbolom '('. Svi pro
3. Ako je "skenirani" simbol neki operator, proverava se da li na vrhu magacina
postoji operator koji je istog ili vi
se uklanja iz magacina i smešta u izlazni izraz, a teku
magacin. Ukoliko je teku
magacina, tekući operator se smesta u magacin.
4. Ako je "skenirani" simbol neki operand, direktno se upisuj
5. Kada se dođe do kraja ulaznog niza, iz magacina se
izlazni niz.
Slika 5.4-2 Primer prevcđenja izraza: ( ( a + b ) * c/d + e t f )/gu postfix notaciju
Na Slika 5.4-2 prikazan je primer prevo
u postfix notaciju korišćenjem magacina. Prevo
Prilikom prevođenja korišć
najvišeg nivoa, množenje i deljenje (operatori '*' i '/')
(operatori '+' i '-') najnižeg prioriteta.
59
izraz koji u infix notaciji ima oblik: a + b * f, u postfix notaciji transformiše se u:
prefix notaciji u izraz oblika: * f + a b. Izrazi u prefix i postfix notaciji tačno definišu redosled
izvršenja operacija i operande nad kojima se izvršavaju operacije. Zbog toga su mnogo
jednostavniji od infix notacije i ne sadrže zagrade za određivanje redosleda operacija, niti
đenje zapisa iz infix u postfix notaciju primenom magacina. Izraz
se "skenira" sleva udesno i pri tome se primenjuju pet osnovnih pravila:
Ako je "skenirani" simbol '(', on se dodaje u magacin.
Ako je "skenirani" simbol ')', iz magacina se čitaju i uklanjaju simboli zaklju
sa simbolom '('. Svi pročitani simboli, osim '(', upisuju se u izlazni izraz.
Ako je "skenirani" simbol neki operator, proverava se da li na vrhu magacina
postoji operator koji je istog ili višeg prioriteta od tekućeg. Ukoliko postoji, on
se uklanja iz magacina i smešta u izlazni izraz, a tekući operator smešta u
magacin. Ukoliko je tekući operator višeg prioriteta od operatora na vrhu
ći operator se smesta u magacin.
Ako je "skenirani" simbol neki operand, direktno se upisuje u izlazni izraz.
đe do kraja ulaznog niza, iz magacina se čitaju svi simboli i upisuju u
đenja izraza: ( ( a + b ) * c/d + e t f )/gu postfix notaciju kori
prikazan je primer prevođenja izraza:
šćenjem magacina. Prevođenjem se dobija sledeći izraz:
đenja korišćen je sledeći prioritet operatora: stepenovanje (operator '
najvišeg nivoa, množenje i deljenje (operatori '*' i '/') srednjeg, a sabiranje i oduzimanje
') najnižeg prioriteta.
+ b * f, u postfix notaciji transformiše se u: a b f * +, a u
definišu redosled
izvršenja operacija i operande nad kojima se izvršavaju operacije. Zbog toga su mnogo
ivanje redosleda operacija, niti
zapisa iz infix u postfix notaciju primenom magacina. Izraz
simboli zaključno
itani simboli, osim '(', upisuju se u izlazni izraz.
Ako je "skenirani" simbol neki operator, proverava se da li na vrhu magacina
ćeg. Ukoliko postoji, on
ći operator smešta u
i operator višeg prioriteta od operatora na vrhu
e u izlazni izraz.
itaju svi simboli i upisuju u
korišćenjem magacina
enjem se dobija sledeći izraz:
i prioritet operatora: stepenovanje (operator '4')
srednjeg, a sabiranje i oduzimanje
5.4.3 Primer: Sabiranje vrlo velikih celih broje
Magacin se može efikasno koristiti i prilikom sabiranja vrlo velikih celih brojeva.
Obzirom da programski jezici imaju ograni
sledeća operacija:
se ne može izvesti. Jedan od nač
dva za smeštanje operanada i jedan za smeštanje rezultata. Operandi se smeštaju (cifra po
cifra) u odgovarajuće magacine, po
operanada uzimaju vršni elementi (cifre najmanje težine) i sabiraju. Ukoliko je rezultat
jednocifreni, on se direktno smešta u magacin rezultata, a ukoliko je dvocifreni, niža cifra
(cifra jedinica) se smešta u magacin rezultata, a viša (cifra dec
prenosa i sabira sa ciframa operanada u slede
magacina operanada prazna. Ukoliko su brojevi razli
bez cifara, cifre iz drugog se prepisuju u mag
Rezultat sabiranja smešten je u magacinu rezultata sa cifrom najve
magacina. Na Slika 5.4-3 dat j
prethodno izloženog algoritma.
Slika 5.4-3
5.5 Red
Red (engl. queue) je linearna struktura poda
dodatom podatku, odnosno red radi po principu ’’prvi upisan, prvi pro
FIFO)
Redovi (engleski queue)
kraju liste, koji se naziva kraj reda,
početak reda. To praktično zna
60
Primer: Sabiranje vrlo velikih celih brojeva
že efikasno koristiti i prilikom sabiranja vrlo velikih celih brojeva.
Obzirom da programski jezici imaju ograničenja u predstavljanju brojeva celobrojnog tipa,
234 524 876 023 227 + 1 243 808 276
že izvesti. Jedan od načina da se prevaziđu ograničenja jeste korišćenje tri magacina,
dva za smeštanje operanada i jedan za smeštanje rezultata. Operandi se smeštaju (cifra po
će magacine, počinjući od cifre najveće težine. Zatim se iz
operanada uzimaju vršni elementi (cifre najmanje težine) i sabiraju. Ukoliko je rezultat
jednocifreni, on se direktno smešta u magacin rezultata, a ukoliko je dvocifreni, niža cifra
(cifra jedinica) se smešta u magacin rezultata, a viša (cifra decetica) se pamti kao cifra
prenosa i sabira sa ciframa operanada u sledećoj iteraciji. Postupak se završava kada su oba
magacina operanada prazna. Ukoliko su brojevi različitih dužina i jedan od magacina ostane
bez cifara, cifre iz drugog se prepisuju u magacin rezultata uz sabiranje sa cifrom prenosa.
Rezultat sabiranja smešten je u magacinu rezultata sa cifrom najveće težine na vrhu tog
dat je primer sabiranja dva cela broja 2785 i 578, koriš
prethodno izloženog algoritma.
Primer sabiranja brojeva 2785 i 578 korišćenjem magacina
je linearna struktura podataka koja omogućuje pristup samo najranije
dodatom podatku, odnosno red radi po principu ’’prvi upisan, prvi pročitan’’ (engl first
queue) su liste elemenata u kojima se elementi dodaju na jednom
kraj reda, a oduzimaju se na drugom kraju liste, koji se naziva
no znači da se elementi sa reda uklanjaju istim redosledom kao
že efikasno koristiti i prilikom sabiranja vrlo velikih celih brojeva.
enja u predstavljanju brojeva celobrojnog tipa,
ćenje tri magacina,
dva za smeštanje operanada i jedan za smeštanje rezultata. Operandi se smeštaju (cifra po
e težine. Zatim se iz magacina
operanada uzimaju vršni elementi (cifre najmanje težine) i sabiraju. Ukoliko je rezultat
jednocifreni, on se direktno smešta u magacin rezultata, a ukoliko je dvocifreni, niža cifra
etica) se pamti kao cifra
oj iteraciji. Postupak se završava kada su oba
itih dužina i jedan od magacina ostane
acin rezultata uz sabiranje sa cifrom prenosa.
će težine na vrhu tog
e primer sabiranja dva cela broja 2785 i 578, korišćenjem
enjem magacina
ćuje pristup samo najranije
itan’’ (engl first-in, first-out –
su liste elemenata u kojima se elementi dodaju na jednom
a oduzimaju se na drugom kraju liste, koji se naziva
i da se elementi sa reda uklanjaju istim redosledom kao što
su i dodavani na red. Iz tog razloga se ova struktura podataka
skraćenica od engleskih reči First In First Out (Prvi unutra prvi napolje). Operacija dodavanja
elemanta u red se najčešće naziva
naziva Delete (obrisati).
Za grafičku reprezentaciju reda koristi se jedan od na
Red možemo zamisliti kao cev otvorenu na oba kraja u koju se na jednom kraju ubacuju
kuglice koje predstavljaju elemente (
prvo vadi kuglica koja je prva uba
u cev biće poslednja izvađena. Upravo ovoj osobini redo
na čekanje u redu gde se prvo uslu
Slika 5.5-
S obzirom da su stekovi u osnovi
ili povezanih lista.
61
su i dodavani na red. Iz tog razloga se ova struktura podataka često naziva i FIFO,
i First In First Out (Prvi unutra prvi napolje). Operacija dodavanja
e naziva Insert (ubaciti), dok se operacija brisanja elementa iz reda
ku reprezentaciju reda koristi se jedan od načina prikazanih na
Slika 5.5-1 Grafička reprezentacija reda
emo zamisliti kao cev otvorenu na oba kraja u koju se na jednom kraju ubacuju
kuglice koje predstavljaju elemente (Slika 5.5-2). Prilikom vađenja kuglica iz cevi uvek se
prvo vadi kuglica koja je prva ubačena u cev i tako redom. Kuglica koja je poslednja uba
ena. Upravo ovoj osobini redovi duguju svoj naziv, jer podse
u redu gde se prvo uslužuju oni koji su prvi stigli.
-2 Šematski prikaz ubacivanja i brisanja elemenata iz reda
S obzirom da su stekovi u osnovi liste, oni se mogu implementirati kori
esto naziva i FIFO, što je
i First In First Out (Prvi unutra prvi napolje). Operacija dodavanja
brisanja elementa iz reda
ina prikazanih na Slika 5.5-1.
emo zamisliti kao cev otvorenu na oba kraja u koju se na jednom kraju ubacuju
enja kuglica iz cevi uvek se
ena u cev i tako redom. Kuglica koja je poslednja ubačena
vi duguju svoj naziv, jer podsećaju
ematski prikaz ubacivanja i brisanja elemenata iz reda
liste, oni se mogu implementirati korišćenjem nizova
62
5.5.1 Implementacija reda pomoću niza
Kada se za implementaciju reda koristi niz, operacije dodavanja i brisanja elemenata iz
reda se realizuju korišćenjem osnovnih operacija nad nizom. Ograničenje implementacije
pomoću niza je nemogućnost proširenja i skraćenja niza u zavisnosti od broja elemenata u
redu.
Za implementaciju reda kortsti se niz konstante veličine, koja mora biti dovoljna da se u
nju smesti ukupan broj elemenata koji se dodaju u red, bez obzira na to koliko je njih obrisano
iz reda. Pored toga, u svakom trenutku je neophodno znati indekse prvog i poslednjeg
elementa u redu. Indeksi -1 označavaju da je red prazan. Prilikom dodavanja elementa u red,
povećava se indeks poslednjeg elementa i na tu poziciju u redu upisuje se novi element. U
slučaju brisanja elementa iz reda, povećava se indeks prvog elementa u redu.
Moguća je i drugačija implementacija koja bi zahtevala samo onoliku veličinu niza
koliko je potrebno da se smeste elementi koji su u jednom trenutku u redu, međutim takva
realizacija zahteva stalno pomeranje preostalih elemenata prilikom brisanja prvog elementa iz
reda.
5.5.2 Implementacija reda pomoću liste
Red se može veoma efikasno implementirati korišćenjem povezanih lista tako što bi se
novi element dodavao uvek na kraj liste. Takođe, u slučaju brisanja elementa iz reda skidao bi
se uvek prvi element u listi, odnosno onaj koji je prvi dodat.
Na početku, lista je prazna, pa su i pokazivači na početak i kraj liste (front i rear)
jednaki NULL Funkcija insert kreira novi element i dodaje ga na kraj liste. Funkcija delete
vraća vrednost prvog elementa u listi i pomera pokazivač frontm sledeći element u listi. Na
kraju se uništava element koji je bio na početku liste.
Na Slika 5.5-3 prikazan je izgled reda predstavljenog povezanom listom prilikom
dodavanja i brisanja elemenata slededm redosledom: lnsert(5), lnsert(8), Delete(), lnsert(2),
lnsert(7), Delete().
Slika 5.5-3 Šematski prikaz dodavanja i brisanja elemenata iz reda predstavljenog povezanom listom
5.5.3 Osnovne operacije
Postoji pet osnovnih operacija za rad sa strukturom tipa red, i to
enqueue - dodaje element na kraj reda,
dequeue - čita i uklanjanja element sa po
getHead - čita element sa po
isEmpty - proverava da li je red prazan i
numberOfElements - vrać
Operacije enqueue i dequeue
osim dodavanja i brisanja elementa moraju ažurirati i pokaziva
respektivno. Ukoliko se dodaje element (operacija
prekoračenje reda i emituje se izuzetak SBPException("Queue overflo
iz praznog reda (operacije dequeue
emituje se izuzetak SBPException("Queue underflo
63
ematski prikaz dodavanja i brisanja elemenata iz reda predstavljenog povezanom listom
Postoji pet osnovnih operacija za rad sa strukturom tipa red, i to su:
dodaje element na kraj reda,
ita i uklanjanja element sa početka reda,
ita element sa početka reda, ali ga ne uklanjanja,
proverava da li je red prazan i
vraća broj elemenata smeštenih u redu.
dequeue menjaju ukupan broj elemenata smeštenih u redu, pa
osim dodavanja i brisanja elementa moraju ažurirati i pokazivače na kraj i po
respektivno. Ukoliko se dodaje element (operacija enqueue) u pun red, javlja se gr
i emituje se izuzetak SBPException("Queue overflow!"). Prilikom
dequeue i getHead) javlja se greška tipa potkora
emituje se izuzetak SBPException("Queue underflow!").
ematski prikaz dodavanja i brisanja elemenata iz reda predstavljenog povezanom listom
štenih u redu, pa
e na kraj i početak reda,
u pun red, javlja se greška tipa
!"). Prilikom čitanja
potkoračenja reda i
Na Slika 5.5-4 prikazan je postupak dodavanja elemenata u red i brisanja elemenata iz
reda. Inicijalno (slika a), red sadr
reda) i tail (kraj reda) ukazuju na jedini element u redu. Operacijom
novi element na kraj reda (slika
operacijom enqueue(7). Uklanjanjem elementa sa po
se vrednost pokazivača head,
Nakon toga, sledi dodavanje još jednog elementa na kraj reda, operacijom
e), i brisanje elementa sa početka reda, operacijom
ažuriraju se vrednost pokaživač
respektivno.
Slika
5.6 Memorijska reprezentacija
Red može imati statič
reprezentaciju. Kod statičke reprezentacije, pokaziva
(poslednji uneti element) su indeksi u jednodimenzionalnom polju, pri
vrednosti pri operaciji dodavanja
polja.
Slika 5.6-1
Dinamička reprezentacija podrazumeva koris
prolazak kroz celu listu, prilikom brisanja elementa sa po
64
prikazan je postupak dodavanja elemenata u red i brisanja elemenata iz
), red sadrži samo jedan element, čija je vrednost 3.
(kraj reda) ukazuju na jedini element u redu. Operacijom enqueue(5)
novi element na kraj reda (slika b). Nakon toga, dodaje se još jedan element (slika
Uklanjanjem elementa sa početka reda, operacijom dequ
head, jer sada je element čija je vrednost 5 na početku reda (slika
Nakon toga, sledi dodavanje još jednog elementa na kraj reda, operacijom enqueue(9)
), i brisanje elementa sa početka reda, operacijom dequeue() (slika f). Svakom od operacija
žuriraju se vrednost pokaživača head i tail, tako da uvek ukazuju na početak i kraj reda,
Slika 5.5-4 Primer dodavanja i brisanje elemenata iz reda
rijska reprezentacija
že imati statičku (Slika 5.6-1a) ili dinamičku (Slika 5.6-
čke reprezentacije, pokazivači na head (prvi uneti element) i
(poslednji uneti element) su indeksi u jednodimenzionalnom polju, pri č
vrednosti pri operaciji dodavanja (tail) i čitanja (head) inkrementiraju po modulu veli
1 Memorijska reprezentacija reda: a) statička b) dinamička
ka reprezentacija podrazumeva korisćenje lančane liste. Da bi se izbegao
prolazak kroz celu listu, prilikom brisanja elementa sa početka liste (ili dodavanja na kraj),
prikazan je postupak dodavanja elemenata u red i brisanja elemenata iz
ija je vrednost 3. I head (početak
enqueue(5) dodaje se
). Nakon toga, dodaje se još jedan element (slika c),
etka reda, operacijom dequeue(), menja
četku reda (slika d).
enqueue(9) (slika
f). Svakom od operacija
tako da uvek ukazuju na početak i kraj reda,
-1b) memorijsku
(prvi uneti element) i tail reda
(poslednji uneti element) su indeksi u jednodimenzionalnom polju, pri čemu se njihove
inkrementiraju po modulu veličine
čka
ane liste. Da bi se izbegao
etka liste (ili dodavanja na kraj),
65
poželjno je da postoje pokazivači i na početak i na kraj liste, kao i dvostruko ulančavanje
elemenata.
5.7 Dvostrani red
Dvostrani red (engl deque) je linearna struktura podataka koja omogućuje dodavanje i
brisanje podataka sa oba kraja
Dvostrani red je specijalni slučaj linearne liste kod koje se novi elementi mogu dodavati
i uklanjati sa oba kraja liste.
5.8 Osnovne operacije
Postoji osam osnovnih operacija za rad sa strukturom tipa dvostrani red, i to su:
enqueueHead - dodaje element na početak dvostranog reda,
enqueueTail - dodaje element na kraj dvostranog reda,
dequeueHead - čita i uklanja element sa početka dvostranog reda,
dequeueTail - čita i uklanja element sa kraja dvostranog reda,
getHead - čita element sa početka dvostranog reda, ali ga ne uklanja,
getTail - čita element sa kraja dvostranog reda, ali ga ne uklanja,
isEmpty - proverava da li je dvostrani red prazan i
numberOfElements - vraća broj elemenata smeštenih u dvostranom redu.
Operacije enqueueHead i enqueueTail emiruju izuzetak SBPException("Deque
overflow!"), ukoliko se upis vrši u pun dvostrani red, dok operacije dequeueHead,
dequeueTail, getHead, i getTail emiruju izuzetak SBPException("Deque underflow!"),
ukoliko je prilikom njihovog poziva dvostrani red prazan.
Na Slika 5.8-1 prikazan je postupak dodavanja elemenata u dvostrani red i brisanja
elemenata iz dvostranog reda. U dvostrani red koji inicijalno ima samo jedan element (slika
a), najpre se dodaje jedan element čija je vrednost 5 na kraj reda (slika b), a zatim i element sa
vrednošću 7 na početak reda (slika c). Nakon toga, uklanja se jedan element sa kraja reda
(slika d), dodaje element sa vrednošću 9 na kraj reda (slika e), i čita element sa početka reda
(slika f).
Slika 5.8-1
5.9 Memorijska reprezentacija
Memorijska reprezentacija dvostranog reda identi
reda, sa izuzetkom dodavanja interfejsnih funkcija koje omogu
odnosno, ne samo inkrementiranje ve
66
1 Primer dodavanja i brisanja elemenata iz dvostranog reda
Memorijska reprezentacija
Memorijska reprezentacija dvostranog reda identična je reprezentaciji jednostranog
reda, sa izuzetkom dodavanja interfejsnih funkcija koje omogućuju upis i čitanje sa oba kr
odnosno, ne samo inkrementiranje već i dekrementiranje pokazivača na početak i kraj reda.
Primer dodavanja i brisanja elemenata iz dvostranog reda
na je reprezentaciji jednostranog
čitanje sa oba kraja,
četak i kraj reda.
67
6 STABLA
6.1 Uvod
Stabla se koriste za predstavljanje hijerarhijske strukture neke kolekcije podataka.
Naime, za razliku od liste, zasnovane na linearnom uređenju podataka, stablo se zasniva na
hijerarhijskom uređenju. Dakle među podacima postoji odnos “podređeni-nadređeni” ili
“dete-roditelj”.
Stablo (engl. tree) je konačan neprazan skup čvorova za koga važi:
1. Postoji jedan specijalan čvor koji se naziva koren (engl. root) stabla.
2. Ostali čvorovi mogu se podeliti u m disjunktnih podskupova (� � 0), od kojih svaki
predstavlja stablo (Slika 6.1-1)
Slika 6.1-1 Stablo T
Ovo je bila rekurzivna definicija. Manja stabla T1, T2, . . .,Tk se zovu pod-stabla korena
r. Koreni r1, r2, . . ., rk od T1, T2, . . .,Tk su deca od r, a r je njihov roditelj . Primetimo da
koren nema roditelja, a svaki od preostalih čvorova ima tačno jednog roditelja. Uređenost
stabla se ogleda u tome što među podstablima postoji linearno uređenje (zna se koje je prvo,
koje drugo,. . .).
Broj podstabala svakog čvora je stepen čvora. Čvor nultog stepena naziva se eksterni
čvor, terminalni čvor ili list, a čvor stepena ≥ 1 naziva se interni ili neterminalni čvor. Za
svaki čvor se definiše nivo ili dubina, pri čemu se uzima da je koren na nultom nivou.
Maksimalni nivo čvora u stablu uvećan za 1 je visina stabla. Moment stabla je broj čvorova
u stablu, a težina stabla je broj listova. Stablo može biti uređeno ili neuređeno. Stablo je
uređeno ako je bitna relativna uređenost podstabala u svakom čvoru.
Na Slika 6.1-2 dat je primer stabla koje sadrži devet
Čvor A je koren stabla, čvorovi C, E, G, H i I su listovi, a
ili unutrašnji čvorovi. Stablo ima visinu 4, težin
Struktura prikazana na prethodnoj slici je stablo iz razloga
C, D, E, F, G, H, I}, pri čemu je
disjunktna skupa {B, E, F, H,
što zadovoljava oba uslova navedena u definiciji.
Struktura prikazana na Slika
onemogućava razdvajanje čvorova od B do I u disjunktne skupove.
Slika
6.2 Binarna stabla
Umesto stabala (koja se
pojavljuju binarna stabla. Radi se o ne
je lakše prikazati u računaru.
Binarno stablo T je konač
vredi:
- T je prazan skup (prazno stablo) , ili
- postoji istaknuti čvor
(TL, TR) disjunktnih (manjih) binarnih stabala,
68
dat je primer stabla koje sadrži devet čvorova: A, B, C, D, E, F, G, H i I.
čvorovi C, E, G, H i I su listovi, a čvorovi A, B, D i F su neterminalni
vorovi. Stablo ima visinu 4, težinu 5 i moment 9.
Slika 6.1-2 Primer stabla
Struktura prikazana na prethodnoj slici je stablo iz razloga što je to skup č
čemu je čvor A koren stabla, a ostali čvorovi su
H, I}, {D, G} i {C }. Svaki od ova tri skupa je takođ
što zadovoljava oba uslova navedena u definiciji.
Slika 6.1-3 nije stablo, zato što činjenica da je
čvorova od B do I u disjunktne skupove.
Slika 6.1-3 Šematski prikaz strukture koja nije stablo
Umesto stabala (koja se često razmatraju u matematici) u računarstvu se jo
stabla. Radi se o nešto jednostavnijem i pravilnije građenom objektu kojeg
je konačan skup podataka istog tipa koje zovemo čvorovi
je prazan skup (prazno stablo) , ili
čvor r koji se zove koren od T , a ostali čvorovi grade ure
) disjunktnih (manjih) binarnih stabala,
vorova: A, B, C, D, E, F, G, H i I.
vorovi A, B, D i F su neterminalni
što je to skup čvorova {A, B,
čvorovi su podeljeni u tri
}. Svaki od ova tri skupa je takođe stablo, zato
da je čvor E podeljen
unarstvu se još češće
enom objektu kojeg
čvorovi. Pri tome
čvorovi grade uređeni par
69
Slika 6.2-1.
Slika 6.2-1 Binarno stablo
Ako T sadrži koren r, tada se binarna stabla TL i TR zovu levo i desno podstablo. Koren
od TL (ako postoji) je levo dete od r, koren od TR (ako postoji) je desno dete od r, a r je
njihov roditelj . Ostala terminologija je ista kao kod stabla.
Primetimo da binarno stablo nije specijalni slučaj uređenog stabla. Naime:
- binarno stablo može biti prazno,
- ako čvor u binarnom stablu ima samo jedno dete, tada nije svejedno da li je to levo ili
desno dete.
Slika 6.2-2 Dva različita binarna stabla.
Na dijagramima sa Slika 6.2-2 se vide dva različita binarna stabla. Isti dijagrami bi se
mogli shvatiti i kao uređena stabla, ali tada bi to bilo jedno te isto stablo.
Zaključimo da je binarno stablo specijalni slučaj stabla u kome ni jedan čvor nema
stepen veći od 2. Proizilazi da je binarno stablo, stablo kod koga svaki čvor ima 0, 1 ili 2
direktna sledbenika. Binarno stablo koje ima u svakom čvoru 0 ili 2 sledbenika naziva se
prošireno ili striktno binarno stablo . Binarno stablo je potpuno ako su svi nivoi
maksimalno popunjeni (Slika 6.2-3). Puno binarno stablo je binarno stablo dubine k koje
sadrži 2k -1 čvorova. Ukoliko je binarno stablo puno njegovi čvorovi se mogu numerisati
brojevima od 1 do 2k -1 tako što bi se po
nivo sa leva na desno.
Binarno stablo je gotovo potpuno
popunjeni, dok je poslednji nivo delimi
Uređeno binarno stablo
njegova vrednost veća od svih vrednosti u
od svih vrednosti u čvorovima
Uravnoteženo ili balansirano binarno
levog i desnog podstabla bilo kog
stablo je uravnoteženo binarno stablo kod koga su svi listovi na
Slika
Slika 6.2
Konačno, za binarno stablo
1. Maksimalni broj čvorova na
2. Ako je k dubina bina
da ima:
23 � 1 � 236 � 236�
70
1 tako što bi se počelo od korena, a zatim numerisao jedan po jedan
gotovo potpuno ako su svi nivoi, osim poslednjeg, potpuno
popunjeni, dok je poslednji nivo delimično popunjen sleva udesno (Slika 6.2-4
eno binarno stablo je binarno stablo kod koga svaki čvor ima svojstvo da je
ća od svih vrednosti u čvorovima levog podstabla, a manja (ili jednaka)
čvorovima desnog podstabla.
Uravnoteženo ili balansirano binarno stablo je binarno stablo kod koga se visina
levog i desnog podstabla bilo kog čvora razlikuje najviše za jedan. Perfektno uravnoteženo
je uravnoteženo binarno stablo kod koga su svi listovi na jednom ili dva nivoa.
Slika 6.2-3 Potpuno binarno stablo sa 4 nivoa (visine 4)
6.2-4 Gotovo potpuno binarno stablo sa 5 nivoa (visine 5)
stablo važi:
čvorova na i-tom nivou je 2!6
dubina binarnog stabla, onda je maksimalan broj čvorova koje stablo mož
� 7 � 28
korena, a zatim numerisao jedan po jedan
ako su svi nivoi, osim poslednjeg, potpuno
4).
čvor ima svojstvo da je
vorovima levog podstabla, a manja (ili jednaka)
stablo je binarno stablo kod koga se visina
Perfektno uravnoteženo
jednom ili dva nivoa.
čvorova koje stablo može
71
Napomenimo da mogu postojati i iskošena stabla, kao što je to prikazano na Slika 6.2-5:
Iskošeno u levo Iskošeno u desno
Slika 6.2-5 Iskošena binarna stabla
Slede primeri binarnih stabala:
- Ako je aritmetički izraz sastavljen od binarnih operacija tada se njegova građa može
prikazati binarnim stablom.
Građa aritmetičkog izraza (a + b) * (a +√�) se može prikazati stablom. Čvorovi bez
dece, odnosno listovi, predstavljaju operande, a ostali čvorovi računske operacije. Uređenost
stabla je važna ako su operacije nekomutativne.
Slika 6.2-6 Aritmetički izraz (a + b) * (a +√�) prikazan kao stablo.
- Ukoliko su, npr. alfa numerički znaci kodirani nizovima bitova, tada se postupak
dekodiranja može prikazati binarnim stablom:
72
Slika 6.2-7 Prikaz binarnog koda pomoću binarnog stabla.
6.3 Memorijska reprezentacija
Stabla mogu imati statičku ili dinamičku reprezentaciju. Najčešće se koristi dinamička
implementacija kod koje svaki čvor sadrži jedno ključno (engl. key) polje i više pokazivača na
podstabla. Pokazivači na podstabla imaju null vrednosti u listovima, ali i u nekim
neterminalnim čvorovima, ukoliko ne postoji odgovarajuće podstablo.
Binarno stablo se na razne načine može definisati kao apstraktni tip podataka. Osim
operacija koje rade na nivou čvorova, lepo se mogu definisati i operacije na nivou pod-
stabala.
Svakom čvoru eksplicitno zapišemo njegovo levo i desno dete. Veza se može zapisati
pomoću kursora ili pomoću pointera. Posmatraćemo varijantu pomoću pointera.
Svaki čvor prikazujemo jednom ćelijom. Čvor je zato jednoznačno odreden pointerom
na tu ćeliju. Binarno stablo se gradi kao struktura ćelija povezanih pointerima. Binarno stablo
poistovećujemo s pointerom na koren. Prazno stablo je prikazano pointerom NULL.
Slika 6.3-1 Implementacija binarnog stabla pomoću pointera
73
Statička implementacija stabala koristi strukturu polja. Kod potpunih i gotovo potpunih
stabala statička reprezentacija je najefikasnija za smeštanje čvorova, obizirom da su svi
elementi polja popunjeni.
Potpuno i gotovo potpuno binarno stablo je građeno od n čvorova, s imenima 0, 1, 2, . .
., n − 1. U tom slučaju vredi:
- levo dete čvora i je čvor 2i + 1 (ako je 2i + 1 > n − 1 tada čvor i nema levo dete);
- desno dete čvora i je i čvor 2i + 2 (ako je 2i+ 2 > n− 1 tada i nema desno dete).
Npr. potpuno binarno stablo s n = 12 čvorova izgleda kao na slici.
Slika 6.3-2 Potpuno binarno stablo.
Na svim nivoima osim zadnjeg postoje svi mogući čvorovi. Čvorovi na zadnjem nivou
su “gurnuti” na levu stranu. Numerisanje ide s nivoa 0 na nivo 1, nivo 2, itd., s leva na desno.
Potpuno binarno stablo treba zamišljati kao objekat sa statičkom građom. Što se tiče
jezika C, na ovakvo stablo se ne primenjuju operacije kao što su CREATE(), LEFT
SUBTREE(), RIGHT SUBTREE(), jer rezultat više ne bi bio potpuno binarno stablo.
Umesto toga potrebno je “manevrisati” po već zadanom stablu, te čitati ili menjati oznake
čvorova. Eventualno se dozvoljava ubacivanje/izbacivanje čvorova na desnom kraju zadnjeg
nivoa.
Slika 6.3-
Potpuno binarno stablo se može elegantno prikazati na ra
ćelija polja sadrži oznaku čvora
imamo definicije:
#define MAXNODE .../* dovoljno velika konstanta */
typedef int node;
typedef struct { int last;
labeltype labels[MAXNODE];
} BTREE;
Manevrisanje po stablu se obavlja na o
ćelijom. Levo i desno dete čvora iz
postoje). Roditelj čvora iz i-te ć
Kao zaključak, na Slika
statičke reprezentacije.
74
3 Implementacija potpunog binarnog stabla pomoću polja.
Potpuno binarno stablo se može elegantno prikazati na računaru pomo
ra i. Takođe imamo kursor koji pokazuje zadnji č
#define MAXNODE .../* dovoljno velika konstanta */
typedef int node;
typedef struct { int last;
labeltype labels[MAXNODE];
Manevrisanje po stablu se obavlja na očigledni način. Koren je predstavljen 0
čvora iz i-te ćelije nalaze se u (2i + 1)-oj i (2i + 2)
te ćelije je u :�� � 1 ��/2<-toj ćeliji.
Slika 6.3-4 dat je primer binarnog stabla i njegove dinami
Simbolički prikaz binarnog stabla
ću polja.
unaru pomoću polja. i-ta
e imamo kursor koji pokazuje zadnji čvor n−1. Dakle
#define MAXNODE .../* dovoljno velika konstanta */
in. Koren je predstavljen 0-tom
+ 2)-oj ćeliji (ako
dat je primer binarnog stabla i njegove dinamičke i
ki prikaz binarnog stabla
Slika
Gotovo potpuno stablo č
jednakom ključu njegovog roditelja, na
roditeljskog ključa veća (ili jednaka) od vrednosti klju
max gomili (engl. maxheap), a ako je manja ili jednaka, o min gomili (engl. minheap). Pod
pojmom gomila najčešće se podraz
6.3.1 Osnovne operacije
Osnovne operacije za rad sa strukturom tipa stablo su:
• insert - dodaje novi
• delete - briše čvor iz stabla,
• search - pronalazi željeni
• traverse - obilazi sve
Mnogi algoritmi za manipulaciju stablima imaju potrebu da sistematski obilaze sve
čvorove u stablu. Generalno, postoje dva tipa obilaska stabla (traverse), i to:
• depthFirst - obilazak po dubini i
• breadthFirst - obilazak po širini.
Pod obilaskom binarnog stabla podrazumevamo prolazak kroz sve njegove
određenim redosledom, pri čemu je istovremeno mogu
podacima koji su u njima zapisani.
Obilazak po dubini (depthFirst
oblika:
• preorder,
75
Dinamička reprezentacija
Statička reprezentacija pomoć
jednodimenzionalnog polja
Slika 6.3-4 Memorijske reprezentacije binarnog stabla
Gotovo potpuno stablo čiji svaki čvor sadrži ključ sa vrednošću već
u njegovog roditelja, naziva se gomila (engl. heap). Ukoliko je vrednost
ća (ili jednaka) od vrednosti ključeva čvorova njegove dece, radi se o
max gomili (engl. maxheap), a ako je manja ili jednaka, o min gomili (engl. minheap). Pod
podrazumeva binarna gomila.
Osnovne operacije za rad sa strukturom tipa stablo su:
dodaje novi čvor u stablo,
čvor iz stabla,
pronalazi željeni čvor u stablu i
obilazi sve čvorove stabla.
i algoritmi za manipulaciju stablima imaju potrebu da sistematski obilaze sve
vorove u stablu. Generalno, postoje dva tipa obilaska stabla (traverse), i to:
obilazak po dubini i
obilazak po širini.
og stabla podrazumevamo prolazak kroz sve njegove
enim redosledom, pri čemu je istovremeno moguće izvršiti i određenu operaciju nad
podacima koji su u njima zapisani.
depthFirst) je rekurzivan i može se javiti u jednom od s
pomoću
ću većom/manjom ili
ziva se gomila (engl. heap). Ukoliko je vrednost
vorova njegove dece, radi se o
max gomili (engl. maxheap), a ako je manja ili jednaka, o min gomili (engl. minheap). Pod
i algoritmi za manipulaciju stablima imaju potrebu da sistematski obilaze sve
og stabla podrazumevamo prolazak kroz sve njegove čvorove
đenu operaciju nad
) je rekurzivan i može se javiti u jednom od sledeća tri
76
• inorder ili
• postorder.
Kod preorder obilaska, najpre se obrađuje koren, a zatim se vrši preorder obilazak
svakog od njegovih podstabala, jednog po jednog, u poretku kojim se zadaju njihove
reference u okviru korena. U slučaju binarnog stabla, najpre se obrađuje koren, zatim njegovo
levo podstablo, pa desno podstablo. Za stablo prikazano na Slika 6.3-5, preorder obilazak daje
sledeći redosled čvorova: A, B, D, E, H, I, C, F, G.
Inorder obilazak ima smisla samo kod binarnih stabala, i vrši se tako što se najpre
obiđe levo podstablo, zatim koren i na kraju desno podstablo. Za stablo prikazano na Slika
6.3-5, inorder obilazak daje sledeći redosled čvorova: D,B,H,E,I,A,F,C,G.
Postorder obilazak obrađuje koren nakon što se obiđu sva njegova podstabla, odnosno,
kod binarnih stabala, nakon obilaska i levog i desnog podstabla. Za stablo prikazano na Slika
6.3-5, postorder obilazak daje sledeći redosled čvorova: D,H,I,E,B,F,G,C,A.
Za razliku od obilazaka po dubini, obilazak po širini se najčešće predstavlja kao
nerekurzivni obilazak, jer najpre posećuje sve čvorove na dubini 0 (tj. koren), zatim sve
čvorove na dubini 1 (direktne potomke korena), pa sve čvorove na dubini 2, itd. Za stablo
prikazano na Slika 6.3-5, obilazak po širini daje sledeći redosled čvorova: A,B,C,D,E,F,G,H,I.
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 Slika 6.3-6:
Slika 6.3-5 Tipičan primer korišćenja binarnog stabla je predstavljanje aritmetičkih izraza
Slika
Brisanje čvora iz uređenog binarnog stabla predstavlja vrlo složenu operaciju, jer
zahteva da stablo ostane ure
brisanja čvora iz uređenog binarnog stabla:
• čvor koji se briše je list
• čvor koji se briše ima jednog potomka (bilo levog ili desnog)
na njegovo mesto dolazi njegov potomak i
• čvor koji se briše ima oba
dva algoritma: brisanje kopiranjem
(deleteByMerge
Kod brisanja kopiranjem
jednak) od svih elemenata u levom podstablu, a manji od svih elemenata u desnom podstablu,
kada bude postavljen na mesto obrisanog elementa. Postoje dva kandidata za zamenu sa
obrisanim elementom, a to su: krajnji desni
podstabla. Jedan od ta dva čvora se briše sa svoje pozicije i premešta na poziciju
uklanja iz stabla. Ukoliko je premešteni
prethodnu poziciju premeštenog
Kod brisanja mešanjem
mešanjem, a zatim dodaje kao podstablo roditelju uklonjenog
ostvariti na jedan od dva načina:
• pronađe se krajnji desni
dodeli čitavo desno
dolazi direktni levi potomak obrisanog
• pronađe se krajnji levi
dodeli čitavo levo podstablo
77
Slika 6.3-6 Aritmetički izraz predstavljen binarnim stablom
vora iz uređenog binarnog stabla predstavlja vrlo složenu operaciju, jer
zahteva da stablo ostane uređeno i nakon uklanjanja željenog čvora. Postoje tri slu
đenog binarnog stabla:
vor koji se briše je list - obzirom da nema potomaka jednostavno se ukljanja,
vor koji se briše ima jednog potomka (bilo levog ili desnog) - č
na njegovo mesto dolazi njegov potomak i
vor koji se briše ima oba potomka - najsloženiji slučaj koji se rešava jednim od
brisanje kopiranjem (deleteByCopying) ili brisanje mešanjem
deleteByMerge).
brisanja kopiranjem neophodno je naći element koji će po vrednosti biti ve
ta u levom podstablu, a manji od svih elemenata u desnom podstablu,
kada bude postavljen na mesto obrisanog elementa. Postoje dva kandidata za zamenu sa
obrisanim elementom, a to su: krajnji desni čvor levog podstabla i krajnji levi
čvora se briše sa svoje pozicije i premešta na poziciju
uklanja iz stabla. Ukoliko je premešteni čvor imao jednog potomka, taj potomak prelazi na
prethodnu poziciju premeštenog čvora.
brisanja mešanjem od dva podstabla čvora koji se briše kreira se jedno stablo
mešanjem, a zatim dodaje kao podstablo roditelju uklonjenog čvora. Mešanje se može
čina:
e se krajnji desni čvor u levom podstablu i njemu se kao desno podstablo
čitavo desno podstablo čvora koji se briše, a na mesto obrisanog
dolazi direktni levi potomak obrisanog čvora i
e se krajnji levi čvor u desnom podstablu i njemu se kao levo podstablo
čitavo levo podstablo čvora koji se briše, a na mesto obrisanog
enog binarnog stabla predstavlja vrlo složenu operaciju, jer
čvora. Postoje tri slučaja
obzirom da nema potomaka jednostavno se ukljanja,
čvor se uklanja, a
aj koji se rešava jednim od
brisanje mešanjem
e po vrednosti biti veći (ili
ta u levom podstablu, a manji od svih elemenata u desnom podstablu,
kada bude postavljen na mesto obrisanog elementa. Postoje dva kandidata za zamenu sa
vor levog podstabla i krajnji levi čvor desnog
vora se briše sa svoje pozicije i premešta na poziciju čvora koji se
vor imao jednog potomka, taj potomak prelazi na
ra koji se briše kreira se jedno stablo
čvora. Mešanje se može
vor u levom podstablu i njemu se kao desno podstablo
vora koji se briše, a na mesto obrisanog čvora
vor u desnom podstablu i njemu se kao levo podstablo
vora koji se briše, a na mesto obrisanog čvora
dolazi
direktni desni potomak obrisanog
Za razliku od brisanja kopiranjem, brisanje mešanjem može narušiti balansiranost
stabla, obzirom da se menja visina jednog podstabla.
Balansiranje binarnog stabla najlakše se može ostvariti koriš
algoritma:
1. sve čvorove stabla iskopirati u polje i obrisati stablo,
2. urediti polje u rastu
3. formirati novo stablo
4. levo podstablo kreira se od leve polovine ure
5. desno podstablo kreira se od desne polovine ure
Koraci 3, 4 i 5 ponavljaju se rekurzivno sve dok postoji bar jedan elemenat u segmentu
uređenog polja na osnovu koga se formira podstablo.
Osnovne operacije za rad sa strukturom tipa
• insert - dodaje novi
• deleteRoot - briše koreni
Prilikom formiranja gomile, novi
njegovog ključa upoređuje sa vrednoš
utvrdi da novododati čvor ima ve
Postupak upoređivanja i zamene mesta se nastavlja sve dok se ne nadje kona
unetog čvora. Na Slika 6.3
sukcesivnog unosa čvorova sa klju
Brisanje korena gomile se izvod
• čita se ključ korena gomile i koren se briše,
• na mesto korena upisuje se poslednji element gomile i
78
direktni desni potomak obrisanog čvora.
Za razliku od brisanja kopiranjem, brisanje mešanjem može narušiti balansiranost
stabla, obzirom da se menja visina jednog podstabla.
binarnog stabla najlakše se može ostvariti korišćenjem sle
vorove stabla iskopirati u polje i obrisati stablo,
urediti polje u rastući redosled,
formirati novo stablo čiji koren postaje središnji elemenat uređenog polja,
levo podstablo kreira se od leve polovine uređenog polja, a
blo kreira se od desne polovine uređenog polja.
Koraci 3, 4 i 5 ponavljaju se rekurzivno sve dok postoji bar jedan elemenat u segmentu
u koga se formira podstablo.
Osnovne operacije za rad sa strukturom tipa gomile su:
e novi čvor u gomilu i
briše koreni čvor gomile.
Prilikom formiranja gomile, novi čvor dodaje se uvek kao list, a zatim se vrednost
đuje sa vrednošću ključa roditelja. U slučaju maxheap
vor ima veću vrednost ključa, on zamenjuje mesto sa roditeljem.
ivanja i zamene mesta se nastavlja sve dok se ne nadje kona
6.3-7 prikazan je postupak formiranja max gomile prilikom
vorova sa ključevima čije su vrednosti: 12, 28, 32 i 45.
Slika 6.3-7 Formiranje max gomile
Brisanje korena gomile se izvodi po sledećem algoritmu:
č korena gomile i koren se briše,
na mesto korena upisuje se poslednji element gomile i
Za razliku od brisanja kopiranjem, brisanje mešanjem može narušiti balansiranost
binarnog stabla najlakše se može ostvariti korišćenjem sledećeg
đenog polja,
Koraci 3, 4 i 5 ponavljaju se rekurzivno sve dok postoji bar jedan elemenat u segmentu
vor dodaje se uvek kao list, a zatim se vrednost
aju maxheap-a, ukoliko se
a, on zamenjuje mesto sa roditeljem.
ivanja i zamene mesta se nastavlja sve dok se ne nadje konačna pozicija
prikazan je postupak formiranja max gomile prilikom
• čvor koji je trenutno na
svoje mesto (odnosno, dok stablo ponovo ne postane
kopiranjem poslednjeg elementa na mesto korena narušava struktura gomile).
Postupak brisanja korena prikazan je na
6.4 Primeri primene
Stabla imaju široku primenu u konverziji zapisa aritmeti
podacima korišćenjem uređenih stabala i brzom pronalaženju odgovora na postav
korišćenjem stabla odlučivanja.
6.4.1 Primer: Stablo algebarskog izraza
Stabla se mogu koristiti za generisanje i izra
izrazu predstavljeni su listovima, a odgovaraju
Na primer, izraz (A + B ) * C-
Slika 6.4
Na osnovu ovakvog stabla vrlo je jednostavno generisati jednu od tri notacije izraza:
prefix, infix ili postfix, korišć
postorder, respektivno).
79
vor koji je trenutno na mestu korena pomera se ka listovima sve dok ne zauzme
svoje mesto (odnosno, dok stablo ponovo ne postane gomila, obzirom da se
kopiranjem poslednjeg elementa na mesto korena narušava struktura gomile).
Postupak brisanja korena prikazan je na Slika 6.3-8.
Slika 6.3-8 Brisanje korena max gomile
Stabla imaju široku primenu u konverziji zapisa aritmetičkih izraza, brzom pristupu
đenih stabala i brzom pronalaženju odgovora na postav
čivanja.
Primer: Stablo algebarskog izraza
Stabla se mogu koristiti za generisanje i izračunavanje algebarskih izraza. Operandi u
izrazu predstavljeni su listovima, a odgovarajuće operacije i relacije - unutrašnjim
- D / E , moze biti predstavljen stablom na Slika
6.4-1 Primer stabla algebarskog izraza (A + B ) * C - D / E
Na osnovu ovakvog stabla vrlo je jednostavno generisati jednu od tri notacije izraza:
prefix, infix ili postfix, korišćenjem odgovarajućih obilazaka po dubini (preorder, inorder i
estu korena pomera se ka listovima sve dok ne zauzme
gomila, obzirom da se
kopiranjem poslednjeg elementa na mesto korena narušava struktura gomile).
kih izraza, brzom pristupu
enih stabala i brzom pronalaženju odgovora na postavljena pitanja
unavanje algebarskih izraza. Operandi u
unutrašnjim čvorovima.
Slika 6.4-1.
Na osnovu ovakvog stabla vrlo je jednostavno generisati jednu od tri notacije izraza:
ih obilazaka po dubini (preorder, inorder i
6.4.2 Primer: Stablo odlučiv
Važna klasa binarnih stabala su stabla odlu
predstavljanja većeg broja različ
pitanja. U ovom slučaju za svako pitanje se vezuje jedan
predstavljaju odgovore da i ne. Primer stabla odlu
životinja slon prikazan je na Slika
6.4.3 Primer: Organizacija sistema datoteka
U mnogim operativnim sistemima, datoteke su organizovane hijera
koji se korisniku predstavljaju u obliku stabla. Interni
listovi su datoteke. Primer hijerarhijske organizacije sistema datoteka prikazan je na
Slika
6.4.4 Primer: Uređenje primenom gomile
Osnovna karakteristika gomile je da se na vrhu (tj. u korenu) nalazi najve
ili najmanji (min gomila) element. Ukoliko neku linearnu strukturu treba urediti u neopadaju
redosled vrednosti njenih elemenata, potrebno je formirati min gomilu.
nerastući redosled formira se max gomila. Postupak dodavanja novog 80
Primer: Stablo odlučivanja
Važna klasa binarnih stabala su stabla odlučivanja, koja su nastala iz potrebe
eg broja različitih izraza nastalih kao rezultat odgovora na kolekciju da
čaju za svako pitanje se vezuje jedan čvor stabla, a levi
predstavljaju odgovore da i ne. Primer stabla odlučivanja kojim se proverava da li je neka
Slika 6.4-2.
Slika 6.4-2 Primer stabla odlučivanja
Primer: Organizacija sistema datoteka
U mnogim operativnim sistemima, datoteke su organizovane hijerarhijski u direktorijume
koji se korisniku predstavljaju u obliku stabla. Interni čvorovi ovog stabla su direktorijumi, a
listovi su datoteke. Primer hijerarhijske organizacije sistema datoteka prikazan je na
Slika 6.4-3 Primer hijerarhijske organizacije sistema datoteka
Primer: Uređenje primenom gomile
Osnovna karakteristika gomile je da se na vrhu (tj. u korenu) nalazi najveć
ili najmanji (min gomila) element. Ukoliko neku linearnu strukturu treba urediti u neopadaju
redosled vrednosti njenih elemenata, potrebno je formirati min gomilu.
i redosled formira se max gomila. Postupak dodavanja novog čvora u gomilu u
ivanja, koja su nastala iz potrebe
itih izraza nastalih kao rezultat odgovora na kolekciju da-ne
vor stabla, a levi i desni link
ivanja kojim se proverava da li je neka
rhijski u direktorijume
vorovi ovog stabla su direktorijumi, a
listovi su datoteke. Primer hijerarhijske organizacije sistema datoteka prikazan je na Slika 6.4-3.
Osnovna karakteristika gomile je da se na vrhu (tj. u korenu) nalazi najveći (max gomila)
ili najmanji (min gomila) element. Ukoliko neku linearnu strukturu treba urediti u neopadajući
redosled vrednosti njenih elemenata, potrebno je formirati min gomilu. Za uređenje u
čvora u gomilu u
81
najnepovoljnijem slučaju ima složenost '�ℎ , gde je h visina stabla. Obzirom da je gomila
gotovo potpuno stablo, složenost dodavanja čvora u gomilu je '�(�)�� , gde je n broj čvorova
u stablu. Ukupna složenost formiranja gomile je '��(�)�� , jer je potrebno dodati n čvorova.
Brisanje korena i restrukturiranje gomile je takođe, u najgorem slučaju, '��(�)�� , pa je
ukupna složenost sortiranja '��(�)�� +'��(�)�� � '��(�)�� , čime se svrstava u jednu
od najefikasnijih metoda sortiranja.
82
7 ALGORITMI SORTIRANJA
7.1 Sortiranje izborom najmanjeg elementa (Selection sort)
Algoritam sortiranja izborom najmanjeg elementa u svojoj osnovi ima sledeći princip.
Prilikom prvog prolaska celim poljem, nađe se element sa najmanjom vrednošću i zameni sa
elementom koji je na prvom mestu polja. U drugom prolasku se, između n-1 elemenata, nađe
element sa najmanjom vrednošću i zameni sa elementom koji se nalazi na drugoj poziciji.
Trećim prolaskom kroz n-2 preostala elementa polja, takođe, se nađe najmanji element i
zameni sa trećim. Postupak se ponavlja do poslednjeg elementa polja koji je na svom mestu.
Da bi se celo polje sortiralo potrebno je ostvariti n-1 prolazaka.
Na slici je prikazan primer sortiranja algoritmom izbora najmanjeg elementa. U svakom
prolasku označen je senčenjem najmanji element niza koji se analizira. Sa desne strane
vertikalne crte je posmarani, nesortirani deo polja. Sedmi prolazak nije potreban jer je deo
nesortiranog polja dužine jedan.
Polje koje treba sortirati 17 31 3 43 11 24 8
Posle 1. zamene �3> 31 17 43 11 24 8
Posle 2. zamene 3 �8> 17 43 11 24 31
Posle 3. zamene 3 8 �11> 43 17 24 31
Posle 4. zamene 3 8 11 �17> 43 24 31
Posle 5. zamene 3 8 11 17 �24> 43 31
Posle 6. zamene 3 8 11 17 24 �31> 43
Algoritam sortiranja izborom najmanjeg elementa može se u jeziku C realizovati
funkcijom selectionSort. Ulazni argumenti fnkcije su polje a[] i njegova dužina n. Funkcija
selectionSort menja ulazno polje tako da ono postane sortirano. Pomoćna funkcija change
menja pozicije elementima polja
void selectionSort (int a[], int n) {
int i, j, min;
for (i = 0; i < n; i++) {
min = i;
for (j = i+1; j < n; j++)
if (a[j] < a[min]) min = j;
change
}
}
void change
int pom;
pom = *x;
*x = *y;
*y = pom;
}
Efikasnost algoritma sortiranja izborom najmanjeg elementa oceni
njegove vremenske složenosti
• U prvom prolasku imamo n
taj broj smanjuje za jedan tako da je ukupan broj upore
�� � 1
• U svakom prolasku postoji još jedna zamena tako da imamo dodatnih
operacija pridruživanja
• Ukupan broj operacija je:
83
min = i;
for (j = i+1; j < n; j++)
if (a[j] < a[min]) min = j;
change (&a[i], &a[min]);
change (int *x, int *y) {
int pom;
pom = *x;
*x = *y;
*y = pom;
Efikasnost algoritma sortiranja izborom najmanjeg elementa ocenić
njegove vremenske složenosti
U prvom prolasku imamo n-1 upoređenja dok se u svakom narednom prolasku
taj broj smanjuje za jedan tako da je ukupan broj upoređivanja
1 � �� � 2 � �� � 3 � 7 � 2 � 1 � %�%6 �
U svakom prolasku postoji još jedna zamena tako da imamo dodatnih
operacija pridruživanja
Ukupan broj operacija je: %�%6
� � 3�� � 1 � '���
Efikasnost algoritma sortiranja izborom najmanjeg elementa ocenićemo analizom
enja dok se u svakom narednom prolasku
U svakom prolasku postoji još jedna zamena tako da imamo dodatnih 3�� � 1
84
7.2 Sortiranje zamenom susednih elemenata (bubble sort)
Algoritam sortiranja zamenom susednih elemenata realizuje se na sledeći način.
Polazimo od početka polja koje treba sortirati prema njegovom kraju i upoređujemo svaka dva
susedna elementa tog polja. Ukoliko je element koji se upređuje veći od sledećeg,
zamenjujemo im mesta, u suprotnom ostaju u istom redoslednom odnosu. Dolaskom do kraja
polja element sa najvećom vrednošću biće na poslednjem mestu. Zatim ponavljamo postupak
ali na skraćenom polju, zadnji elemenat skraćenog polja je već na svom mestu i ne sortira se.
Algoritam se zaustavlja čim se u nekom prolasku ustanovi da nema parova elemenata koje
treba zameniti.
Algoritam sortiranja zamenom susednih elemenata se može realizovati i na drugi način,
naime, sortiranje može krenuti sa kraja polja prema njegovom početku. Uslov zamene dva
susedna elementa polja, u ovom slučaju, je da sledeći element mora biti manji od prethodnog.
Sledeća slika pokazuje primer sortiranja algoritmom zamene susednih elemenata. Sa
slike možemo videti način realizacije ovog algoritma sortiranja. Algoritam formira pokretni
prozor u kome su dva susedna elementa koja se upoređuju (osenčeni deo polja). Kretanje
prozora je za po jedan element sve do kraja polja, u prvom prolazu, odnosno do poslednje
sortiranog elementa (označeno vertikalnim crtama). Poslednji prolaz, u ovom slučaju šesti,
služi da se ustanovi da više nema parova susednih elemenata kojima bi trebalo zameniti
mesta.
Prvi prolaz 17 31 3 43 11 24 8
17 3 31 43 11 24 8
17 3 31 11 43 24 8
17 3 31 11 24 43 8
17 3 31 11 24 �8> 43
Drugi prolaz 17 3 31 11 24 �8> 43
3 17 31 11 24 �8> 43
3 17 11 31 24 �8> 43
3 17 11 24 31 �8> 43
3 17 11 24 �8> 31 43
Treći prolaz 3 17 11 24 �8> 31 43
3 11 17 24 �8> 31 43
3 11 17 �8> 24 31 43
Četvrti prolaz 3 11 17 �8> 24 31 43
Peti prolaz
Šesti prolaz
Algoritam sortiranja zamenom susednih elemenata može se u jeziku C realizovati
funkcijom bubbleSort. Ulazni argumenti fnkcije su polje a
bubbleSort menja ulazno polje tako da ono postane sortirano. Pomo
pozicije elementima polja.
void bubbleSort (int a[], int n) {
int i, j;
for (i = 0; i < n
for (j = 0; j < n
if (a[j+1] < a[j])
change (&a[j], &a[j+1]);
}
Algoritam sortiranja zamenom susednih elemenata se može poboljšati ukoliko
zaustavimo postupak onog trenutka kada se ustanovi da u toku prolaska kroz polje nije bilo ni
jedne zamene susednih elemenata. Poboljšana verzija bubbleSort algoritma je:
void bubbleSort1 (int a[], int n)
int i, j, chg;
85
3 11 �8> 17 24 31
3 11 �8> 17 24 31
3 �8> 11 17 24 31
3 �8> 11 17 24 31
Algoritam sortiranja zamenom susednih elemenata može se u jeziku C realizovati
funkcijom bubbleSort. Ulazni argumenti fnkcije su polje a[] i njegova dužina n. Funkcija
bubbleSort menja ulazno polje tako da ono postane sortirano. Pomoćna funkcija change menja
void bubbleSort (int a[], int n) {
for (i = 0; i < n-1; i++)
for (j = 0; j < n-1-i; j++)
if (a[j+1] < a[j])
change (&a[j], &a[j+1]);
Algoritam sortiranja zamenom susednih elemenata se može poboljšati ukoliko
zaustavimo postupak onog trenutka kada se ustanovi da u toku prolaska kroz polje nije bilo ni
ednih elemenata. Poboljšana verzija bubbleSort algoritma je:
void bubbleSort1 (int a[], int n) {
int i, j, chg;
43
43
43
43
Algoritam sortiranja zamenom susednih elemenata može se u jeziku C realizovati
i njegova dužina n. Funkcija
ćna funkcija change menja
Algoritam sortiranja zamenom susednih elemenata se može poboljšati ukoliko
zaustavimo postupak onog trenutka kada se ustanovi da u toku prolaska kroz polje nije bilo ni
ednih elemenata. Poboljšana verzija bubbleSort algoritma je:
86
for (i = 0, chg = 1; chg; i++) {
chg = 0;
for (j = 0; j < n-1-i; j++)
if (a[j+1] < a[j]) { change (&a[j], &a[j+1]);
chg = 1;
}
}
}
Analizom vremenske složenosti algoritma sortiranja zamenom susednih elemenata
ocenićemo efikasnost samog algoritma.
• Prilikom prvog prolaska u najgorem slučaju možemo imati n-1 upoređenja i isto
toliko zamena elemenata
• Prilikom drugog prolaska, takođe u najgorem slučaju, imaćemo n-2 upoređenja i
n-2 zamena elemenata
• Ukoliko ovako nastavimo, u n-1 prolasku imaćemo u najgorem slučaju 1
upoređenje i 1 zamenu, tako da, konačno, možemo reći da u najgorem slučaju,
broj operacija će biti
4�� � 1 � 4�� � 2 � 7 � 4 # 1 � 4��� � 1 2 � 2��� � 1
• Ovaj broj operacija se stvarno dobija za slučaj kada su elementi polja već silazno
sortirani. U suprotnom ako je polje uzlazno sortirano obaviće se samo n-1
upoređenja i nula zamena, što opisuje samo jedan prolaz kroz polje.
• Za bilo koje drugo uređenje polja broj neophodnih operacija kreće se između n-1
i 2n(n-1), u svakom slučaju vreme realizacije je '��� .
7.3 Sortiranje umatanjem (insertion sort)
Algoritam sortiranja umetanjem podrazumeva da je pre početka njegove implementacije
deo polja sortiran a deo nije. Osnovni princip rada je da u jednom prolasku algoritam uzima
prvi elemenat iz nesortiranog dela polja i stavlja ga na njegovo ’’pravo mesto’’ (u smislu
sortiranog redosleda) u sortirani deo, pri čemu dolazi do pomeranja nekih elemenata za jedno
mesto dalje. Ovakvim postupkom se, u jednom prolasku, dužina sortiranog dela polja
povećava za jedan a za isti iznos se smanjuje dužina nesortiranog dela.
Ovaj jednostavni algoritam za sortiranje umetanjem (insertion sort) ilustrovaćemo
sledećim primetom, slika__. U svakom prolasku, element iz nesortiranog dela polja koji se
umeće u sortirani deo označen je sen
strelicom. Dvostruka vertikalna crta u ovom primeru odvaja s
nesortiranog dela koji se nalazi sa desne strane crte.
Početno polje
Posle 1. prolaska
Posle 2. prolaska
Posle 3. prolaska
Posle 4. prolaska
Posle 5. prolaska
Posle 6. prolaska
Algoritam sortiranja umetanjem može se u jeziku C realizovati funkcijom insertionSort.
Ulazni argumenti fnkcije su polje a
polje tako da ono postane sortirano.
void insertionSort (int a[], int n) { int i, j;
int aux;
for (i = 1; i < n; i++) { aux = a[i];
for (j = i; j >= 1 && a[j
a[j] = a[j
a[j] = aux;
}
}
87
čen je senčenjem dok je mesto gde se umeće element ozna
strelicom. Dvostruka vertikalna crta u ovom primeru odvaja sortirani deo sa leve strane od
nesortiranog dela koji se nalazi sa desne strane crte.
�17> B31 3 43 11 24
B17 �31> 3 43 11 24
3 17 �31> B43 11 24
3 B17 31 �43> 11 24
3 11 17 B31 �43> 24
3 B 11 17 24 31 �43>3 8 11 17 24 31
Algoritam sortiranja umetanjem može se u jeziku C realizovati funkcijom insertionSort.
Ulazni argumenti fnkcije su polje a[] i njegova dužina n. Funkcija insertionSort menja ulazno
polje tako da ono postane sortirano.
void insertionSort (int a[], int n) { int i, j;
for (i = 1; i < n; i++) { aux = a[i];
for (j = i; j >= 1 && a[j-1] > aux; j--)
a[j] = a[j-1];
a[j] = aux;
će element označeno
ortirani deo sa leve strane od
24 8
24 8
24 8
24 8
24 8
� > 8
31 �43>
Algoritam sortiranja umetanjem može se u jeziku C realizovati funkcijom insertionSort.
i njegova dužina n. Funkcija insertionSort menja ulazno
88
Efikasnost algoritma sortiranja umetanjem ocenićemo analizom njegove vremenske
složenosti.
• U k-tom prolasku unazad prolazimo sortiranim delom polja dužine k. Elemente
na koje nailazimo pomeramo za jedno mesto dalje sve dok su oni veći od
elementa koga želimo umetnuti nanjegovo ’’pravo mesto’’. Taj postupak u
najgorem slučaju daje k upoređenja i otprilike toliko pridruživanja.
• Dakle ukupan broj operacija u najgorem slučaju je
2 # 1 � 2 # 2 � 7 � 2�� � 1 � ��� � 1
• Red veličine vremena izvođenja je '��� . U praksi se pokazuje da je ovaj
algoritam brži od algoritama sa zamenom elemenata.
7.4 Brzo sortiranje (quick sort)
Algoritam brzog sortiranja pripada grupi rekurzivnih algoritama. Osnovna ideja
algoritma je sledeća: odabere se jedan element polja koga ćemo nazvati pivot i sve ostale
elemente razvrstavamo levo od njega (ispred) ukoliko su manji ili jednaki njemu ili desno od
pivota (iza) ukoliko su veći ili jednaki njemu. Jasno je da posle ovakvog razvrstavanja pivot
ostaje na svom ’’pravom mestu’’ u sortiranom polju. Dalji postupak je jednostavan, naime,
treba nezavisno sortirati deo polja levo od pivota i deo polja desno od njega. Sortiranje oba
podpolja postiže se rekurzivnim pozivom istog algoritma ili na trivijalan način kada je polje
dužine 0 ili 1.
Razvrstavanje elemenata levo odnosno desno od pivota efikasno se obavlja tako što
pomeramo kursor sa levog odnosno desnog kraja polja, sve dok su tekući elementi manji ili
jednaki odnosno veći ili jednaki od pivota. Kada se oba kursora zaustave, našli smo element s
leva koji je veći od pivota i element sa desna koji je manji od pivota. Ta dva elementa koji su
na ’’pogrešnim stranama’’ zamenimo i zatim nastavimo sa pomeranjem kursora.
Razvrstavanje je završeno kada se kursori ukrste.
Početno polje, pivot je prvi element �17> 31 3 43 11 24 8
Postavljanje, pomeranje i zaustavljanje kursora: �17> 31 3 43 11 24 8
4 C 4 D
89
Zamena elemenata na koje ukazuju kursori �17> 8 3 43 11 24 31
4 C 4 D
Pomeranje i zaustavljanje kursora �17> 8 3 43 11 24 31
4 C 4 D
Zamena elemenata na koje ukazuju kursori �17> 8 3 11 43 24 31
4 C 4 D
Pomeranje i zaustavljanje kursora: �17> 8 3 11 43 24 31
4 D 4 C
Kursori su se ukrstili. Ubacujemo pivot E8� 3 �11F 17 E43� 24 �31F Dva podpolja sortiramo rekurzivnim pozivima E3� 8 �11F 17 E24� 31 �43F
Jedan primer algoritma brzog sortiranja prikazan je na slici. Simboli 4 C i 4 D
označavaju položaj kursora sa levog odnosno desnog kraja polja u raznim fazama
razvrstavanja elemenata. Dvostruka vertikalna crta pokazuje da je pivot izdvojen u toku
razvrstavanja elemenata, dok uglate zagrade odvajaju podpolja koja se sortiraju rekurzivnim
pozivom istog algoritma. Nisu prikazani detalji unutar tih rekurzivnih poziva.
Implementacija algoritma brzog sortiranja u jeziku C je data kao rekurzivna funkcija
quickSort( ). Ovaj algoritam se može realizovati na više načina s obzirom na razne
mogućnosti izbora pivota. Dati primer rekurzivne funkcije predstavlja najjednostavniju
implementaciju u kojoj se u svakom rekurzivnom pozivu bira prvi, početni, element za ulogu
pivota u svakom podpolju koga treba sortirati. I ovog puta koristimo funkciju change za
zamenu vrednosti dva elementa. Da bi se sortiralo polje a[ ] dužine n, glavni program mora
pozvati quickSort( ) sa argumentima: quickSort(a,0,n-1).
void quickSort(int a[], int l, int r) {
int i,j;
if (l>=r) return;
i = l+1; /* razvrstavanje elemenata s obzirom na pivot */
j = r;
while ((i <= j) && (i<=r) && (j>l)) {
while ((a[i] < a[l]) && (i<=r)) i++;
while ((a[j] > a[l]) && (j>l)) j--;
if (i<j)
change(&a[i], &a[j]);
90
}
if (i>r) { /* pivot je najveci u polju */
change(&a[r], &a[l]);
quickSort(a, l, r-1);
}
else if (j<=l) { /* pivot je najmanji u polju */
quickSort(a, l+1, r);
}
else { /* pivot je negdje u sredini */
change(&a[j], &a[l]);
quickSort(a, l, j-1);
quickSort(a, j+1, r);
}
}
Efikasnost algoritma brzog sortiranja izvršićemo analizom vremenske složenosti.
Rezultati ove analize su:
• Algoritam brzog sortiranja u najgorem slučaju, kada je pivot početni elemenat
polja i kada je polje već sortirano, ima složenost '��� .
• Može se pokazati matematičkim dokazom da je prosečno vreme izvršavanja
algoritma '�� # (�)�
• Ponašanje algoritma u priličnoj meri zavisi od načina biranja pivota. Najčešće
korišćena mogućnost je izabrati početni element polja kao pivot, zatim, pivot
može biti medijana između tri elemenata koji se nalaze na početku, kraju
odnosno sredini polja
• Praktična primena ovog algoritma pokazuje da je on izuzetno brz, najbrži od
svih poznatih algoritama. Brži je nego što se to može prepoznati teoretskom
estimacijom vremena izvršenja.
7.5 Višestruko sortiranje umetanjem (Shell sort)
Shellovo sortiranje radi tako da sortira u većim koracima koji se postupno smanjuju na
korak od jedne pozicije, ali do tada je niz već gotovo sortiran, pa je i sortiranje umetanjem (ili
zamenom susednih elemenata) efikasnije.
91
Za realizaciju algoritma višestrukog sortiranja umetanjem potrebno je od originalnog
polja formirati k različitih podpolja. Podpolja se dobijaju od originalnog polja tako što se
uzmu elementi koji su međusobno udaljeni za k mesta. Preciznije, za dati k dobijaju se
podpolja:
P0: a[0], a[k], a[2k], ....
P1: a[1], a[k+1], a[2k+1], ....
.....
.....
Pk-1: a[k-1], a[2k-1], a[3k-1], ....
Proces k-struke primene sortiranja umetanjem za potrebe posebnog sortiranja svakog od
ovih k podpolja naziva se k-subsort.
Algoritam višestrukog sortiranja umetanjem (shell sort) radi tako da za definisani
opadajući niz k1 > k2 > ... > km = 1 obavi k1-subsort, zatim k2-subsort, ... , na kraju km -subsort.
Poslednji km –subsort je ustvari 1-subsort i realizuje obično sortiranje umetanjem na celom
originalnom polju. Prethodni k-subsortovi služe zato da (radeći na kratkim podpoljima)
donekle sortiraju celo polje tako da idući k-subsortovi imaju sve manje posla.
Jedan primer algoritma višestrukog sortiranja umetanjem je dat na sledećoj slici. U
primeru je dat opadajući niz k-ova, 4>2>1. Istom bojom su, u svakom redu, označeni elementi
koji čine u okviru k-tog subsorta, jedno podpolje.
Početno polje 17 31 3 43 11 24 8
Ulaz za 4-subsort 17 31 3 43 11 24 8
Izlaz iz 4-subsorta 11 24 3 43 17 31 8
Ulaz za 2-subsort 11 24 3 43 17 31 8
Izlaz iz 2-subsorta 3 24 8 31 11 43 17
Ulaz za 1-subsort 3 24 8 31 11 43 17
Izlaz iz 1-subsorta 3 8 11 17 24 31 43
Ideja Shellovog sortiranja možemo pokazati i na drugi način: prvo se od niza podataka
kreira dvodimenzionalno polje gde je broj kolona definisan izborom k, a zatim se sortiraju
kolone. Time se dobije delimično sortirano polje.
92
Proces se ponavlja tako da u svakom koraku polje ima sve manje kolona, u zadnjem
koraku ostaje samo jedna kolona u kojoj su podaci sortirani. Svakim korakom sortiranost niza
je sve veća.
Broj operacija sortiranja u svakom koraku je ograničen i manji, jer je niz već delimično
sortiran u prethodnim koracima. Prethodni primer za k-ove 4>2>1 je prikazan na sledećoj
slici. Najpre je originalno polje transformisano u dvodimenzionalno polje sa 4 kolona (slika a)
i svaka od tih kolona je sortirana (slika b), zatim je tako dobijeno polje transformisano u
dvodimenzionalno polje sa 2 kolone (slika c) i te dve kolone sortirane u rastući niz (slika d).
Konačno, formirano je polje od 1 kolone (slika e) koje se sortira u rastući niz (slika f)
17 31 3 43 ⟹ 11 24 3 43
11 24 8 17 31 8
(a) (b)
11 24 3 24
3 43 ⟹ 8 31
17 31 11 43
8 17
(c) (d)
3 3
24 ⟹ 8
8 11
31 17
11 24
43 31
17 43
(e) (f)
93
Implementacija višestrukog sortiranja umetanjem (Shell sort-a) u jeziku C može se
dobiti modifikacijom implementacije sortiranja umetanjem tako što dodajemo još jednu petlju
koja odgovara odabranom nizu k-subsortova. Prikazana funkcija ShellSort ( ) koristi niz k-ova
oblika k1=n/2, k2=n/4, ... km=1.
void ShellSort (int a[], int n) {
int i, j, step;
int aux;
for (step = n/2; step > 0; step /= 2) {
for (i = step; i < n; i++) {
aux = a[i];
for (j = i; j >= step && a[j-step] > aux; j -= step)
a[j] = a[j-step];
a[j] = aux;
}
}
}
Analiza vremenske složenosti koja nam može dati efikasnost algoritma višestrukog
sortiranja (Shell sort) je u ovom slučaju veoma teška i predstavlja nepoznanicu za istraživače.
Naime, za ovaj algoritam još uvek ne postoje jasne i potpune ocene vremenske složenosti tako
da je prosečno vreme izvođenja nerazrešen problem. Međutim, eksperimentalna merenja
pokazuju da je algoritam izuzeno brz, brži nego što to pokazuju teoretske ocene vremenske
složenosti.
94
8 PRETRAŽIVANJE
Jedan od vrlo čestih zadataka u programiranju je pretraživanje. Pod pretaživanjem se
podrazumeva provera da li se zadata vrednost pojavljuje u nekoj kolekciji vrednosti i njeno
izdvajanje. Efikasnost pretraživanja uglavnom se meri prosečnim brojem poređenja koje je
potrebno izvesti u postupku traženja različitih vrednosti u datoj kolekciji i zbog najčešće
velikog broja poređenja, takvi algoritmi treba da budu vrlo efikasni. U narednim
podpoglavljima objasnićemo nekoliko različitih algoritama pretraživanja, kao što su
sekvencijalno, binarno, pretraživanje korišćenjem binarnih stabala
8.1 Sekvencijalno pretraživanje
Definišimo najpre objekat nad kojim se vrši pretraživanje, to je proizvoljni niz koji u
opštem slučaju nije uređen. Sekvencijalno pretraživanje kolekcija podrazumeva da se
pretraživanje obavlja tako što se tražena vrednost poredi redom sa svim elementima niza,
počev od prvog. Pretraživanje se prekida onog trenutka kada se pronađe vrednost jednaka
traženoj, ili se stigne do kraja niza. Tako će funkcija kojom se pretražuje imati zapis:
int sekv_pret (int an, int te, int ae[]) {
int i;
i = 0;
while (i < an) i++;
if (ae[i] == te) return(i);
return(-1);
}
Ako bismo govorili o složenosti, ovaj algoritam je dodatno usložnjen dodavanjem
uslova za izlazak iz petlje (i<an). Popravka ovog algoritma postiže se tako što se niz
produžava još jednim (lažnim) elementom jednakim traženom elementu. Nakon toga, za
95
izlazak iz petlje neće biti potrebno testiranje da li je brojač i dostigao ukupan broj elemenata
(kraj niza). Tako dobijamo funkciju:
int sekv_pret (int an, int te, int ae) {
int i;
ae[an] = te;
i = 0;
while (ae[i] != te) i++;
if (i < an) return(i)
else return(-1);
}
8.2 Binarno pretraživanje
Slučaju da imamo kolekciju po kojoj pretražujemo i koja predstavlja sortirani niz,
možemo primeniti drugi algoritam pretraživanja, tzv. binarno pretraživanje. Kod ove vrste
pretraživanja postupak se može skratiti jer se pretraživanje obavlja polovljenjem niza,
odnosno dela niza u kome se traži zadata vrednost.
Prvi korak je da zadatu vrednost tražimo u okviru celog niza (od prvog do poslednjeg
elementa) tako što izdvajamo srednji element tog niza i poredimo ga sa traženom vrednošću
(ako je broj elemenata niza paran, izdvajamo levi od dva srednja elementa). U slučaju da je
tražena vrednost jednaka srednjem elementu, pretraživanje je okončano. Ako je tražena
vrednost manja od vrednosti srednjeg elementa, onda se ona može nalaziti samo u levoj
polovini niza. U suprotnom, tražena vrednost se nalazi u desnoj polovini. Ovakav postupak se
ponavlja u onom delu niza koji se pretražuje. Algoritam binarnog pretraživanja se prekida
onog trenutka kada:
• srednji element i tražena vrednost se poklapaju, ili
• deo niza u okviru koga tražimo vrednost je prazan.
Tako dobijamo funkciju:
int bin_pret (int an, int te, int ae[]) {
int d, g, s;
d = 0; g = an-1;
while (d <= g) {
s = (d+g)/2;
if (ae[s] == te) return (s);
if (ae[s] < te) d = s+1;
else g = s-1;
}
return (-1) ;
}
96
Binarno pretraživanje možemo modifikovati tako da se, umesto dva indeksa (donja i
gornja granica za deo niza po kome se vrši pretraživanje), koristi samo jedan indeks. Naime,
umesto donje i gornje granice možerno računati sredinu (centar) i poluprečnik dela niza po
kome pretražujemo.
8.3 Binarno stablo za pretraživanje
Binarno stablo za pretraživanje treba da ima sledeća svojstva:
• Čvorovima binarnog stabla pridružene su vrednosti iz kolekcije po kojoj se
obavlja pretraživanje.
• Za bilo koji čvor datog stabla važi:
o sve vrednosti pridružene čvorovima u levom podstablu stabla sa
korenom u tom čvoru su manje ili jednake vrednosti pridruženoj datom
čvoru;
o sve vrednosti pridružene čvorovima desnog podstabla stabla sa
korenom u tom čvoru su veće od vrednosti pridružene datom čvoru.
Čvorove binarnog stabla predstavljamo pomocu strukture koja sadrži:
• polje u kome se nalazi informacija pridružena datom čvoru (korenu) i
• polja koja dati čvor vezuju sa njegovim naslednicima, odnosno podstablima:
struct drvo {
int sad;
struct drvo *ldr, *ddr;
};
Nekad je za rad zgodno da osim polja koja vezuju čvor sa njegovim naslednicima
imamo i polje koje dati čvor vezuje sa njegovim prethodnikom. Tada bi struktura ovako
izgledala:
struct drvo {
int sad;
struct drvo *pdr, *ldr, *ddr;
};
U svrhu pretraživanja potrebno je za pretraživanu kolekciju konstruisati binarno stablo
za pretraživanje. To se postiže dodavanjem jednog po jednog elementa niza u binarno stablo
na odgovarajuće mesto, tako da nakon dodavanja svakog pojedinačnog elementa i dalje budu
zadovoljena sva svojstva stabla za pretraživanje.
Primer binarnog stabla za pretraživanje je prikazan na Slika 8.3-1
97
Slika 8.3-1 Binarno stablo za pretraživanje
Binarno stablo za pretraživanje je u osnovi binarno stablo, tako da se može obići u
inorder, preorder ili postorder redosledu. Ukoliko binarno stablo za pretraživanje obiđemo u
inorder redosledu i pri tome odštampamo vrednosti u čvorovima, dobićemo vrednosti
sortirane u rastućem redosledu.
Binarno stablo za pretraživanje je veoma važna struktura podataka. Posmatrajmo, na
primer, problem pretraživanja niza. Ukoliko je niz sortiran, pretraživanje možemo znatno
ubrzati korišćenjem binarnog pretraživanja. Međutim, ukoliko želimo da izvršimo promene u
nizu kao što su dodavanje i brisanje elementa, to će zahtevati pomeranje određenog broja
elemenata svaki put. Ovaj problem možemo rešiti korišćenjem povezanih lista, zato što one
omogućavaju dodavanje i brisanje elemenata vrlo jednostavnim premeštanjem nekoliko
pokazivača. Međutim, problem sa povezanim listama je to što one ne omogućavaju direktan
pristup pojedinim elementima, već samo sekvencijalno kretanje kroz listu, element po
element. Rešenje ovih problema leži upravo u binamim stablima. Ukoliko se elementi
uređenog niza ili liste smeste u čvorove binarnog stabla za pretraživanje, nalaženje
odgovarajućeg ključa u binamom stablu zahteva 0(logn) koraka.
8.4 Kreiranje binarnog stabla za pretraživanje
Pretpostavimo da svaki čvor binarnog stabla sadrži celobrojni podatak, kao i pokazivače
na levo i desno podstablo. U tom slučaju struktura koja opisuje čvor binarnog stabla bi mogla
da izgleda ovako:
struct cvor
{
int podatak;
struct cvor *levi,*desni;
};
98
Za kreiranje binarnog stabla za pretraživanje treba koristiti funkciju koja kreiraju novi
čvor, dodeljuje mu prosleđenu vrednost i dodaje ga u postojeće stablo. Prva provera koju
takva funkcija obavlja jeste provera da li je stablo prazno. Ukoliko jeste, novi čvor se dodaje
kao koren stabla. Ako stablo nije prazno otpočinje se sa kretanjem kroz stablo korišćenjem
pomoćnog pokazivača. Podatak u trenutnom čvoru upoređuje se sa novom vrednošću. U
slučaju 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 vrši sve
do trenutka dok se ne dođe do kraja stabla, odnosno dok pokazivač na odgovarajuće dete nije
NULL. Sve vreme kretanja čuva se pokazivač na roditeljski čvor, kako bi se na njega na kraju
dodao novi čvor 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 veća od vrednosti poslednjeg
čvora.
U glavnom programu zadaje se broj čvorova, kao i vrednosti u njima. Unete vrednosti
se dodaju u drvo korišćenjem prethodno opisane funkcije. Na kraju se vrši štampanje čvorova
stabla tokom obilaska stabla u inorder redosledu.
8.5 Pretraživanje u binarnom stablu za pretraživanje
Pretraživanje u binarnom stablu predstavlja proces u kome se traži čvor u stablu, koji
zadovoljava unapred definisane kriterijume. Najčešće je to pretraživanje u cilju nalaženja
čvora koji sadrži određeni podatak koji nazivamo ključ.
Da bismo pronašli određeni ključ u datom binarnom stablu za pretraživanje, krećemo od
korena stabla i upoređujemo ključ sa podatkom u čvoru. Ukoliko su ključ i podatak jednaki,
funkcija vraća 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 pronađe traženi čvor ili kada je podstablo koje posmatramo
prazno. Ukoliko je posmatrano podstablo prazno, funkcija vraća NULL, kao znak da traženi
čvor nije pronađen.
8.5.1 Određivanje 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 uvećava za jedan kako bi se uračunao i koren stabla.
Ukoliko je stablo list (nema potomaka), onda je broj
ukazuje na potrebu rekurzivnog prolaska
8.5.2 Zamena mesta levim i desnim podstablima
Elegantan metod za zamenu mesta levim i desnim podstablima unutar binarnog stabla je
korišćenje rekurzivnog algoritma. Funkcija zamenjuje m
na njima rekurzivno primenjuje isti postupak.
Primenom ovog algoritma na binarno stablo za pretra
dalo rastući niz, dobilo bi se binarno stablo koje bi pri inorder štampanju dalo
8.6 Umetanje vrednosti u binarno
Ako je element koji se ume
umeće u levo podstablo; a ako je ve
podstablo, do trenutka kada pod
postoji). Tada formiramo drvo koje se sastoji samo od jednog
pridružena vrednost koju dodajemo u
smo prošli neposredno pre toga.
Na Slika 8.6-1 prikazan je postupak umetanja broja 13 u binarno
Kao što se vidi, u toku tog umetanj
vrednosti 12, 18 i 15. Od čvora kome je pridružena vrednost 15, skre
13<15). Kako taj čvor trenutno nema levog naslednika, dodajemo novi
pridružujemo vrednost 13 i koji č
dobijeno stablo zadržava sva svojstva binarnog
99
potomaka), onda je broj čvorova u njemu jednak jedan. Ovaj opis
ebu rekurzivnog prolaska kroz stablo sve dok se ne dođe do njegovih listova.
Zamena mesta levim i desnim podstablima
Elegantan metod za zamenu mesta levim i desnim podstablima unutar binarnog stabla je
rekurzivnog algoritma. Funkcija zamenjuje mesta levom i desnom podstablu, a zatim
primenjuje isti postupak.
Primenom ovog algoritma na binarno stablo za pretraživanje, koje bi pri inorder štampanju
dobilo bi se binarno stablo koje bi pri inorder štampanju dalo opadaju
Umetanje vrednosti u binarno stablo za pretraživanje
Ako je element koji se umeće u stablo manji ili jednak vrednosti u korenu drveta, on se
; a ako je veći, u desno. Postupak se ponavlja za odgovaraju
trenutka kada podstablo u koje treba umetnuti element ne postane prazno (ne
postoji). Tada formiramo drvo koje se sastoji samo od jednog čvora (koren).
pridružena vrednost koju dodajemo u stablo i to podstablo se povezuje sa čvorom kroz koji
rošli neposredno pre toga.
prikazan je postupak umetanja broja 13 u binarno stablo
Kao što se vidi, u toku tog umetanja proći ćemo kroz čvorove kojima su pridružene redom
čvora kome je pridružena vrednost 15, skrećemo levo (zato što je
čvor trenutno nema levog naslednika, dodajemo novi
pridružujemo vrednost 13 i koji če biti levi naslednik. Time je vrednost 13 umetnuta u drvo, a
zadržava sva svojstva binarnog stabla za pretraživanje.
Slika 8.6-1
vorova u njemu jednak jedan. Ovaj opis
đe do njegovih listova.
Elegantan metod za zamenu mesta levim i desnim podstablima unutar binarnog stabla je
esta levom i desnom podstablu, a zatim
živanje, koje bi pri inorder štampanju
opadajući niz.
manji ili jednak vrednosti u korenu drveta, on se
i, u desno. Postupak se ponavlja za odgovarajuće
u koje treba umetnuti element ne postane prazno (ne
čvora (koren). Čvoru je
se povezuje sa čvorom kroz koji
za pretraživanje.
vorove kojima su pridružene redom
ćemo levo (zato što je
vor trenutno nema levog naslednika, dodajemo novi čvor kome
biti levi naslednik. Time je vrednost 13 umetnuta u drvo, a
100
8.7 Brisanje čvora iz binarnog stabla za pretraživanje
Prikažimo i postupak kojim se neka vrednost briše iz binarnog stabla za pretraživanje.
To se obavlja tako što se prvo pronađe čvor kome je pridružena vrednost.
Ako dati čvor ima najviše jednog naslednika, onda se taj naslednik vezuje sa njegovim
prethodnikom.
Ako dati čvor ima oba naslednika, onda se tom čvoru pridružuje informacija iz čvora
koji ima najviše jednog naslednika, a potom se taj čvor briše. Medutim, da bi se zadržala sva
svojstva stabla za pretraživanje, taj čvor koji brišemo ne može biti proizvoljno izabran.
Naime, stablo mora zadržati svojstva binarnog stabla za pretraživanje, odnosno nova vrednost
koju pridružujemo mora biti veća (ili jednaka) od svih vrednosti iz levog podstabla, i strogo
manja od vrednosti iz desnog podstabla. Da bismo to postigli, nova vrednost koju upisujemo u
pronađeni čvor je najmanja vrednost iz njegovog desnog podstabla. Do čvora sa najmanjom
vrednošću u nekom stablu za pretraživanje stiže se tako što se krećemo od prethodnika ka
levom nasledniku dok god je to moguće (znači, dok čvor u kome se nalazimo ima levog
naslednika).
Označimo pokazivač na čvor koji želimo da obrišemo sa x (skraćeno: čvor x), a
pokazivač na čvor koji je njegov roditelj sa y. Nakon brisanja čvora x, potrebno je izvršiti
reorganizaciju njegovih potomaka kako bi oni i dalje formirali binarno stablo za pretraživanje,
a zatim novoformirano podstablo povezati na odgovarajući način sa čvorom y, u zavisnosti od
toga da li je čvor x bio levi ili desni potomak čvora y. U slučaju da je čvor x bio koren stabla,
onda podstablo formirano od njegovih potomaka postaje novi koren. Označimo pokazivač na
podstablo formirano od potomaka čvora x sa q.
8.7.1 Brisanje čvora koji ima dva potomka
Posmatrajmo binarno stablo prikazano na Slika 8.7-1
Slika 8.7
Korišćenjem pomoćnog pokaziva
bismo pronašli njegov desni list, a zatim postavljamo desni pokaziva
desno podstablo čvora x, kao što je pokazano na
pokazuje na levo podstablo čvora
ostaje samo da se pokazivač q postavi za
jeste NULL (obrisan je koren), onda novi koren
Slika 8.7-
Drugi način brisanja čvora je da se prolazi kroz desno podstablo
pronašao njegov levi list, a zatim se levi pokaziva
podstablo čvora x, kao što je prikazano na
čvor x iz memorije. Nakon toga, pokaziva
čvora x, a čvor x se briše iz memorije. Ukoliko pokaziva
101
8.7-1 Binarno stablo pre brisanja čvora na koji pokazuje x
ćnog pokazivača pom, prolazimo kroz levo podstablo
njegov desni list, a zatim postavljamo desni pokazivač ovog lista da pokazuje na
kao što je pokazano na Slika 8.7-2. Nakon toga, pokazivač
čvora x, a čvor x se briše iz memorije. Ukoliko pokazivač
postavi za odgovarajućeg potomka čvora y. Ako pokazrva
koren), onda novi koren postaje pokazivač q.
-2 Binarno stablo nakon brisanja čvora na koji pokazuje x
čvora je da se prolazi kroz desno podstablo čvora
pronašao njegov levi list, a zatim se levi pokazivač tog lista postavlja da pokazuje na levo
kao što je prikazano na Slika 8.7-3. Naravno, na kraju je potrebno obrisati
iz memorije. Nakon toga, pokazivač q se postavlja da pokazuje na desno podstablo
se briše iz memorije. Ukoliko pokazivač y nije NULL, ostaje samo da se
prolazimo kroz levo podstablo čvora x, kako
č ovog lista da pokazuje na
pokazivač q se postavlja da
se briše iz memorije. Ukoliko pokazivač y nije NULL,
vora y. Ako pokazrvač na čvory
x
čvora x kako bi se
tog lista postavlja da pokazuje na levo
. Naravno, na kraju je potrebno obrisati
se postavlja da pokazuje na desno podstablo
y nije NULL, ostaje samo da se
pokazivač q postavi za odgovar
(obrisan je koren), onda novi koren postaje pokaziva
Slika 8.7-
8.7.2 Brisanje čvora koji ima jednog potomka
Posmatrajmo binarno stablo prikazano na
Slika 8.7
Ukoliko želimo da obrišemo
na podstablo čvora x koje postoji, a zatim iz memorije obrišemo
na Slika 8.7-5. Ukoliko pokaziva
odgovarajućeg potomka čvora y. Ako pokaziva
onda novi koren postaje pokaziva
102
postavi za odgovarajućeg potomka čvora y. Ako pokazivač na čvor y jeste NULL
(obrisan je koren), onda novi koren postaje pokazivač q.
-3 Binarno stablo nakon brisanja čvora na koji pokazuje x
ima jednog potomka
Posmatrajmo binarno stablo prikazano na Slika 8.7-4
8.7-4 Binarno stablo pre brisanja čvora na koji pokazuje x
želimo da obrišemo čvorx, dovoljno je da postavimo pokazivač
koje postoji, a zatim iz memorije obrišemo čvor x, kao što je prikazano
. Ukoliko pokazivačy nije NULL, ostaje samo da se pokazivač
čvora y. Ako pokazivač na čvory jeste NULL (obrisan je koren),
onda novi koren postaje pokazivač q.
č čvor y jeste NULL
x
vorx, dovoljno je da postavimo pokazivač q da pokazuje
x, kao što je prikazano
y nije NULL, ostaje samo da se pokazivač q postavi za
vory jeste NULL (obrisan je koren),
Slika 8.7-
8.7.3 Brisanje čvora koji nema ni jednog potomka
Posmatrajmo binarno stablo na
Slika 8.7
Da bismo obrisali čvor x
NULL, a zatim, ukoliko pokaziva
odgovarajućeg potomka čvora
onda novi koren postaje pokaziva
Slika 8.7-
103
-5 Binarno stablo nakon brisanja čvora na koji pokazuje x
Brisanje čvora koji nema ni jednog potomka
Posmatrajmo binarno stablo na Slika 8.7-6:
8.7-6 Binarno stablo pre brisanja čvora na koji pokazuje x
x iz binarnog stabla, potrebno je samo da pokazivač
pokazivač y nije NULL, ostaje samo da se pokazivač
čvora y. Ako pokazivač na čvor y jeste NULL (obrisan je koren),
onda novi koren postaje pokazivač q.
-7 Binarno stablo nakon brisanja čvora na koji pokazuje x
x
binarnog stabla, potrebno je samo da pokazivaču q dodelimo
y nije NULL, ostaje samo da se pokazivač q postavi za
jeste NULL (obrisan je koren),
vora na koji pokazuje x
104
8.8 Pretraživanje po binarnom stablu za pretraživanje
Najzad, možemo ispisati i funkciju kojom proveravamo da li data vrednost postoji u
binarnom stablu za pretraživanje. To obavljamo tako što traženu vrednost poredimo sa
vrednošću pridruženom korenu. Ako su vrednosti jednake, postupak je okončan. Ako je
tražena vrednost manja, onda se na osnovu svojstava stabla za pretraživanje može nalaziti
samo u levom podstablu. U suprotnom, tražena vrednost je u desnom podstablu. Postupak
ponavljamo za izabrano podstablo. Prekidamo ga u slučaju pronalaženja tražene vrednosti ili
onda kada izabrano podstablo postane prazno.
105
9 Literatura
(1) S.Đorđević-Kajan, L.Stojmenov,A.Dimitrijević : STRUKTURE PODATAKA U
JEZIKU C++, Praktikum, Elektronski fakultet Niš, 2005.
(2) A.Aho,J.Hopcroft, J.Ulman: DATA STRUCTURES AND ALGORITHMS, Addison-
Wesley, Reading, MA,1983
(3) M.Weiss: DATA STRUCTURES AND PROBLEM SOLVING USING C++,
Addison-Wesley, 2000
(4) R.Manger, M.Marušić: STRUKTURE PODATAKA I ALGORITMI, Skripta,
Prirodoslovno Matematički Fakultet, Zagreb, 2007.
(5) A.Drozdek: DATA STRUCTURES AND ALGORITHMS IN C++, Books Cole, 2nd
Edition, 2000.
(6) D.Urošević: ALGORITMI U PROGRAMSKOM JEZIKU C, Mikro knjiga, Beograd,
2003.
(7) B.Stojanović: STRUKTURE PODATAKA I ALGORITMI 2, Radni materijali,
Tehnički fakultet, Kragujevac