Programski Jezici I Strukture Podataka - Dusan Malbaski

You might also like

Download as doc or pdf
Download as doc or pdf
You are on page 1of 112

FAKULTET TEHNIČKIH NAUKA

UNIVERZITETA U NOVOM SADU

1
Semestar
Elektrotehnika i računarstvo
Odsek za računarstvo i automatiku

prof. dr Dušan Malbaški 02 ESE2 501

Programski jezici
i strukture
podataka

1
P R O F. D R D U Š A N M A L B A Š K I , T M D 1 4 5

Programski jezici i strukture podataka

UNIVERZITET U NOVOM SADU


Fakultet tehničkih nauka
Elektrotehnika i računarstvo
Odsek za računarstvo i automatiku

Šifra predmeta: 02 ESE2 501


Semestar: I
Predavanja u semestru/u nedelji: 60 / 4
Vežbi u semestru/u nedelji: 10N+50C / 4
Asistenti: mr Branko Markoski, TMD 9A
Žarko Ivanov, TMD 15A

LITERATURA:
O'Brian S.: Turbo Pascal 6.0, Mikro Knjiga, Beograd, 1991. (ili ekvivalent)
Malbaški D., Obradović D.: Osnovne strukture podataka, UNS, 1995.
Hotomski P., Malbaški D.: Matematička logika i principi programiranja, UNS, 2000.
Malbaški D.: Odabrana poglavlja metoda programiranja, UNS, 2002.
Sadržaj
UVOD

Uvod Error! Bookmark not defined.

Alfabet Pascala 2

TIPOVI PODATA KA

Tipovi podataka 4

Hijerarhija operatora 5

Logički tip 5

Celobrojni tip 6

Realni tip 7

Znakovni tip 8

String 8

Enumeracija 9

Intervalni tip 9

Nizovi 10

Skupovi 11

Slog 12

Datoteke 13

Primer 18

STRUK TUR A PROG RAM A

Opšta struktura programa 22

Zaglavlje 22

Deklaracije 23

Algoritamski deo 24

NARED BE

Naredba dodele 26

Složena naredba (sekvenca) 26

Naredbe selekcije 26

Petlje 28

Naredbe skoka 29

Elementarni ulaz/izlaz 30

M ODUL I

Potprogrami 31

Moduli 35

Šta se nalazi u modulu 37

Jedinice u Turbo Pascalu 37

Pascalovi gotovi uniti 39


Primer 39
1
Tema

1
D E S I G N C U S T O M I Z A T I O N

Programski jezik Pascal


U ovom delu ćemo obraditi osnove programskog jezika
Pascal, sa posebnom pažnjom na Turbo Pascal.
Bavićemo se tipovima podataka u Turbo Pascalu, a
spomenućemo i opštu strukturu pascalskih programa,
neke osnovne naredbe i rad sa potprogramima.

P askal se pojavio 1969. Njegov autor je Švajcarac Niklaus Wirth, a


ime je dobio po Francuzu Blezu Pascalu, izumitelju prve mašine za
računanje. Nastao je posle prve velike softverske krize koja je
nastala zbog toga što tadašnji softver nije mogao da zadovolji potrebe
korisnika i iskoristi mogućnosti hardvera. Pascal je nastao na bazi
programskog jezika ALGOL (ALGOrhitmic Language) tako što je
preuzeta većina komandi (neke su odbačene), a uvedene su nove strukture
podataka. Inače, Pascal nije prvobitno pisan za izvršavanje na računaru,
već za prikazivanje programa, tj. imao je edukativnu ulogu.

Pascal je standardizovan programski jezik što znači da postoji neka


osnovna struktura koja je ista za sve verzije ovog programskog jezika i
stoga se program pisan za jednu verziju uz manje izmene može izvršavati
na računaru sa nekom drugom verzijom Pascala. Zbog toga, osnovna
svrha Pascala kakav je on sad je pisanje čitljivih i razumljivih programa.
Takav program se lako ispravlja i modifikuje, a takođe ga nije potrebno
posebno dokumentovati, jer je sam program prilično razumljiv. Pascal je
prvi programski jezik koji ima takvu strukturu da je omogućio pisanje
programa bez upotrebe skokova.

Četiri aspekta koje treba razjasniti prilikom programiranja


1. Kakvim tipovima podataka raspolažemo?

2. Kakvim upravljačkim strukturama raspolažemo?

3. Kako se organizuje ulaz i izlaz?

4. Kako se vrši modularizacija (upotreba procedura, funkcija i


modula)?
P R O G R A M S K I J E Z I K P A S C A L


Alfabet Pascala
Skup simbola koji se koriste u programskom jeziku naziva se alfabet
programskog jezika.

Pascal je veštački jezik i stoga poseduje strogo definisan skup simobla koji
se smeju koristiti.

U alfabet Pascala spadaju:

 slova engleske abecede (karakteri), bez razlike velikih i malih


slova i donja crta _

 cifre od 0 do 9

 specijalni znaci (+, =, :, -, *, :=, <= itd.)

Skup simbola koji se koriste u programskom jeziku naziva se alfabet


programskog jezika.

Pascal program ima slobodan format, što znači da ne postoje striktna


pravila o rasporedu komandi u tekstu programa. Ali zbog toga mora da
postoji rečnik programskog jezika (sadrži rezervisane reči).

U programu se indikatorima jednoznačno identifikuju promenljive,


konstante, tipovi i potprogrami. Identifikatori se izgrađuju poštujući
sledeća pravila:

 u identifikator mogu samo da uđu slova, cifre i donja crta;

 identifikator mora da počne slovom;

 postoji maksimalna dužina identifikatora koja zavisi od


programskog jezika.

Identifikatori koji imaju semantiku treba da imaju mnemoniku.

To znači da ako identifikator predstavlja npr. neku realnu veličinu,


njegovo ime treba da asocira na tu veličinu (npr. sila, masa itd.). Postavlja

3
P R O G R A M S K I J E Z I K P A S C A L

Dobra upotreba
identifikatora eliminiše
najveći deo potrebe za
komentarima.
se pitanje da li treba koristiti englesku mnemoniku ili mnemoniku
maternjeg jezika. Engleski jezik ima drugačiju strukturu od srpskog, tako
da je engleska mnemonika kraća. Takođe, naredbne programskog jezika
su na engleskom, ali postoji ograničenje u vidu dovoljnog poznavanja
stranog jezika.

Naredbe se uvek razdvajaju separatorom. U Pascalu to je tačkazarez:


naredba1; naredba2;

Komentar je slobodni tekst čija je svrha da razjasni potencijalno nejasne


delove koda. U Pascalu, se komentari umeću između vitičastih zagrada:
{ovo je komentar}

4
Tipovi podataka
Kad je Pascal nastao, prava inovacija koju je on doneo bila je u domenu
tipova podataka. Ranije je postojao mali broj tipova i nije bilo moguće da
programer kreira svoj sopstveni.

U Pascalu postoji određeni broj ugrađenih tipova na osnovu kojih gradimo


sopstvene tipove. Treba voditi računa da izgrađeni tip što vernije i jasnije
odražava ono na šta se odnosi.

tipovi podataka

osnovni (skalarni)
izvedeni (strukturirani)

standardni niz
nestandardni
deo su programskog jezika, na
njih programer nema uticaja
koje programer sam pravi skup
slog

logički (Bulov) enumeracija

datoteka
celobrojni interval

realni

znakovni

string

pokazivač

Tipovi podataka

Svi osnovni tipovi u Pascalu imaju identifikator. A u sastav tipa ulaze


vrednosti i operacije.
P R O G R A M S K I J E Z I K P A S C A L


Ovaj tip ima dve Važno!
logičke vrednosti: false < true
tačno i netačno.

Hijerarhija operatora
Pošto u izrazu figurišu promenljive, konstante, operatori i funkcije, mora
postojati redosled izvođenja operacija. Postoje određene razlike u odnosu
na ovu hijerarhiju u matematici.

Redosled je sledeći:

zagrade: ( i );
funkcije;
operator not;
operatori: *, /, div, mod i and;
operatori +, -, or i
relacioni operatori: =, <>, >, >=, <, <= i operator in
Ukoliko se desi da su operatori na istom nivou prioriteta, onda se
primenjuje pravilo „s leva na desno“.

Logički tip
Njegov identifikator je: Boolean. Zbog nemogućnosti da se u Pascalu
koriste matematičke oznake za tačno i netačno (T i ), uvedene su logičke
konstante koje su dobile posebna imena. To su true i false.

Logičke operacije
Postoje tri osnovne logičke operacije u Pascalu. To su konjunkcija,
disjunkcija i neegacija. U tabeli su upoređene matematičke i Pascalove oznake
tih funkcija.

operacija u u
matematici Pascalu
konjunkcija  and
disjunkcija  or
negacija  not

Relacioni operatori
U Pascalu ne postoje relacije kao u matematici. Postoje relacioni operatori,
pa se relacije u stvari tretiraju kao operacije koje imaju rezultat.

Uz podatke logičkog tipa mogu se koristiti sledeći relacioni operatori:

operato značenje
r
= jednako

6
P R O G R A M S K I J E Z I K P A S C A L

operato značenje
r
<> nije jednako
> veće
>= veće ili jednako
< manje
<= manje ili
jednako

Upotrebom relacionih operatora mogu se iskazati i sledeće složene matematičke


relacije:

operacija u u
matematici Pascalu
implikacija  p<=q
ekvivalencija  p=q
ekskluzivna
 p<>q
disjunkcija

Celobrojni tip
Ovaj tip obuhvata familiju tipova, ali osnovni je integer. U Pascalu se tip
promenljive određuje zavisno od toga koji raspon promenljiva zauzima u
modelu.

tip opseg
integer od -32 768 do 32 767 2B
shortint od -128 do 127 1B
longint od oko -2,14∙109 do 2,14∙109 4B
byte od 0 do 255 1B
word od 0 do 65 535 2B
Operacije
Operacije koje možemo vršiti sa podacima celobrojnog tipa su: sabiranje
(+), oduzimanje (-), množenje (*), deljenje (/), celobrojno deljenje (div) i
ostatak pri deljenju (mod). Rezultat deljenja je uvek realan broj bez obzira
što delimo cele brojeve, a ako želimo da deljenjem dobijemo ceo broj,
koristićemo operator div. Treba voditi računa da operator div samo odbaci
brojeve iza decimalne tačke i na taj način formira ceo broj. Tako dobijamo
da je 9 div 10 = 0 iako bi matematičkim zaokruživanjem dobili 1.

Funkcije
Funkcije kojima raspolažemo kada obrađujemo podatke celobrojnog tipa
su: apsolutna vrednost (abs), kvadrat broja (sqr), neparnost (odd),
sledbenik (succ) i prethodnik (pred).

7
P R O G R A M S K I J E Z I K P A S C A L


Tipovi byte i word
Ovi tipovi nemaju ulogu da modeliraju cele brojeve. Naime, u njihovom
registru ne postoji mesto za predznak, pa se zbog toga svi bitovi jednako
tretiraju. Ovi tipovi prvenstveno služe za operacije nad bitovima ćelije.

Da bi sadržaj ćelije po bitovima bio vidljiv programeru, cele brojeve


možemo lakše prikazati u obliku heksadecimalnog zapisa, tako što ćemo
ispred zapisa staviti znak $ koji prevodiocu označava da je u pitanju
heksadecimalni podatak. Na primer:
$7A2C

Nepisano je pravilo da se koriste velika slova za brojeve od A do F.

U heksadecimalnom zapisu, raspon koji može uzeti byte podatak je od $00


do $FF, a word od $0000 do $FFFF.

Bit operacije
Na tipove byte i word su primenljive još neke operacije. To su tzv. bit
operacije. To mogu biti logičke operacije and, or, not i xor. N.b. označavaju
se isto kao Bulove operacije. Ove operacije obrađuju svaki bit posebno.
Tako:
Not $000F = $FFF0

Naravno, ove operacije su primenljive i na ostale celobrojne tipove, ali


njihov rezultat ne može biti neposredno jasan.

Pored ovih za rad sa bitovima standardne su još i shl i shr, koje služe za
pomeranje (šift) bitova u levo i u desno.

Realni tip
I ovaj tip obuhvata familiju tipova, gde je osnovni tip real. Ovo je podskup
skupa realnih brojeva. Dok je u matematici skup celih brojeva podskup
skupa realnih brojeva (Z  R), u programiranju to ne važi. Celobrojni tip
nije podskup realnog tipa.

Podaci realnog tipa se prikazuju u obliku decimalnog zapisa (5,6) ili


eksponencijalno (56E-1). Mantisa eksponencijalnog zapisa može biti realan
broj, dok je eksponent uvek ceo broj. Zavisno od veličine broja koristićemo
određenu notaciju. Eksponencijalna notacija se koristi za zapis mnogo velikih i
mnogo malih brojeva.

8
P R O G R A M S K I J E Z I K P A S C A L

tip opseg
single od 1,5∙10-45 do 3,4∙1038 4B
real od 2,9∙10-39 do 1,7∙1038 6B
double od 5∙10-324 do 1,7∙10308 8B
comp od -9,2∙1018 do 9,2∙1018 8B
extended 3,4∙10-4932 do 10B
1,1∙104932

Tip comp modelira celobrojni tip. On ne posduje razlomljeni deo.

Operacije
Operacije koje možemo vršiti sa podacima realnog tipa su: sabiranje (+),
oduzimanje (-), množenje (*) i deljenje (/).

Funkcije
Funkcije koje možemo koristiti sa podacima realnog tipa su: apsolutna
vrednost (abs), kvadrat broja (sqr), kvadratni koren (sqrt), sinus (sin),
kosinus (cos), arkus tangengs (arctan), prirodni logaritam (ln), eksponent
(exp). Pored ovih postoje i dve funkcije koje povezuju realni tip sa
celobrojnim. To su odsecanje decimala (trunc) i zaokruživanje (round).

Znakovni tip
Njegov identifikator je char. Skup svih znakova se zove karakter set
(character set). Pascalov karakter set obuhvata 255 znakova ASCII kôda
gde spadaju prazno mesto, brojevi, velika i mala slova engleske abecede,
interpunkcijski i specijalni znaci i simboli.

Podatke znakovnog tipa označavamo tako što ih stavljamo među


jednostruke znake navoda:
'L'

Znakove možemo dodeljivati konstantama takođe navodeći njihov ASCII


kod iza prefiksa #. Na primer:
#76 = 'L'

Relacioni operatori
Sa podacima znakovnog tipa takođe možemo koristiti relacione operatore.
Prilikom upoređivanja, upoređuju se ordinalni brojevi karakterâ. U
Pascalu, ordinalni broj nekog karaktera odgovara ordinalnom broju tog
karaktera u ASCII kôdu.

Funkcije
Od funkcija možemo koristiti: prethodnik (pred), sledbenik (succ),
određivanje ordinalnog broja ASCII kôda (ord) i određivanje karaktera
definisanog ordinalnim brojem ASCII kôda (chr).

9
P R O G R A M S K I J E Z I K P A S C A L

Dužina stringa se može


unapred zadati ako
ga deklarišemo pomoću:

string[duzina]

String
Ovo je tekstualni tip, tj. njegove promenljive su tekstovi.

Mora se voditi računa da tip string i char ne mogu biti ekvivalentni, jer se
operacije nad njima razlikuju. Takođe, prazan string postoji, dok prazan
znak ne može da postoji. Na kraju, podatak tipa char ima dužinu jedan
znak, dok podatak tipa string može da ima dužinu do 255 znakova.

Naime, kod stringa, prvi bajt se ne koristi za smeštaj podatka, već za


čuvanje dužine stringa. Pošto bajt ima raspon vrednosti od 0 do 255, time
je i dužina stringa ograničena na maksimalno 255 znakova.

Podatke string tipa označavamo isto kao i char, tj. stavljanjem među
apostrofe:
'Luka'

Operacije
Operacija sa stringovima ima nekoliko desetina, ali jedna od najvažnijih je
konkatenacija, tj. spajanje stringa. Ona se vrši pomoću operatora +:

'Luka' + ' Ranisavljević' = 'Luka Ranisavljević'

Pored ove, dosta se koristi i funkcija za određivanje aktuelen dužine


stringa length.

Enumeracija
Ovo je nestandardni skalarni tip. Razlikuje se od svih ostalih do sada
spomenutih, zato što je njegov domet uvek program u kojem je definisan.
Ovaj tip ne postoji u Pascalu, pa ga programer definiše u svom programu.
Drugi nazivi za ovaj tip su i nabrojivi tip, nabrojani tip itd.

Enumeracija ima unapred zadate vrednosti koje zadaje programer u


programu gde je potrebna enumeracija. Vrednosti su konstante i imaju
sintaksu identifikatora. Promenljiva tipa enumeracije može da uzme samo
jednu od nabrojanih vrednosti.

Opšti oblik
type ImeTipa = (sve_konstante_tipa);

Primer:
type Dani = (pon, uto, sre, cet, pet, sub, ned);

10
P R O G R A M S K I J E Z I K P A S C A L

Operacije
Operacije sa ovim tipom su dosta jednostavne. To su sledbenik (succ) i
prethodnik (pred). Takođe se mogu koristiti svih šest relacionih operatora
(=, <>, >, >=, <, <=) i funkcija ord koja određuje redni broj.

Sve ove operacije možemo koristiti, jer redosled vrednosti nije proizvoljan.
Stoga svaka vrednost u enumeraciji ima svoj redni broj i to: prva je 0,
druga je 1 itd.

Ulaz i izlaz za ovaj tip nisu definisani, pa se vrednosti promenljivima ovog


tipa ne mogu zadavati pomoću procedura read i readln, niti se one mogu
štampati pomoću write i writeln.

Enumeracija se koristi da bi se izbeglo šifriranje podataka.

Intervalni tip
Ovo je izvedeni tip, jer se oslanja na neki od osnovnih tipova. Intervalni tip
se izvodi iz nekog drugog tipa i to onih za koje postoji preslikavanje na skup
prirodnih brojeva (celobrojni i znakovni, ali ne real i string). Ovaj tip u
stvari „iseca“ jedan segment iz osnovnog tipa.

Opšti oblik
type ImeTipa = dg..gg

Gde je dg donja granica, a gg gornja granica.

Primer:
type RadniDani = pon..pet;
type NulaDoSest = 0..6;

Ako je osnovni tip od kojeg se uzima interval neki izvedeni tip, prvo
moramo definisati taj izvedeni tip. U gornjem primeru prvo moramo
definisati tip Dani (enumeraciju), pa tek onda RadniDani.

Promenljive intervalnog tipa nasleđuju osobine osnovnog tipa, ali im je


opseg određen donjom i gornjom granicom. Funkcije i operatori su
definisani za ovaj tip kao i za osnovni.

Intervalni tip se koristi za definisanje drugih tipova kod kojih je bitno da se


zada opseg (npr. definisanje opsega nizova) i ako je u domenu problema
potrebno koristiti ovakav tip. Ako je potrebno strogo voditi računa da
promenljiva ne izađe iz željenog opsega, koristićemo intervalni tip. Jer ako
promenljiva izađe iz opsega, dobija se poruka o grešci.

11
P R O G R A M S K I J E Z I K P A S C A L


Nizovi
Ovo je izvedeni, struktuirani tip. Bez obzira na broj dimenzija, Pascal sve
nizove tretira jednako. Niz obuhvata sekvencu određenih vrednosti,
obavezno istog tipa. Njihov broj se zadaje u programu.

Opšti oblik
type ImeTipa = array[opseg1, opseg2, ..., opsegN] of tip;

Opseg je integralnog tipa, cela enumeracija ili logički tip. Ne može biti real
i integer. To znači da opseg može biti samo izvedeni celobrojni tip, kod
kojeg je definisana donja i gornja granica. Vrednost opsega može biti i
negativan po potebi ili izveden iz znakovnog tipa. U praksi se opseg
najčešće zadaje kao 1 do n i ima ih jedan ili dva. Broj opsega određuje broj
dimenzija niza.

Dvoindeksni nizovi skalara se zovu matrice.

Primeri:
type TNiz = array[1..5] of real;
type TMatrica = array[1..4, 1..10] of integer;

Svaki element navedenog realnog niza se ponaša kao realna skalarana


promenljiva, odnosno svaki element navedene celobrojne matrice se
ponaša kao celobrojna skalarna promenljiva. Sve što možemo da radimo
sa realnom (tj. celobrojnom) promenljivom možemo i sa članom
odgovarajućeg niza.

Članovima niza pristupamo tako što navodimo njihov(e) indeks(e). Indeksi


su konstante, promenljive i izrazi.
niz[i];
matr[i,j];

U suštini Pascal ne poznaje tip matrice, samo tip niza (zbog uniformnosti),
pa se matrica tretira kao niz nizova. Stoga TMatricu možemo definisati i
na sledeći način:
type TMatrica = array[1..4] of array[1..10] of integer;

Prvi način je skraćeni zapis niza nizova. Slično, i članu matrice se može
pristupiti na sledeći način:
matr[i][j];
12
P R O G R A M S K I J E Z I K P A S C A L


Čitamo: j-ti element niza koji je i-ti element niza matr.

Isto tako se na sledeći način može pristupati vrstama matrice:


matr[i]

Skupovi
Ovaj tip predstavlja metematičke skupove.

Opšti oblik
type ImeTipa = set of tip_elemenata;

Elementi skupa moraju biti istog tipa i to mogu mogu biti sledeći tipovi:
logički, znakovni, enumeracija i intervalni tip.

U Turbo Pascalu tip elementa može da ima najviše 256 različitih elemenata.
To je posledica memorisanja skupa. Skup se čuva kao podatak od 32 bajta,
što je 256 bita i to tako što se svakom potencijalnom elementu dodeli 1 bit.
Ako element pripada skupu, njegov bit ima vrednost 1, u suprotnom 0.

Kao i u matematici i ovde važi da je redosled navođenja elemenata


proizvoljan i nema uticaja na vrednost skupa. Takođe, udvojeni elementi se
ne uzimaju u obzir.

Primeri:
type TMalaSlova = set of 'a'..'z';
TOsnovneBoje = (crvena, zuta, plava);
TSkupOsnovnihBoja = set of TOsnovneBoje;

Konstante ovog tipa su svi skupovi koji se mogu formirati od elemenata, s


tim što je [ ] prazan skup.

Konstante od TSkupOsnovnihBoja bi bile sledeće:


[] [crvena] [zuta] [plava] [crvena, zuta] [crvena, plava]
[zuta, plava] [crvena, zuta, plava]

Inače konstante možemo zadati i kao promenljive, izraze, imenovane


konstante i opsege:
[i, i * j - 1, 3, 11..20]

13
P R O G R A M S K I J E Z I K P A S C A L

Operacije
Tu pre svega spada dodela vrednosti, kada vrednosti elemenata jednog
skupa dodeljujemo elementima drugog skupa. Na primer:
type TSkup = set of 1..50;
var s1, s1: TSkup;
s1 := s2;

Zatim, tu spadaju još i unija, presek i razlika:

operacija u matematici u Pascalu


unija AB a + b
presek AB a * b
razlika A\B a - b

Relacioni operatori imaju posebna značenja kad se primenjuju na skupove:

operacija u u
matematici Pascalu
podskup AB a <= b
nadskup AB a >= b
jednakost A=B a = b
nejednakost AB a <> b
pripadnost aB a in b

Ranije su se skupovi najviše koristili za proveru da li se vrednost neke


promenljive nalazi u odgovarajućem opsegu. Na primer, da li je neko slovo
malo ili veliko. Pa da ne bismo pisali:
if (slovo = 'A' or slovo = 'B' or ...) then

koristimo skupove i pišemo kraće:


if slovo in [A..Z] then

Slog
Slog se drugačije naziva zapis. Ovaj tip je izveden kao i niz, iz nekog
osnovnog tipa, ali za razliku od elemenata niza, elementi sloga ne moraju
biti istog tipa. Znači da tip sloga može biti izveden iz više različitih osnovnih
tipova.

Slog nam omogućuje da u programu modeliramo određeni tzv. realni


entitet čije osobine opisuju elementi tog sloga.

14
P R O G R A M S K I J E Z I K P A S C A L

Opšti oblik
type ImeTipa = record
e1: tip1;
e2: tip2;
...
eN: tipN;
end;

Pri čemu je ei element sloga koji zovemo polje. Svako ei može imati više
identifikatora, u slučaju da više polja u jednom slogu ima isti tip. Tipovi
polja su proizvoljni. Svako polje se ponaša kao samostalna promenljiva tog
tipa.

Primer:
type Stanovnik = record
jmbg: string[13];
ime: string[15];
prezime: string[30];
end;

U semantičkom smislu, elementi niza su samostalni, tj. svaki za sebe ima


značenje. Ovo ne važi za elemente sloga. Elementi sloga zajedno opisuju
entitet, pa svaki za sebe nema značenje.

Dodela vrednosti
Ako dodeljujemo vrednost jedne promenljive tipa sloga drugoj
promenljivoj tipa sloga, vrednost svakog polja iz prve se kopira u
odgovrajuće polje ove druge.

Zbog toga, slogu možemo pristupati u celini, ali i njegovim delovima


(poljima). Određenom polju u slogu pristupamo ako imeđu imena sloga i
polja stavimo tačku:
Stanovnik.jmbg := '1906983800052';

Iterator with
Naredbu with koristimo za pristup poljima sloga, s tim što nam ona
omogućava da ne moramo svaki put navesti ime sloga kad pristupamo
nekom polju. Njen cilj nije skraćivanje kôda, već preglednost i
zadovoljavanje principa jedan posao – jedna naredba.
with a begin
jmbg := '1906983800052';
ime := 'Luka';
prezime := 'Ranisavljevic'
end;

Iteratori omogućavaju da se pristupi svakom elementu neke složene


strukture.

15
P R O G R A M S K I J E Z I K P A S C A L

Datoteke se čuvaju takve Tekući elemenat


kakve jesu dok se je onaj na kojim se
eksplicitno ne izršavaju procedure i
promene. funkcije.

Datoteke
Svrha postojanja datoteke u svim programskim jezicima je permanentno
čuvanje podataka. Podaci se u memoriji čuvaju najduže dok traje program.
Dok se, na primer, lokalne promenljive čuvaju još kraće.

Izlaz iz programa nam je često potreban i posle završetka programa, pa ga


zbog toga memorišemo. Ulaz iole obimnijih informacija je besmisleno
raditi sa tastature. Inače se najveći deo informacija potrebnih za
izvršavanje programa priprema iz datoteke, gde se oni provere, a potom ih
program obradi. Zavisno od konkretne situacije izlaz ide na ekran ili u
datoteku ili oboje.

Datoteka sa svojim sadržajem je fizički smeštena van programa i nalazi se


na permanentom mediju. Dakle, datoteke mogu da služe za komunikaciju
između programa, što je standardni vid komunikacije.

Sa stanovišta Pascala, datoteka se sastoji od sekvencijalno poređanih


elemenata. Izrazito karakteristično je da je u svakom trenutku jedan
elemenat markiran i zove se tekući elemenat. Tekući element može biti
jedan od postojećih ili novi (tj. jedan iz poslednjeg postojećeg u sekvenci).
Zbog toga i prazna datoteka ima tekući element. Procedure i funkcije se
izvršavaju implicitno nad tekućim elementom, npr. prilikom čitanja ili
pisanja, uvek se pristupa tekućem elementu.

Turbo Pascal ima dobro rešen datotečki sistem, tj. mehanizmi za


korišćenje datoteka su jednostavni. Turbo Pascal raspoznaje tri različita
tipa datoteka, od kojih standardnu primenu imaju prve dve. To su:

 tipizirana datoteka;

 tekstualna datoteka;

 netipizirana datoteka.

Tipizirana datoteka
Deklarišemo je naredbom type. Alternativni način (koji se često koristi) je
direktno zadavanje tipa uz naziv promenljive. Na primer:
type TSlog = record
{opis}
end;
var f: file of TSlog;

16
P R O G R A M S K I J E Z I K P A S C A L


Ne postoje naredbe za komunikaciju sa datotekama, već se
koriste posebne procedure i funkcije. Za tipizirane
datoteke postoje desetine procedura i funkcija, a
najvažnije delimo u dve grupe.

1. U ovu grupu spadaju univerzalne procedure i funkcije, tj. one


koje su iste u svim verzijama Pascala. To su četiri procedure i jedna
funkcija. Prve dve procedure služe za pripremu datoteke, a druge
dve za ulaz i izlaz.

a) rewrite(f) formira datoteku na spoljašnjem mediju ako ona još


ne postoji. Ako postoji, briše sav njen sadržaj. Posle izvršavanja
ove procedure, datoteka se sastoji od jedne prazne lokacije koja
je tekuća.

b) reset(f) se koristi pod pretpostavkom da datoteka već postoji


nezavisno od toga da li sadrži neke podatke ili je prazna. U
svakom slučaju ona (potencijalne) podatke ne dira i postavlja
prvi element da bude tekući. Pre korišćenja datoteke u
programu mora se izvršiti rewrite ili reset.

c) read(f, elem) se koristi za čitanje podataka (tj. elemenata) iz


datoteke. Parametar elem dobija vrednost tekućeg elementa, a
marker tekuće lokacije se premešta na sledeću. Elem je bafer
promenljiva.

d) write(f, elem) se koristi za upisivanje parametra elem u tekuću


lokaciju. Isto se marker tekuće pomera na sledeću lokaciju. Za
razliku od read, procedura write može da se izvede i nad
praznom lokacijom. U tom slučaju ona dobija vrednost
parametra elem i kreira se nova prazna lokacija koja postaje
tekuća. Zbog toga datoteka može da se proširuje u memoriji.

Element datoteke se ne može eksplicitno obrisati.

e) eof(f) (End Of File) je ugrađena funkcija koja vraća


promenljivu Bulovog tipa. Vrednost vraćene promenljive je
true, ako je kao tekući označen element iza poslednjeg
nepraznog (tj. novi). U suprotnom, ova funkcija vraća false.

2. U ovoj grupi su procedure i funkcije koje postoje u svim


verzijama, ali im sintaksa varira od verzije Pascala. Ove su nam
(kao i one iz prve grupe) neophodne za rad sa datotekama.

a) Assign(f, putanja)– za ovu proceduru se može reći da je osnovna


u radu sa datotekama. Spoljnjo ime datoteke je njeno pravo ime

17
P R O G R A M S K I J E Z I K P A S C A L

i u skladu je sa pravilima imenovanja operativnog sistema. U


programu ne koristimo to ime, već neku promenljivu (npr. f).
Da bi napravili asocijaciju između internog i eksternog imena
datoteke koristimo Assign. Parametar f je interno ime datoteke,
a putanja je tipa string i predstavlja apsolutnu ili relativnu
putanju do fajla na mediju.

Kad koristimo neku datoteku u programu, prvo ćemo


izvršiti proceduru Assign, da bi računar znao sa kojom
datotekom radi.

b) Close(f) je procedura koja se koristi da zatvorimo datoteku kad


nam više nije potrebna. Posle zatvaranja datoteka nam više nije
na raspolaganju dok ponovo ne izvršimo Assign.

U Turbo Pascalu se sve preostale otvorene datoteke (koje


nismo eksplicitno zatvorili) automatski zatvaraju pre
završetka programa. U praksi se pribegava tome da se
eksplicitno otvorena datoteka eksplicitno i zatvori.

Nije običaj da se sve datoteke eksplicitno zatvaraju na


samom kraju programa, već onda kad nam više nisu
potrebne.

c) Seek(f, pozicija) je procedura koja dejstvuje na oznaku tekućeg


elementa i to tako što za tekući element postavlja onaj čiju smo
poziciju naveli. Mora se voditi računa da se elementi
obeležavaju počev od 0 ne do 1. Parametar pozicija je tipa
longint.

d) FilePos(f) je funkcija tipa longint koja nam saopštava veličinu


datoteke izraženu brojem elemenata. Vrednost koju vraća ova
funkcija jednaka je broju zauzetih lokacija plus 1. Ako želimo
da marker tekuće lokacije postavimo na kraj datoteke (tj. na
novu praznu lokaciju) to ćemo učiniti komandom:
Seek(f, FilePos(f));

U toku izrade programa može se desiti da ne znamo da li neka datoteka


koja nam treba postoji u spoljašnjoj memoriji, pa da npr. koristimo reset
na nepostojećoj datoteci kada dolazi do greške.

Da bismo rešili ovaj problem koristićemo funkciju IOResult koja nam može
poslužiti da testiramo uspešnost bilo koje funkcije za rad sa datotekama.
Funkcija vraća vrednost 0 ako nije nastala nikakva greška u operaciji sa
datotekom. U suprotnom vraća nam odgovarajući kôd koji predstavlja
šifru nastale greške i na osnovu kojeg možemo predvideti da se u
programu izvrše odgovarajući koraci koji saniraju grešku.

18
P R O G R A M S K I J E Z I K P A S C A L

Tekstualna datoteka
Ovaj tip datoteke se intenzivno koristi. U originalnom Pascalu su
tekstualne datoteke predstavljale vrstu tipiziranih datoteka – tipizirane
datoteke čiji su elementi znakovi. Kasnije je ovaj način definisanja
tekstualnih datoteka eliminisan. Drugačije se tekstualne datoteke zovu i
tekst fajlovi.

Tekstualna datoteka predstavlja poseban tip podataka i postoji posebno


rezervisano ime za ovaj tip: text. Osnovni element ove datoteke jeste znak.
Pošto ovakva datoteka sadrži tekst (ne formalne podatke), u nju se piše i iz
nje se čita pomoću stringova.

Opšti oblik za definisanje promenljivih ovog tipa je sledeći:


var t: text;

I datoteke ove vrste postoje nezavisno od programa, imaju spoljnje


identifikatore i u programu se moraju povezati sa spoljnjim imenom koje
je nezavisno od programa. Kao i kod tipiziranih datoteka i ovde se to
postiže procedurom Assign.

Tekstualne datoteke se otvaraju za pisanje i čitanje istim procedurama kao


i tipizirane, i one imaju iste osobine, ali postoje dve razlike. I kod
tekstualnih datoteka tekući element postoji, ali programer na njega nema
nikakvog uticaja. Druga razlika se tiče režima rada tekstualne datoteke.
Ako je otvaramo procedurom rewrite, datoteka je u tzv. „write-only“
režimu, kad je u nju moguće samo upisivati podatke. A ako je otvorimo sa
reset, onda je ona u tzv. „read-only“ režimu kad se iz nje može samo čitati.

Postoji i treći način otvaranja, pomoću procedure append. Datoteka se


otvara kao da smo izvršili reset, ali se marker tekućeg elementa postavlja
na kraj datoteke i u nju možemo upisati nove podatke koji će se naći iza
već postojećih.

Na disku se tekstualna datoteka čuva kao niz znakova od kojih su neki


specijalni (npr. eoln označava kraj linije, a eof kraj fajla).

Način rukovanja ovom datotekom je identičan elementarom ulazu i izlazu,


tj. podatke upisujemo i čitamo pomoću procedura write, writeln, read i
readln. Drugačije rečeno, datoteka se ponaša kao ekran kad se u nju
upisuje, a kao tastatura kad se iz nje čita. To je zbog toga što se ekran i
tastatura u stvari tretiraju kao posebna vrsta tekstualne datoteke.

U procedurama za ulaz i izlaz se kao prvi parametar obavezno navodi


promenljiva koja se odnosi na datoteku iz koje želimo da učitamo podatke,
tj. da ih upišemo. Input i output su dve standardne datoteke automatski
pridružene tastaturi i ekranu (printeru), pa ako ih ne navedemo kao
parametre procedura za elementarni ulaz i izlaz, podrazumevaju se.

19
P R O G R A M S K I J E Z I K P A S C A L

Od ostalih procedura i funkcija bitnih za upravljanje tekstualnim


datotekama, spomenućemo još neke. Close se koristi za zatvaranje
datoteke. Funkcija eof pokazuje kada naiđemo na kraj datoteke, a eoln
kada naiđemo na kraj reda. Eoln je u Turbo Pascalu izgubila značaj, jer
postoji readln koja učitava ceo red odjednom. Naravno, writeln koja kao
parametar ima samo ime datoteke upisuje u nju prazan red.

Netipizirana datoteka
Ovo je uobičajen naziv za ovaj tip datoteke, ali nije dovoljno precizan kada
se govori o Turbo Pascalu. Jedno od osnovnih načela ovog programskog
jezika jeste da sve ima svoje ime, tako da je nepravilno govoriti o
netipiziranim podacima.

Ovaj naziv se koristi upravo zbog toga što se netipiziranoj datoteci


pristupa na nivou bajta, tj. njeni osnovni elementi se tretiraju kao bajtovi.
Sadržaj datoteke se sastoji od niza bajtova bez ikakve semantike. Nju
obezbeđuje programer u svom programu. Ovo je dosta važan tip datoteke.

Opšti oblik za definisanje promenljivih ovog tipa je:


var b: file;

Vidimo da se u deklaraciji promenljive navodi samo da je u pitanju


datoteka, ali ne i o kakvom tipu datoteke se radi.

I za ove datoteke se koriste: assign, reset i rewrite, ali reset i rewrite imaju
drugačiju sintaksu, jer se navodi i veličina jednog elementa u bajtovima.
Mogu se koristiti i close, seek, filepos i filesize. Filesize ne vraća veličinu
datoteke u bajtovima, veću u elementima. Npr. ako jedan element ima 10
bajtova, filesize će vratiti broj desetobajtnih elemenata u datoteci. Za
rukovanje sadržajem datoteke se koriste posebne procedure: blockread i
blockwrite.

Pokazivači
Pokazivači predstavljaju jedan od najvažnijih tipova u Pascalu i
predstavljaju najveći konkretni doprinos Pascala uopšte. Omogućili su da
program u toku rada zahteva dodatnu memoriju od sistema i oslobađa tu
naknadno zahtevanu memoriju.

Postoje dve međusobno srodne vrste pokazivača: skalarni (osnovni) i


izvedeni. Među njima postoje razlike, ali oni mogu međusobno
razmenjivati vrednosti. Inače, pokazivače uopšteno zovemo pointeri bez
obzira koje su vrste.

Vrednost jednog pokazivača je adresa. Adresa je zajednička karakteristika


svih tipova podataka i kategorija u programu.

20
P R O G R A M S K I J E Z I K P A S C A L

U Pascalu se za
označavanje pokazivača
koristio simbol , a u
Turbo Pascalu se koristi
^.
Kad tražimo dodatnu memoriju od sistema, mi njenu adresu unapred ne
znamo. Dodatnu memoriju naš program traži od jednog drugog programa
čija je uloga da obezbedi onoliko memorije koliko smo tražili i onda nam
prosledi adresu te novozauzete memorije. Adresu ćemo čuvati u
promenljivoj tipa pokazivača.

Važno!

Pokazivači nam omogućavaju dinamičku dodelu memorije i


pristup toj dinamički dodeljenoj memoriji preko njene adrese.

Netipizirani pokazivači
Ovo je jedan od osnovnih skalarnih tipova. Vrednosti promenljivih ovog
tipa se razlikuju od drugih vrednosti osnovnih tipova koliko se i oni među
sobom razlikuju. Drugačije se ovaj tip naziva i adresni tip ili generički
pokazivač. Nešto malo manje se koriste od tipiziranih pokazivača.

Promenljivu deklarišemo na sledeći način:


var adr: pointer;

Nekoj adresi se ne može pristupiti direktno preko goredeklarisane


promenljive adr, jer mi ne znamo šta se na toj adresi nalazi. Zbog toga je
namena generičkih pokazivača čuvanje vrednosti tipiziranog pokazivača.

Tipizirani pokazivači
Pokazivači ovog tipa su od primarnog značaja, jer gotovo da nema
programa koji ih ne koristi. Nisu postojali u originalnom Pascalu.

Tipizirani pokazivač je izvedeni tip i njegova vrednost jeste adresa, ali se


prilikom definisanje promenljive ovog tipa daje i informacija o tome šta se
nalazi na toj adresi. Ako se zna šta stoji na određenoj adresi, onda je moguć
pristup toj adresi. Dakle, osnovna namena tipiziranog pokazivača jeste
dinamička promena memorije.

Ovaj tip se mora eksplicitno deklarisati i to na sledeći način:

type ImeTipa = ^tip_podatka;

Naravno, možemo ga deklarisati i direktno u deklaraciji promenljive:


var pok: ^tip_podatka;

Nepisano je pravilo da se kod imenovanja pokazivačkih tipova na početak


imena stavi veliko slovo P, kako bismo kasnije u programu znali da je reč o
21
P R O G R A M S K I J E Z I K P A S C A L

pokazivaču. Kod promenljivih, stavljamo malo slovo p. Ovo je tzv.


mađarska notacija. Na primer:

type PInt = ^integer;


var pI : PInt;

Tipizirane pokazivače koristimo na dva načina: možemo manipulisati


vrednošću pokazivača (tj. adresom na koju pokazuje) ili podatkom na koji
pokazuje (sadržajem memorijske adrese). Sadržaj adrese pokazivača
(podatak) ima sve osobine promenljive koja se nalazi na toj adresi i njemu
pristupamo pomoću: pI^.

Postoje dva načina za povezivanje pokazivača i lokacije čiju adresu sadrži


pokazivač. U prvom slučaju, sve promenljive su deo statičke memorije
programa. Na primer:
var i: integer;
p: ^integer;
t, w: pointer;

i := 5;
p := @i;
p^ := -7;
t := @i;
w := p;

U ovom primeru, i je celobrojna promenljiva, p je tipizirani, a t i w su


generički pokazivači. Dodelićmo vrednost 5 promenljivoj i, a zatim njenu
adresu promenljivoj p. To radimo pomoću adresnog operatora @. Potom
smo upisali vrednost -7 na lokaciju p^, tj. promenili smo vrednost i.
Adresama t i w ne možemo da pristupamo, jer su t i w generički
pokazivači. Oni čuvaju samo adresu i, tj. vrednost p.

Drugi način povezivanja je važniji, jer omogućava dinamičku dodelu


memorije. Dinamička memorija se zove i heap. Pokazivač (koji je deo
statičke memorije programa) nam omogućava da u određenom trenutku
zahtevamo od sistema da nam dodeli lokaciju iz ostatka memorije, ali pri
tome se mora znati koliko memorije i za šta. Pascal program se u tom
slučaju obraća tzv. upravljaču heapa koji pronalazi gde postoji slobodna
memorija koja se traži, označava tu lokaciju kao zauzetu i upisuje njenu
adresu u pointer.

Sa upravljačem heapa se komunicira uz pomoć procedura. Procedura


new(pI), gde je pI tipizirani pokazivač. Posle izvršavanja procedure new,
možemo da koristimo promenljivu pI^. Kad nam ova lokacija više nije
potrebna, javljamo da se označi kao slobodna procedurom dispose(pI).
Posle njenog izvršavanja nam pI^ više nije na raspolaganju, tj. sadržaj
pokazivača je nil.

22
P R O G R A M S K I J E Z I K P A S C A L


Pokazivačka konstanta nil
Pokazivač bilo koje vrste može da uzme njenu vrednost. U tom slučaju
pokazivač ne pokazuje ni na šta.

Posle izvršavanja procedure new(pI), ne smemo promenljivoj pI dodeliti


vrednost nil mi sami. Desiće se da će se prekinuti veza između pokazivača i
lokacije, ali da će lokacija ostati označena kao zauzeta. Zbog toga moramo
izvršiti i proceduru dispose, da bi se lokacija korektno oslobodila.

Primer
U ovom primeru ilustrovaćemo rad sa datotekom i korišćenje unita u
Turbo Pascalu (strana 40). Program koristi unit MPoint koji je dat na
strani 42.

Smatra se da već postoji formirana datoteka koja sadrži neke elemente


(podatke) tipa TPoint. Program će pročitati podatke iz cele datoteke i
odrediti (štampati) apscisu i ordinatu tačke najudaljenije od koordinatnog
početka.
program NajdaljaTacka;

uses MPoint;
var DatTacka: file of TPoint;
Nula, tacka, najdalja: TPoint;
maxrast, pom: real;

begin
Assign(DatTacaka, 'c:\mydir\tacke.dat');
reset(DatTacaka);
Create(Nula, 0, 0);
maxrast := 0;

while not eof(DatTacaka) do begin


read(DatTacaka, tacka);
pom := distance(tacka, Nula);
if maxrast < pom then begin
maxrast := pom;
Copy(tacka, najdalja); end
end;

Close(DatTacaka);
writeln('Najdalja tačka ima apscisu ',
GetX(najdalja), ' i ordinatu ', GetY(najdalja))

end.

23
P R O G R A M S K I J E Z I K P A S C A L

Opšta struktura programa


Pascal programi imaju čvrsto definisanu strukturu. Tačno se zna gde se
koji deo kôda piše. Time se smanjuje verovatnoća da se napravi greška.

Strukturu Pascal programa čini sam program, njegovi potprogrami i moduli.

Pošto je struktura gotovo uniformna, možemo govoriti o globalnoj strukturi


programa. Takođe, bez obzira koji prevodilac prevodi kôd, vrlo je moguće
da će on uvek raditi jednako.

Globalna struktura programa

zaglavlje

deklaracije
labele
konstante
tipovi
promenljive
potprogrami
algoritamski deo
blok

Zaglavlje
U zaglavlju se identifikuje program. Ova linija kôda u turbo Pascalu nije
obavezna.
program ime_programa;

24
P R O G R A M S K I J E Z I K P A S C A L


Deklaracije
Odmah na početku teksta o deklaracijama treba napomenuti dve stvari.
Prvo: redosled kategorija koje se deklarišu nije dat po važnosti. Drugo:
odnos važnosti deklaracija i algoritamskog dela se u toku vremena menjao.
Ranije su programeri veliku pažnju obraćali da algoritamski deo, dok
deklaracije nisu bile mnogo bitne. To je bilo zbog toga što su tadašnji
programi imali male mogućnost, pa samim tim tipova, promenljivih itd.
nije bilo mnogo. Kasnije je delu sa deklaracijama posvećena veća pažnja
(tako je i u Pascalu), jer vrlo se lako može desiti da pogrešno deklarisana
promenljiva utiče da se javlja greška u programu ili da ozbiljno ugrozi
performanse programa. Danas, pošto se koristi objektni model
programiranja, obrisana je granica između deklaracija i algoritamskog
dela i ta dva su dela postali ravnopravni.

Labele
Labele su oznake naredbi u programu. Ranije su mnogo korišćene, dok se
danas teži da se upotreba labela i skokova u programu maksimalno
izbegne. U Pascalu se one skoro uopšte ne koriste osim u slučaju komande
goto. Treba voditi računa da se program tako piše da ova komanda
postane izlišna.

Sintaksa:
label identifikator1, identifikator2, ..., identifikatorN;

Označavanje naredbi se vrši na sledeći način:


oznaka: naredba;

Primer:
label kraj;
...
kraj: writeln;

Konstante
Deklarišemo samo imenovane konstante.

Sintaksa:
const ime1 = vrednost1, ime2 = vrednost2,
..., imeN = vrednostN;

25
P R O G R A M S K I J E Z I K P A S C A L

Konstante koje u Primer:


programu imaju
određeno značenje bi
trebalo da budu
imenovane.

const pi = 3.14;

Tipovi
Tipovi koje deklarišemo su u stvari sopstveni tipovi koje definiše
programer. Takođe, ime tipa treba da bude smisleno. Nepisano pravilo je
da ime tipa počinje velikim slovom. Pošto identifikator ne može sadržati
razmake, onda ako ime tipa sadrži više reči, sve ih pišemo zajedno, ali
svaku počinjemo velikim slovom.

Sintaksa:
type ImeTipa1 = opis_tipa1;
ImeTipa2 = opis_tipa2;
...
ImeTipaN = opis_tipaN;

Primer:
type Visina = real;

Promenljive
Svaka promenljiva ima ime i tip i zauzima memoriju u kojoj se čuva njena
vrednost. U Pascalu je eksplicitno deklarisanje promenljivih obavezno. Na
taj način, između ostalog, se smanjuje mogućnost greške.

Promenljive deklarišemo na sledeći način:


var ime1_1, ime1_2, ime1_3 : tip1;
ime2_1, ime2_2 : tip2;

Direktno zadavanje tipa


Kod deklaracije promenljivih dajemo njeno ime i njen tip. Ako je tip
izveden, možemo mu prvo dati ime u deklaraciji tipova pa ga onda
koristiti. Ali ga možemo zadati i direktno, tj. u deklaraciji promenljive. Na
primer:
var dani: (pon, uto, sre, cet, pet, sub, ned);

Ovo se u glavnom ne radi, jer na ovaj način ne možemo kasnije definisati


još jednu promenljivu istog tipa. Takođe ovo nije u duhu Pascala, jer bi sve
trebalo da ima svoje ime.

Potprogrami
Potprogrami u Pascalu su u stvari procedure i funkcije. Prilikom njihovog
deklarisanja one se navode u celini. Kao što program može da ima svoj
potprogram, tako i potprogram može da ima svoj potprogram. Broj nivoa
potprograma nije ograničen, ali je u praksi potrebno najviše dva nivoa, a
26
P R O G R A M S K I J E Z I K P A S C A L

veoma retko se koriste i tri. Velik broj podnivoa čini program teškim za
razumevanje, a ranije je rečeno da je osnovna svrha Pascala pisanje
čitljivih i razumljivih programa.

O procedurama i funkcijama će više reči biti kasnije.

Algoritamski deo
Algoritamski deo se sastoji od naredbi. Da bi prevodiocu označili
algoritamski deo, stavljamo ga među tzv. programske zagrade:
begin
naredba;
end.

Obavezno se iza ovog end stavlja tačka, ne tačka-zarez.

Programski jezik Pascal sadrži samo najbitnije naredbe. ALGOL je


sadržao jedan broj naredbi koje su se jako retko koristile. Pascal ih nema.

27
P R O G R A M S K I J E Z I K P A S C A L


Naredba dodele je
dvoznak.

Naredbe
Naredba dodele
Ova naredba je osnovna naredba svakog proceduralnog programskog
jezika. Njena sintaksa u Pascalu je sledeća:
promenljiva := izraz;

Ova se naredba izvršava u dva koraka:

 izračunava se vrednost izraza;

 dodela vrednosti izraza promenljivoj sa leve strane.

Mora se voditi računa da promenljiva i izraz imaju isti tip. Jedini izuzetak
je da je promenljiva tipa real, a izraz integer.

Složena naredba (sekvenca)


Složena naredba predstavlja vrlo jednostavan i delotvoran način da se više
nezavisnih naredbi tretira kao jedna složena.

Sekvencu nezavisnih naredbi stavljamo među programske zagrade. U


Pascalu su to begin i end, kako je objašnjeno na strani 27.

Kada pišem program u Pascalu, koristimo se principom: jedan posao –


jedna naredba. Samim tim, ceo naš program možemo posmatrati kao
jednu složenu naredbu.

Naredbe selekcije
Drugačije se nazivaju uslovne naredbe.

If then i if then else


Ove dve naredbe su potpuno ravnopravne. Neki autori naredbu if then
smatraju specijalnim slučajem ove druge, što nije opravdano.

28
P R O G R A M S K I J E Z I K P A S C A L

Sintaksa:
if logicki_izraz then naredba1;
else naredba2;

if logicki_izraz then naredba;

logički true true logički false


izraz izraz

false naredba naredba 1 naredba 2

Kod komande if then else, zavisno od toga je li logički izraz tačan ili ne
izvršava se prva, odnosno druga naredba. Kod komande if then, pak,
naredba se izvršava ako je izraz tačan, ako nije, ne izvršava se.

Primer:

 sin x x  3,5 if x > 3,5 then g := sin(x)


 else if x = 3,5 then g:=
g 0 x  3,5
0.0
cos x x  3,5
 else g := cos(x)

Case
Naredba case predstavlja naredbu višestruke selekcije. To je izvedena
naredba. Koristimo je kada treba da uporedimo vrednost nekog izraza sa
unapred zadatim vrednostima. Mora se voditi računa da izraz ne sme biti
tipa real i string.

Sintaksa:
case izraz of
vrednost1_1, vrednost1_2: naredba1;
vrednost2_1: naredba2;
...
vrednostN: naredbaN;
end;

Primer:
case i + s of
1, 4: y := sin(z);
0: begin y := 0; j := 1 end;
-10: x := x + 1
end;

29
P R O G R A M S K I J E Z I K P A S C A L

Upravljačka promenljiva


se zove i kontrolna
promenljiva.

Petlje
Petlje predstavljaju jednu od najosnovnijih struktura u programiranju.
Pomoću njih se fizički ograničenim brojem naredbi računaru može zadati
proizvoljno veliki psao. U Pascalu postoje tri naredbe ciklusa: for, while i
repeat. Svaki ciklus predstavlja jedinstvenu naredbu.

For
For je brojački ciklus. For petlja ima upravljačku promenljivu čija
vrednost upravlja ponavljanjem ciklusa. Njena vrednost se menja i
proverava automatski, stoga kod ove petlje postoji određena
automatizacija.

Sintaksa:
for kp := pv {to|downto} kv do naredba;

Gde je kp ime kontrolne promenljive, pv je početna vrednost, a kv krajnja


vrednost. Koristimo to ili downto zavisno od toga želimo li da se prilikom
izvršenja petlje vrednost kontrolne promenljive odbrojava unapred ili
unazad od početne do krajnje vrednosti (npr. od 1 do 10 ili od 10 do 1).

Ova petlja ne mora da se izvrši ni jednom. Koristimo je kada je u trenutku


otpočinjanja ciklusa poznato koliko će biti ponavljanja.

While
Ovo je osnovna vrsta ciklusa, pošto se njim može rešiti bilo koje
ponavljanje.

Sintaksa:
while logicki_izraz do naredba;

Na BDA naredbe while se vidi da se prvo


proverava vrednost logičkog izraza, pa ako
je izraz tačan, izvršava se naredba. Zbog
false logički naredba toga se ova petlja ne mora izvršiti ni jednom.
izraz
Naravno, broj ponavljanja ne mora biti
true
unapred poznat, ali je bitno da naredba
utiče na vrednost logičkog izraza. U
suprotnom se petlja ili uopšte neće izvršiti
(ako je izraz netačan pre ulaska u petlju) ili će se izvršavati beskonačno
(pošto je izraz uvek tačan).

30
P R O G R A M S K I J E Z I K P A S C A L

Naredbe skoka
treba izbegavati.
Repeat
Sintaksa:
blok
naredbi
repeat
naredba_1;
logički false
naredba_2;
izraz
true ...;
naredba_n
until logicki_izraz;

Repeat naredba je slična naredbi while. Doduše, mnogo


manje se koristi. Za razliku od while, pošto se uslov proverava na kraju,
repeat se izvršava makar jednom. Ako je naredba sekvenca, ne koriste se
programske zagrade begin i end, jer se ponavlja sve što je između repeat i
until.

Najvažnija razlika između while i repeat je što se while ponavlja dok iskaz
jeste tačan, a repeat dok iskaz ne postane tačan.

Naredbe skoka
U Pascalu postoji pet naredbi skoka. Kao što je iznešeno ranije, Pascal je
tako koncipiran da je potreba za skokom skoro eliminisana.

Osnovna naredba skoka je goto. Njena sintaksa je:


goto labela;

Labela je mnemonički identifikator.

Pored ove postoje i naredbe skoka koje se koriste u ciklusima i


potprogramima:

 break – momentalni izlazak iz ciklusa;

 continue – momentalni skok na početak ciklusa;

 exit – momentalno završavanje potprograma;

 halt – momentalno zaustavljanje programa. Ova naredba je


najčešće propraćena porukom za korisnika.

31
P R O G R A M S K I J E Z I K P A S C A L

Elementarni ulaz/izlaz
Elementarni ulaz jeste ulaz sa tastature, a elementarni izlaz jeste izlaz na
ekran.

U Pascalu se ovo obavlja pomoću dva potprograma (dve procedure) čiji je


broj parametara promenljiv.

Za izlaz na ekran u tekstualnom režimu se koristi:


write(p1, p2, ..., pN);
writeln(p1, p2, ..., pN);
writeln;

Gde je pi konstruktor sastavljen na sledeći način:


pI = e1 : e2 : e3

e1, e2 i e3 su izrazi i to: e 1 je izraz čija se vrednost prikazuje, e 2 određuje


broj pozicija koju zauzima e1 na ekranu, a e3 je broj decimalnih mesta. e2 i
e3 su najčešće konstantne vrednosti.

Pažnja

Treba voditi računa o tome da kad write završi ispis, ekranski


kurzor ostaje odmah iza poslednjeg ispisa, dok ga writeln
premešta na početak novog reda. Samim tim, writeln bez
parametara samo premešta kurzor na početak sledećeg reda.

Za ulaz sa tastature koristimo:


read(v1, v2, ..., vN);
readln(v1, v2, ..., vN);
readln;

Gde je vi ime promenljive čiju vrednost tražimo od korisnika.

Ako unosimo više promenljivih odjednom, njihove vrednosti prilikom


unosa razdvajamo tako što među njima napravimo jedno ili više praznih
mesta.
32
P R O G R A M S K I J E Z I K P A S C A L

Potprogrami
Prvobitna namena potprograma je bilo skraćivanje izvornog koda, ali je
ovo brzo zanemareno. Osnovni razlog upotrebe potprograma je što oni
predstavljaju logičku celinu i time sam program postaje pregledniji i lakši
za razumevanje. Potprogrami predstavljaju jedan od nivoa
modularizacije.

Postoje dve vrste potprograma: funkcije i procedure. One imaju istu


strukturu koja je gotovo identična opštoj strukturi programa.

Zaglavlje potprogramapredstavlja mehanizam koji se razmenjuju


parametri između glavnog programa i potprograma. Oblik zaglavlja zavisi
od vrste potprograma.
function ime(formalni_parametri): tip
function ime: tip

procedure ime(formalni_parametri)
procedure ime

Namena formalnih parametara je prenos ulaznih vrednosti klijenta i


prihvatanje eventualnih vrednosti funkcije, odnosno vrednosti koje vraća
procedura. Formalni parametri mogu biti promenljive svih osnovnih
tipova ili druge procedure.

Primeri:
function Proizvod(n: integer): longint;
var p: longint; i: integer;
begin
p := 1;
for i := 1 to n do p := p * i;
Proizvod := p;
end;

33
P R O G R A M S K I J E Z I K P A S C A L

procedure MinMax(x, y, z: real; var min, max : real);


begin
if (x < y) and (x < z) then min := x
else if (y < x) and (y < z) then min := y
else min := z;
if (x > y) and (x > z) then max := x
else if (y > x) and (y > z) then max := y
else max := z;
end;

Da bi pozvali neku funkciju, njeno ime ćemo uvrstiti u neki izraz.


Proceduru pozivamo samo navođenjem njenog imena u kôdu programa.

Svaka funkcija vraća jednu vrednost, tako što njenom imenu dodelimo
vrednost u kôdu funkcije. (U primeru funkcije Prozivod, pretposlednja
linija kôda dodeljuje vrednost p funkciji.) Pri tome treba voditi računa da
se ime funkcije ne sme koristiti u njoj samoj, osim u slučaju dodele
konačne vrednosti koju funkcija vraća. Funkcije vraćaju samo skalarne
vrednosti.

Procedura, s druge strane, ne vraća nikakvu vrednost svojim imenom. Njih


koristimo za izmenu stanja programa koje je opisano vrednostima nekih
promenljivih, jer će procedura promeniti vrednosti tih promenljivih. Ako
je potrebno da je izlazna vrednost potprograma takva da ne može da je
vrati funkcija (nije jedna ili nije skalarna) koristićemo proceduru.

Deklaracija unapred
Da bi jedan potprogram mogao pozvati drugi, onaj koji je pozvan mora
biti deklarisan pre ovog koji poziva. Tj. ako P koristi Q, Q mora biti
deklarisano pre P. U slučaju da P poziva Q, ali i Q poziva P nije moguće
oba programa smestiti jedan pre drugog, pa koristimo deklaraciju
unapred. U zaglavlje jedan potprogram postavljamo prvi i koristimo
ključnu reč forward koja prevodiocu označava da će potprogram biti
opisan kasnije.

Primer:
procedure Q(...); forward;
procedure P(...);
begin
...
Q
...
end;

Lokalne i globalne promenljive


Pošto se često javlja potreba da u potprogramu postoje neke promenljive
koje van njega nemaju značenje, uvodimo lokalne promenljive. Formalni
parametri potprograma su lokalne promenljive. Za razliku od ovih postoje
i globalne promenljive, koje su definisane u glavnom programu i važe za ceo
program.

34
P R O G R A M S K I J E Z I K P A S C A L

Ako se dogodi da se poklope imena lokalne i globalne promenljive, lokalna


promenljiva ima prednost, tj. u potprogramu će važiti lokalna
promenljiva, a van njega globalna.

Pažnja

Treba voditi računa da lokalna i globalna promenljiva istog


imena nikako ne utiču jedna na drugu.

Formalni i stvarni parametri


Formalni parametri su oni koji se pojavljuju u zaglavlju potprograma. Pri
pozivu tog potprograma njihove vrednosti se zamenjuju vrednostima
stvarnih parametara.

Stvarni parametri su oni koji se nalaze u pozivu potprograma i to mogu biti


promenljive ili izrazi.

Stvarni i formalni parametri se moraju poklapati po tipu i po redosledu


kako se navode u pozivu potprograma, odnosno u njegovom zaglavlju.

Parametri vrednosti i parametri imena


Prenos parametara između glavnog programa i potprograma se izvršava
preko steka i može biti prenos po vrednosti, kad se prenosi samo vrednost
tog parametra, ili po imenu, kad se prenosi adresa parametra.

Prenos po vrednosti se koristi za čisto ulazne parametre čiju vrednost u


glavnom programu potprogram ne treba da menja. Zbog toga na mestu
poziva parametra po vrednosti može da stoji i neki izraz.

Prenos po imenu se koristi za ulazno/izlazne parametre. Pošto se u steku


nalazi stvarna adresa parametra, potprogram može da menja vrednost
parametra u glavnom programu.

Da bi prevodilac znao da li se neki parametar prenosi po vrednosti ili


imenu, dodajemo rezervisanu reč var u zaglavlje potprograma. Tako u
primeru procedure MinMax x, y i z se prenose po vrednosti, jer ispred njih
ne stoji var, a min i max po imenu, jer ispred njih stoji var.

Nizovi kao parametri potprograma


Nizove prosleđujemo potprogramu na sledeći način: prvo deklarišemo tip,
a zatim u potprogramu navedemo formalni parametar tog tipa. Na
primer:
type TNiz: array[1..10000] of integer;
...
function f(n: integer; Niz: TNiz): integer;
begin
...
end;
35
P R O G R A M S K I J E Z I K P A S C A L

Ovde postoje dva problema:

 niz se prenosi kao parametar vrednosti;

 funkcija će prihvatiti samo nizove koji su identičnog tipa kao


formalni parametar.

Prvi problem nastaje zbog toga što ako se niz prenosi kao parametar
vrednosti, svih n elemenata se prenosi na stek bez obzira koliko nam zaista
treba. Ovo zauzima nepotrebne resurse, ali i oduzima vreme pogotovo ako
niz ima velik broj članova. Zbog toga možemo dodati var u deklaraciju
parametra, da bi se niz preneo po imenu. Tad će potprogram raditi sa
stvarnim elementima niza, ali se mora voditi računa ako je niz čisto ulazni
da potprogram ne menja vrednost članova.

U Turbo Pascalu 7.0 je dozvoljeno da se stvarni parametri prenose na tri


načina. Pored prenosa po vrednosti i imenu, uveden je i prenos parametra
kao konstante. U tom slučaju se takođe prenosi adresa stvarnog
parametra, ali prevodilac vodi računa da potprogram ne menja njegovu
vrednost.

U gornjem primeru bismo to rešili na sledeći način:


type TNiz: array[1..10000] of integer;
...
function f(n: integer; const Niz: TNiz): integer;
begin
...
end;

Što se tiče drugog problema, on se ogleda u sledećem. Kokretno, u


navedenom primeru, funkcija f će prihvatiti kao ulazni parametar neku
celobrojnu vrednost n i isključivo celobrojni niz od 10 000 elemenata čiji je
opseg od 1 do 10 000. U slučaju da želimo da napišemo neki uopšteni
potprogram (npr. za sabiranje n članova niza), za svaki niz koji je
drugačiji od ovog bi morali pisati novi potprogram.

Ovaj problem je sintaksno rešen tek u Turbo Pascalu 7.0, ali samo za
jednodimenzionalne nizove. Kod deklaracije tog niza nećemo navesti
njegov opseg. Na primer, procedura P će prihvatiti sve nizove koji su
realnog tipa.
procedure P(RNiz: array of real);

Low() i High()
Ove dve funkcije su uvedene za rad sa otvorenim parametrima. Low nam
daje donju granicu niza (najmanji indeks, indeks prvog elementa), a High
gornju granicu (tj. najveći indeks, indeks poslednjeg elementa).

36
P R O G R A M S K I J E Z I K P A S C A L

Da bi mogli koristiti Primer:


Low() i High() prevodiocu
moramo zadati direktivu
{&P+}.

function Suma(const X: array of real; n: integer): real;


var s: real; i: integer;
begin
s := 0;
for i := 1 to n do
s := s + x[Low(x) + i – 1];
Suma := s
end;

Potprogrami kao parametri drugih potprograma


Potprogramu možemo proslediti neki drugi potprogram kao parametar,
tako što ćemo parametru pridružiti odgovarajući tip.

U sledećem primeru smo definisali tip TFunc koji odgovara funkciji g. U


deklaraciji funkcije Integral, kao jedan od parametara navodimo f koji je
tipa TFunc.
type TFunc = function(x: real): real;
function Integral(a, b: real; f: TFunc): real;
var t: real;
begin
...
f(t);
...
end;
function g(x: real): real;
begin
g := 2 * exp(x) – sin(x)
end;
...
y := Integral(1.2, g)
...

Rekurzivni potprogrami
Rekurzivni potprogram je onaj koji poziva samoga sebe, tj. koristi
sopstvene usluge. Prvi put su se rekurzivni potprogrami pojavili u Algolu,
jer je tad uveden stek koji je omogućio rekurzivno pozivanje potprograma.
Primer rekurzivne funkcije je faktorijel.

Rekurzivni programi su najčešće kratki ali nejasni i često utiču na brzinu


izvršavanja programa. Treba ih izbegavati, jer uz korišćenje lokalnih
promenljivih lako mogu prepuniti stek.

Koriste se za rešavanje rekurzivnih problema, npr. prolazak kroz stablo i


sl.

37
P R O G R A M S K I J E Z I K P A S C A L


U početku biblioteke
Bez modula nema
nisu imale
profesionalne
strukturu,
izrade programa ni
predstavljale su skup
neuređenih programa na jednom
koji se koriste po proceduralnom
potrebi. programskom
jeziku.
Primer:
function Faktorijel(n: integer): longint;
begin
if n := 0 then Faktorijel := 1
else Faktorijel := n * Faktorijel(n-1)
end;

Moduli
Moduli predstavljaju vrstu autonomnih softverskih jedinica. Da bismo
lakše realizovali neki kompleksni program, razbijamo ga na delove od
kojih svaki predstavljaja logičku celinu, pa onda te delove zasebno
realizujemo i na kraju ih spajamo.

Moduli su se pojavili 60-ih godina kao rezultat povećanih zahteva


korisnika. Prvi moduli su bili vrlo jednostavni i osnovna namena im je bila
da se jednom napisan kôd može više puta upotrebiti.

Da ne bismo svaki put kopirali deo kôda koji izvršava isti posao, pojavile
su se biblioteke gotovih programa. U početku su bile štampane na papiru, pa
se proces njihove implementacije svodio na prepisivanje kôda sa papira.
Kasnije je pronađen mehanizam da se ove biblioteke prenose u
prevedenom obliku.

Pojavom strukturnih programskih jezika, biblioteke modula više nisu


predstavljale skupove programa opšte namene koji rešavaju neki problem,
već su dobile odgovarajuću organizaciju, tj. strukturu.

Važno je napomenuti da Wirthov Pascal nije poznavao module. Ceo


program (sa svim potprogramima) je predstavljao čvrsto vezanu celinu.
Prepisivanje kôda je bio jedini način da se izvede da se neki potprogram
jednog programa izvršava i u nekom drugom programu.

Za pisanje modula koristimo uobičajene komande programskog jezika.


Moduli se koriste isključivo u prevedenom obliku i prevedeni modul u
Pascalu nema ekstenziju EXE, jer nije izvršni. Najčešće ima ekstenziju
TPU ili TPP.

Šta je modul?

38
P R O G R A M S K I J E Z I K P A S C A L


Šta se dešava sa ulazom i
Information Hiding
kako se transformiše u
Principle izlaz, klijenta se ne
tiče.

Modul je softverska komponenta koja se realizuje (tj.


projektuje, kôdira, testira i modifikuje) autonomno, bez
potrebe da se taj kôd meša sa nekim drugim kôdom.

Modul može biti izvršni, a ne mora. U Pascalu postoje obe vrste modula.
Naime, kod Pascala glavni program je takođe modul (izvršni). Ostale
strukture po pravilu nisu izvršni moduli.

Opšta struktura modula


Zbog postojanja modula, glavni program pokazuje tendenciju smanjenja.
U normalnim okolnostima, sve što se dešava u programu se dešava u
modulima. U jedan modul smestićemo srodne funkcije. Ako je već napisan
neki modul koji zadovoljava naše potrebe, nikada nećemo pisati neki svoj
koji radi isti posao.

Opšta struktura modula je saobrazna principu skrivanja informacija koji je


formulisao Parnas početkom 70-ih. Ovaj princip nalaže da detalji
realizacije modula treba da budu skriveni od klijenta. U ovom slučaju
klijent je drugi program, ne programer.

Na primer, za realizaciju tačke u Dekartovom koordinatnom sistemu


postoje dva načina: pomoću vektora sa dve komponente (jedna predstavlja
apscisu, druga ordinatu) i pomoću tipa sloga (gde jedno polje predstavlja
apscisu, a drugo ordinatu).. Ova dva načina su potpuno različita, jer svaki
način zahteva drugi kôd i sl. ali su ravnopravni – ni jedan nije bolji od
drugog.

Po principi skrivanja informacija klijent ne sme znati je li ovaj problem


rešen korišćenjem dvokomponentnog vektora ili sloga. Detalji realizacije
su nedostupni klijentu, čak ako se i promene, klijent to ne sme da primeti.
Problem će biti tako rešen da modul ima isto ime u oba slučaja, iste ulazne
i iste izlazne parametre.

U svojoj strukturi moduli moraju imati dva dela:

interfejs modula: klijent ga vidi, to je deo kroz koji se vrši interakcija između klijenta i modula, pa
je ovo u stvari deo za spregu sa klijentom.
U idealnom slučaju (a skoro uvek je i stvarno tako) interfejs se nikad ne menja, eventualno se dopunjava,
jer bilo kakva izmena interfejsa povlači promenu svih poziva klijenata tom modulu;
telo modula: ovo je obavezan deo i u Pascalu se zove implementacija. Ovaj deo sadrži pomenute
skrivene delove modula.

39
P R O G R A M S K I J E Z I K P A S C A L


Potprogram nije
modul, jer nije
autonomno realizovan,
već kao deo modula (tj.
glavnog programa).

U modulu se u principu mogu pojaviti sve komponente programskog


jezika. U Pascalu se pojavljuju potprogrami, tipovi, imenovane konstante,
a malo ređe i promenljive.

U Turbo Pascalu postoje dve vrste modula, svaki sa svojom strukturom:

 glavni program (autonomno realizovan);

 modul u užem smislu reči, koji nije izvršni kao glavni program i
nudi svoje usluge klijentima.

Šta se nalazi u modulu


Modul pre svega mora predstavljati logički zaokruženu celinu. Njega
odlikuju jaka logička kohezija i slaba logička adhezija. Pod prvim
terminom podrazumevamo da modul sadrži logički povezane delove.
Drugi termin se odnosi na slabu logičku zavisnost jednog modula od nekog
drugog (loose coupling). Oba termina proističu iz zahteva da je modul
autonoman.

Uniti u Turbo Pascalu


Modul u užem smislu reči u Turbo Pascalu se zove jedinica ili unit. Njena
struktura nije identična strukturi glavnog programa zbog svrhe modula i
zbog toga što je prilikom pisanja modula najvažnije poštovati princip
skrivanja informacija.

Unit se u opštem slučaju sastoji od tri (odnosno četiri) dela. To su:

zaglavlje (jednostavno je kao i zaglavlje glavnog programa);


interfejs;
implementacija i
inicijalizacija (ovaj deo je opcioni).
Zaglavlje unita
Zaglavlje ima jednostavan oblik: sastoji se od službene reči unit i imena
jedinice:
unit ime_jedinice;

Izbor imena zavisi od verzije Pascala. U Turbo Pascalu ime jedinice mora
da se poklopi sa imenom datoteke u kojoj se na disku čuva kôd te jedinice.

40
P R O G R A M S K I J E Z I K P A S C A L

Ukoliko se desi da
deklarišemo neki
potprogram u interfejsu,
a ne realizujemo ga u
implementaciji,
prevodilac će nam
prijaviti grešku.
Interfejs
Označavamo ga službenom reči interface iza koje ne stoji tačka-zarez. Ako
naš unit koristi usluge nekog drugog, onda u interfejs stavljamo referencu
na drugi unit. To se radi pomoću:
uses ime_jedinice1, ime_jedinice2, ..., ime_jediniceN;

Inače, kad god koristimo procedure i funkcije nekog unita, moramo


navesti njegovu referencu, da bi prevodilac znao da na raspolaganju ima
još neke potprograme.

U interfejsu se takođe mogu naći deklaracije tipova, konstanti,


promenljivih i potprograma.

Ako je neka procedura ili funkcija iz unita javno dostupna, onda se njeno
zaglavlje navodi u zaglavlje unita. Inače, zaglavlja potprograma u
interfejsu imaju osobinu deklaracije unapred i zbog toga je redosled
deklarisanja potprograma provizoran. Takođe je sve jedno kojim ih redom
navodimo u telu jedinice.

Implementacija
Označavamo je službenom reči implementation iza koje ne stoji tačka-
zarez. U ovom delu se nalazi realizacija procedura i funkcija deklarisanih u
interfejsu (njihov kompletan tekst uključujući i zaglavlje).

Pošto su zaglavlja potprograma zajedno sa formalnim parametrima


navedena u interfejsu, u implementaciji nije obavezno da se ponovo
deklarišu formalni parametri. Doduše, ovo se uglavnom radi, jer je
programeru dok piše potprogram lakše da vidi kako je nazvao parametre
potprograma i koliko ih ima ako još jednom ponovi celo zaglavlje u
implementaciji.

Kao što je već rečeno, redosled navođenja procedura i funkcija je


irelevantan. Takođe svaki potprogram može koristiti neki drugi u okviru
unita. Ako su nam potrebni i potprogrami drugih unita, koristimo
službenu reč uses.

Deo za implementaciju unita podseća na deklaracioni deo glavnog


programa i fizički je najveći deo unita. Takođe može da sadrži i lokalne
promenljive koje se ne vide van unita. To su interne promenljive koje služe
kao pomoć u implementaciji potprograma i imaju osobine globalnih
promenljivih za taj unit. Unit takođe sadrži i lokalne procedure i funkcije
(isto nedostupne van njega), a ređe i lokalne tipove i konstante.

41
P R O G R A M S K I J E Z I K P A S C A L


Ovog dela obično
nema, jer ima vrlo
specifičnu namenu.

Kao u interfejsu tako i u implementaciji se mogu naći reference na druge


unite i to onda kad se njihove usluge koriste samo interno. Treba voditi
računa da kružne reference nisu moguće, jedino u slučaju da se jedan unit
referencira u interfejsu drugog, a drugi u implementaciji prvog. Ovo se
retko koristi.

Inicijalizacija
Inicijalizacija služi za postavljanje nekih početnih stanja u modulu i
izvršava se samo jedanput i to kada se u zaglalvju klijenta naiđe na uses.
Inicijalizacija se najčešće koristi za postavljanje vrednosti nekih
promenljivih i ovo je jedini izvršni deo unita.

Inicijalizacija se prepoznaje po tome što počinje službenom reči begin, iza


koje slede naredbe.

Bez obzira da li unit ima inicijalizaciju ili ne, uvek se završava sa end iza
kojeg sledi tačka.

Pascalovi gotovi uniti


U Pascalu postoji velik broj gotovih unita. Od njih je najvažniji system
koji sadrži sve osnovne funkcije i procedure Pascala. Ovo je jedini unit koji
se automatski uključuje u program i ne treba se posebno navoditi.

Pored ovog, za rad u tekstualnom režimu u Pascalu bitni su i:

 crt (služi za neposredno rukovanje tastaturom i ekranom);

 DOS (malo raznovrsniji unit, sadrži potprograme za upravljanje


datotekama, direktorijumima itd.);

 graph (koristi se za rad sa grafičkim elemenatima);

 printer (komunikacija sa lokalnim štampačem).

Primer
Sledeći program predstavlja unit koji sadrži neke procedure i funkcije
potrebne za realizaciju tačke u Dekartovom koordinatnom sistemu.
Čuvamo ga u MPOINT.PAS datoteci.
UNIT MPOINT;

42
P R O G R A M S K I J E Z I K P A S C A L

INTERFACE

type TPoint = record


x, y: real
end;

procedure Create(var p: TPoint; xx, yy: real);


function GetX(p: TPoint): real;
function GetY(p: TPoint): real;
procedure Copy(from: TPoint; to: TPoint);
function Distance(p1, p2: TPoint): real;

IMPLEMENTATION

procedure Create(var p: TPoint; xx, yy: real);


begin
with p do begin x:= xx; y:= yy; end
end;

function GetX(p: TPoint): real;


begin
GetX := p.x
end;

function GetY(p: TPoint): real;


begin
GetY := p.y
end;

procedure Copy(from: TPoint; to: TPoint);


begin
to.x := from.x;
to.y := from.y
end;

function Distance(p1, p2: TPoint): real;


begin
Distance := sqrt(sqr(p1.x – p2.x) + sqr(p1.y – p2.y))
end;

END.

43
2
Tema

44
Sintaksa programskih
jezika
Ovde ćemo ukratko izložiti osnovne činjenice o sintaksi
prograsmskih jezika i reći nešto o tri najšire korišćena
sistem meta-jezika.

Aspekti svakog programskog jezika su:

 sintaksa,

 semantika i

 pragmatika.

Sintaksa sadrži pravila za građenje konstrukcija datog programskog jezika.


Čvrsto je vezana za kompajler čiji je osnovni zadatak (pored prevođenja
programa na mašinski jezik) da proveri da li je program napisan u skladu
sa sintaksnim pravilima. Drugačije rečeno, kompajler proverava da li je
neka struktura pravilno napisana i na taj način proverava da li je ta
struktura uopšte deo programskog jezika. Sintaksa programskih jezika je
po pravilu mnogo jednostavnija od sintakse govornog jezika, ali je zato
krajnje stroga.

Semantika se bavi značenjem onog što je napisano. To je interpretacija


sintaksno pravilno napisane strukture.

Pragmatika predstavlja način korišćenja jezičkih konstrukcija da bi se rešio


zadati problem.

Pošto je sintaksa programskih jezika strogo formalna, već krajem 50ih se


javila ideja da se formalno i prikaže. Prvi formalni sistem za opis sintakse
se pojavio 1960. i opisivao je sintaksu ALGOLa.

Za formalni prikaz sintakse se koristi meta-jezik. Meta-jezik je, dakle, jezik


za opis programskog jezika. Isto je formalan i postoji mnogo različitih
varijanti meta-jezika. Tri su najpoznatija: BNF, EBNF i sintaksni
dijagram. Prva dva se koriste više u svrhu formalnog zadavanja sintakse, a
treći je pogodan za njeno prezentovanje. Takođe, prva dva predstavljaju
linearnu formu, dok se treći prikazuje dvodimenzionalno.

Način za opis sintakse nekog programskog jezika postavlja pred nas jedan
osnovni problem: kako predstaviti terminale, a kako neterminale.

45
S I N T A K S A P R O G R A M S K I H J E Z I K A

Terminali su samoobjašnjavajuće konstrukcije nekog programskog jezika.


Neterminali su one konstrukcije koje treba dalje razjašnjavati. Na primer,
ako posmatramo sledeću naredbu Pascala:
while logicki_izraz do naredba;

while i do su terminali, dok su logicki_izraz i naredba neterminali (treba ih


definisati). Njih jednim imenom zovemo simboli.

Ova tri sistema meta-jezika se bave načinima za zadavanje terminala i


neterminala. Pošto kompajleri rade na meta-jezicima, treba obezbediti da
formalni sistem predstavi sve moguće oblike neterminala.

Kompajler generator
Ulaz za kompajler generator jeste sintaksa novog programskog jezika koja
se saopštava odgovarajućim meta-jezikom. Semantiku zadajemo na
osnovu nekog već postojećeg programskog jezika (najčešće je to C).
Kompajler generator nam onda generiše kompajler tog našeg novog
programskog jezika.

Bekus-Naurova forma – BNF


John Backus (tvorac Fortrana) i Peter Naur su napravili ovaj, prvi meta-
jezik, kojeg definišu sedam stavki.

1. neterminale prikazujemo između kao: <neterminal>;

2. terminali se prikazuju bez ikakvih dodatnih znakova, onako


kako se pišu u programskom jeziku;

3. simbol ::= znači jednakost po definiciji, gde se sa leve strane


nalazi terminal, a sa desne opis tog terminala u vidu kombinacije
neterminala i terminala. Ako se sa desne strane nalazi neterminal,
onda njega objašnjavamo na isti način;

4. simbol | označava isključivo ili eksplicitno navedenih elemenata.


Na primer: cifra ::= 0|1|2|3|4|5|6|7|8|9. Ili: slovo ::= A|B|C|D|E|...|Z|a|
b|c|d...|z, s tim što se u zadavanju sintakse svi elementi moraju
eksplicitno navesti. Ovde to nije slučaj zbog preglednosti;

5. ako lančamo simbole, pišemo ih jedan za drugim, npr:


<dvoznačni naziv> ::= <slovo><slovo>|<slovo>cifra>;

6. ako konstrukti ne moraju uvek imati istu dužinu koristimo


rekurziju, npr: <kard broj> ::= <cifra>|<kard broj><cifra>;

46
S I N T A K S A P R O G R A M S K I H J E Z I K A

 7. postoji i mogućnost ponavljanja nekog simbola jednom ili više


puta: {<x>} ili ograničenog ponavljanja {<x>}nm gde je m najmanji
mogući broj, a n najveći mogući broj ponavljanja.

Poboljšana Bekus-Naurova forma – EBNF


Više se upotrebljava od BNF i posebno je pogodna za kompajler
generatore. Postoje određene razlike u odnosu na BNF.

1. neterminali se prikazuju bez ikakvih dodatnih simbola. Ako se


neterminal sastoji od više reči, između njih se stavlja crtica ili donja
crta, npr: kard-broj ili kard_broj;

2. terminali se stavljaju pod navodnike, npr: "while";

3. simbol = predstavlja jednakost po definiciji;

4. isključivo ili se predstavlja istim simbolom |;

5. lančanje se vrši na isti način kao kod BNF;

6. rekurzija je identična;

7. ponavljanje može biti nula ili više puta (kod BNF je jednom ili
više puta). Ograničeno ponavljanje je isto kao za BNF.

8. simbolima srednjih zagrada [ i ] se označava opcija;

9. simbolima malih zagrada ( i ) se označava objedinjavanje


izraza;

10. na kraju svakog meta-izraza se stavlja tačka . koja


označava njegov kraj.

Na primer:

"FOR" kont_prom ":=" pv ("TO"|"DOWNTO") kv "DO" naredba ";".

47
S I N T A K S A P R O G R A M S K I H J E Z I K A

Sintaksni dijagram
Kao što je već rečeno, najviše se koristi za prezentaciju sintakse forme i to u
glavnom čitaocu u knjigama. Sintaksni dijagram je čitljiviji od BFN i
EBNF. Sredstva za prikazivanje sintaksnog dijagrama su grafička.

Sintaksni dijagram kao celina ima jednu ulaznu granu na kojoj piše naziv
konstrukcije koju definišemo. Terminale prikazujemo krugovima ili
zaobljenim pravougaonicima, neterminale pravougaonicima i međusobno
ih povezujemo usmerenim granama, pa se lančanje postiže upravo na taj
način. Ekskluzivno ili ne postoji. Ponavljanje se postiže isto upotrebom
usmerenih grana.

Svaka konstrukcija dobijena prolaskom kroz dijagram je pravilna.

Primeri
cifra

0 1 2 3 4 5 6 7 8 9

kard_broj
cifra

48
3
Tema

49
Osnovi teorije
algoritama
Ovde ćemo videti kako se definiše algoritam i biće dat
kraći prikaz tri najpoznatija algoritamska sistema:
rekurzivne funkcije, Tjuringove mašine i normalne
algoritme Markova.

Šta je to algoritam?

A lgoritam je vrlo star pojam i ne podleže strogom definisanju (kao i


neki pojmovi iz geometrije, npr. tačka, prava i ravan). Dakle, ne
postoji stroga definicija algoritma, već se on intuitivno definiše. Reč
algoritam potiče od imena arapskog matematičara iz IX veka, a njegovo
ime je Abu Jaffar Mohammed ibn Musa al Khowarizmi. Izgovor poslednje
dve reči podseća na izgovor reči algoritam.

Emiprijska definicija algortima

Algoritam je pravilo formulisano na nekom jeziku koje


jednoznačno definiše redosled operacija neophodan za
transformaciju dozvoljenih ulaznih podataka u traženi
rezultat.

Druga definicija je sintetička i formalnija je od ove empirijske. Oslanja se


na alfabet (W, skup simbola bez semantike) u okviru kojeg se definiše skup
W* – skup reči (nizovi simbola) u kojem se nalazi i prazna reč.

Posmatraćemo dva alfabeta: X i Y, gde je X ulazni alfabet (sadrži


dozvoljene ulazne podatke), a Y izlazni alfabet (sadrži izlazne rezultate). X i
Y su najčešće isti. Nad skupovima reči X* i Y* se definiše alfabetski
operator G, tako da je G  X*  Y*, pri čemu G nije funkcija. G vrši
transformacije reči iz X* u reć iz Y*. Uvešćemo i pojam kodeksa Z koji
predstavlja skup zakona koji bliže određuju kako G vrši transformaciju
ulazne u izlaznu reč. Odavde sledi sintetička definicija algoritma.

Sintetička definicija algortima

Algoritam je uređena četvortka (X*, Y*, G, Z).

50
O S N O V I T E O R I J E A L G O R I T A M A


Izračunljive
funkcije su one čija se
vrednost može izračunati
algoritmom.

Iako su X*, Y* i G strogo definisani, Z je definisan intuitivno, pa je i ova


definicija intuitivna.

Dva algoritma mogu biti ekvivalentni na dva načina: po izvršavanju ili


funkcionalno. Ako su isti po izvršavanju, isti ulazni podaci daju iste
rezultate. Ako su dva algoritma funkcionalno ekvivalentni, onda im se i
kodeksi poklapaju (na primer, ekvivalentni algoritmi imaju isti BDA, ali
drugačije nazvane promenljive).

Algoritmi su deterministički (za isti ulaz daju isti izlaz) ili sholastički.

Algoritamski sistemi
Algoritamski sistem je sredstvo za zadavanje algoritma. Postoji čitav niz
poznatih algoritamskih sistema (npr. opšti BDA koji nije do kraja precizno
definisan ili oni vezani za konkretne probeleme, koji opet nisu dovoljno
opšti).

Tri algoritamska sistema su najpoznatiji i sva tri su ekvivalentna, tj. mogu


se svesti jedan na drugi. To su rekurzivne funkcije, Tjuringove mašine i
Markovljevi normalni algoritmi.

Rekurzivne funkcije
Ovo su najstariji algoritamski sistemi. Vrednost funkcije za neki argument
računa se poznatim postupkom na bazi vrednosti funkcije za prethodne
vrednosti argumenta. Na primer, ako računamo faktorijel broja n (n!)
imamo za f(0) = 1, a dalje f(i) = i  f(i-1), i = 1, 2, ..., n.

Churchova teza kaže: klasa izračunljivih funkcija poklapa se sa klasom


rekurzivnih funkcija i od najvećeg je značaja za aritmetičke funkcije
definisane na skupu celih nenegativnih brojeva, tj f : Nk  N. (Aritmetičke
funkcije su diskretne.)

Služeći se aritmetičkim funkcijama, možemo napraviti bijektivno


preslikavanje skupa reči nekog alfabeta (T*) na skup prirodnih brojeva
(N). Znači, sve reči iz skupa T* možemo kôdirati elementima iz N.

Osnovna teza teorije algoritama sa stanovišta rekurzivnih funkcija kaže da


za svaki algoritam koji obrađuje skupove celih nenegativnih brojeva
postoji (funkcionalno) ekvivalentan algoritam koji odgovara nekog
rekurzivnoj funkciji.

51
O S N O V I T E O R I J E A L G O R I T A M A

Rekurziju ostvarujemo pomoću šest sredstava, podeljenih u dve grupe: tri


bazne funkcije (od kojih moramo poći) i tri osnovne operacije. To su:

1. nula funkcija: preslikava sve argumente u 0, tj. 0n(x1, x2, ..., xn) =
0;

2. funkcija naslednik: vrednost funkcije je jednaka vrednosti


funkcije argumenata uvećanog za jedan, tj. S(x) = x', x' = x + 1 ;

3. projekcijska funkcija: Inj(x1, x2, ..., xj, ..., xn) = xj ;

4. operacija supstitucije: supstitucija funkcija h1, h2, ..., hm u


funkciju g na sledeći način: f(x1, x2, ..., xn) = g(h1(x1, x2, ..., xn), h2(x1,
x2, ..., xn), ..., hm(x1, x2, ..., xn)) ;

5. operacija proste rekurzije: kada iz dve funkcije dobijamo treću,


npr. rekurzija po y: f(x1, x2, ..., xn, 0) = g(x1, x2, ..., xn, y + 1) i f(x1,
x2, ..., xn) = h(x1, x2, ..., xn, y, f(x1, x2, ..., xn, y)). U prostom obliku
pišemo: f(0) = a, f(y+1) = h(y, f(y)) ; i

6. operacija minimizacije: izvodi se iz neke aritmetičke funkcije


g(x1, x2, ..., xn, y). Ciljna funkcija f(x1, x2, ..., xn) se dobij
minimizacijom g, tako što za vrednost f usvajamo najmanje celo
nenegativno rešenje jednačine g(x1, x2, ..., xn, y) = 0. Ako takvo
rešenje ne postoji, onda funkcija nije definisana za te vrednosti
argumenata.

glasi: za funkciju f : Nk  N, k  N  {0} kaže


Definicija rekurzivne funkcije
se da je rekurzivna ako postoji bar jedan konačan niz funkcija f 1, f2, ..., ft
gde je ft  f takav da svaka funkcija fi iz tog niza zadovoljava sledeća dva
uslova:

 fi je bazna funkcija i

 fi se dobija od prethodnih funkcija u nizu supstitucijom,


prostom rekurzijom ili minimizacijom.

Primer
Sabiranje celih nenegativnih brojeva kao rekurzivna funkcija:

f1(x) = I1(x)

f2(x) = S(x)

f3(x, 0) = I1'(x)

f3(x, y + 1) = S(f3(x, y)) = f2(f3(x, y))

52
O S N O V I T E O R I J E A L G O R I T A M A

f3  f = x + y.

53
O S N O V I T E O R I J E A L G O R I T A M A

UTM se može svesti na


specijalnu.

Tjuringove mašine
Pod Tjuringovim mašinama podrazumevamo familiju matematičkih
apstrakcija koje predstavljaju jednu apstraktnu mašinu. Ovde
posmatramo algoritam sa stanovišta onoga ko ga izvršava, tj. Tjuringove
mašine prikazuju apstraktnog izvršioca algoritma i njegovo ponašanje
kojim se strogo definisan ulaz transformiše u strogo definisan izlaz.

Definisao ih je Alan Turing 1936. godine. Svaki današnji računar


predstavlja Tjuringovu mašinu. Kad je 1943. napravljen ENIAC (John
von Neumann) on je u suštini predstavljao Tjuringovu mašinu.

Zadatak Tjuringove mašine je da reč iz nekog ulaznog alfabeta


transformiše u reč nekog izlaznog alfabeta. Zbog toga je glavni problem
način zadavanja alfabetskog operatora.

Postoje dve grupe Tjuringovih mašina i to su specijalne i univerzalne


Tjuringove mašine. Današnji računar je po svojoj prirodi jedna
univerzalna Tjuringova mašina.

Specijalne Tjuringove mašine


Imaju tri funkcionalne celine i to su: beskonačna traka, upisno-čitajuća
glava i upravljački blok.

 Beskonačna traka igra ulogu memorije i može ih biti jedna ili


više, ali su sve ekvivalentne. Na beskonačnoj traci se nalazi ulazna
reč i na njoj se izvode sve transformacije. Na početku rada se na
beskonačnoj traci nalazi neka ulazna reč od slova, a levo i desno od
te reči su prazne ćelije (označavamo ih sa B).

 Upisno-čitajuća glava izvršava operaciju učitavanja nekog slova


sa ili upisivanja nekog slova na trenutnu poziciju. Ima mogućnost da
se pomeri za jedno mesto u levo ili desno U početnom trenutku se
nalazi iznad prvog slova ulazne reči.

 Upravljački blok upravlja radom Tjuringove mašine i uvek se


nalazi u nekom stanju. Skup stanja upravljačkog bloka nazivamo
unutrašnji alfabet Tjuringove mašine i u njemu mora da se nađe
tačno jedno početno stanje i jedno ili više završnih stanja. Kad se
54
O S N O V I T E O R I J E A L G O R I T A M A

 upravljački blok nađe u jednom od završnih stanja, sesija je


završena. Na početku rada je upravljački blok u početnom stanju.

Rad Tjuringove mašine se odvija po koracima (pokretima) u tri razdela.


Prvo se menja stanje upravljačkog bloka. Zatim se vrši upis slova koje nije
B na poziciju iznad koje je upisno-čitajuća glava. Glava se pomera za
jednom mesto u levo ili desno. Ovaj postupak se ponavlja dok se
upravljački blok ne nađe u nekom završnom stanju. Rezultat rada će biti
reč koja se nalazi između dve prazne ćelije.

Među simbolima neke reči može se pojaviti i prazan simbol koji ne utiče na
reč i označavamo ga sa . Treba voditi računa da prazna ćelija (B) ne
sadrži nikakav podatak. Samim tim ako sadrži prazno slovo (), ona nije
prazna.

Ne postoji način da se unapred zna da će za neku ulaznu reč Tjuringova


mašina posle konačnog broja koraka doći u jedno od završnih stanja, tj. ne
postoji način da unapred znamo hoće li algoritam dati rezultate ili ne.

Formalna definicija Tjuringovih mašina


Formalno se Tjuringove mašine definišu kao uređena šestorka (, , , ,
q0, F), gde je:

  – unutrašnji alfabet;

  – spoljašnji alfabet (skup svih simbola koji se mogu naći na


beskonačnoj traci uključujući i B i );

  – skup ulaznih slova (podskup skupa , u opštem slučaju:  


 \ {B}, tj. sigurno B  , ali možda i neki drugi element iz  takođe
ne pripada );

  – funkcija prelaza (obavlja pokrete, a odluka o pokretu se


donosi na osnovu stanja upravljačkog bloka i simbola iznad kojeg
se trenutno nalazi upisno-čitajuća glava, tj.  : (  )    ( \
{B})  {L, R};

 q0 – početno stanje;

 F – skup završnih stanja.

55
O S N O V I T E O R I J E A L G O R I T A M A


Konfiguracija Tjuringove mašine
Konfiguracija Tjuringove mašine je uređena trojka (q, , i) i ona određuje
njeno ukupno stanje.

Ukupno stanje Tjuringove mašine je određeno stanjem upravljačkog bloka


(q), aktuelnom reči na beskonačnoj traci () i položajem upisno-čitajuće
glave (i), tj. njenim rastojanjem od početka aktuelne reči (redni broj slova
iznad kojeg se glava nalazi).

Funkcije prelaza
Funkcija prelaza se zadaje u vidu pesudnonaredbe, npr: qa  q'a'.

Drugi način za njihovo zadavanje (ne isključuje prvi) je u vidu


funkcionalne sheme. To je matrica koja po jednoj dimenziji ima oznake
stanja, a po kolonama oznake iz spoljašnjeg alfabeta. Na preseku se nalaze
urđene trojke (q', a, P).

Osnovna teza teorije algoritama sa stanovišta Tjuringovih mašina kaže da


se svaki algoritam može zadati u obliku funkcionalne sheme specijalne
Tjuringove mašine, tj. svaki algoritam je jedna Tjuringova mašina.

Univerzalne Tjuringove mašine


Postavlja se pitanje možemo li definisati Tjuringovu mašinu koja bi mogla
predstavljati svaki algoritam. To je univerzalna Tjuringova mašina. Ima tu
osobinu da ne služi za izvršavanje jednog algoritma, već svakog algoritma.
Funkcionalna shema se kodira, tako da i ona postaje deo ulaza.

Univerzalne Tjuringove mašine na ulazu imaju reč koju treba obraditi


zajedno sa uputstvom za njenu obradu.

U savremenim računarima, ova uputstva zovemo programima.

Primer
 T = (, , , , q0, F)

  = {S1, S2, S3}

  = {0, 1, , B}

  = {0, 1}

 q0 = S1

 F = {S3}
56
O S N O V I T E O R I J E A L G O R I T A M A

 funkcionalna shema ove Tjuringove mašine je:

0 1  B
S1 (S2, 0, R) (S2, 1, R) - -
S2 (S2, 1, R) (S2, 0, R) - (S3, , R)
S3 - - - -

57
O S N O V I T E O R I J E A L G O R I T A M A

Normalni algoritmi Markova


Ovo je najnoviji algoritamski sistem, izveden je 1954. iz BDA. Posmatraju
algoritam sa stanovišta izvršavanja.

Osnovni problem kojim se bave NAM je kako prikazati alfabetski operator


G na neki standardni način.

Kod zadavanja alfabetskog operatora (transformacije ulazne reči) Markov


je uočivo da postoje svega dve osnovne operacije: operacija obrade i
operacija odluke. Tako da se Markovljevi algoritmi prikazuju primenom
ove dve operacije:

Postoji i treća operacija, to je smena nad tzv. tekućom reči:   .

Na početku algoritma se poijavljuje početna vrednost tekuće reči na kojoj


se izvršava strogo definisana sekvenca smena na sledeći način: u tekućoj
reči se locira prva s leva pojava podreči  i zatim se ona zameni sa .

Na primer: tekuća reč je 9215125415181512,  je 151, a  je 0. Posle smene


dobijamo: 92025415181512.

Naravno, ako smena ima više, mora se voditi računa o redosledu njihovog
izvršavanja. Tako intuitivno podrazumevamo strogo uređen niz smena
koje se primenjuju u tekućoj reči.

Ako podreči  nema, ništa se neće dogoditi.

U svakom slučaju, mora postojati posebna vrsta nula ili više završnih
smena koje se izvršavaju ako ni jedna druga više ne može da se izvrši. Njih
označavamo tako što stavimo tačku iza strelice, npr.  . .

Uobičajena oznaka za prazno slovo je . Proširivanje reči radimo na


sledeći način:   , tj. ispred tekuće dodajemo .

58
O S N O V I T E O R I J E A L G O R I T A M A

Definicija normalnih algoritama Markova


MNA definišemo koristeći sledeće definicije:

 i je smena;

 x je reč;

 P(i, x) je predikat, tj. x = i(x)

 K(i) pokazuje T ako je i završna smena, tj.  ako nije.

Opšti oblik Markovljevih normalnih algoritama


Opšti oblik Markovljevih normalnih algoritama prikazan je sledećom
šemom:

početak

ulaz:
X

DA NE
P(1, x) x = 1(x) K(1)

NE DA
1
DA NE
P(2, x) x = 2(x) K(2)

NE DA
1

DA NE
P(i, x) x = i(x) K(i)

NE DA
1
1

izlaz:
X

kraj

59
O S N O V I T E O R I J E A L G O R I T A M A

Fundamentalne osobine
algoritama
To su diskretnost, primenljivost, determinisanost i masovnost.

 Diskretnost je definiciona osobina, jer kontinualni algoritmi ne


postoje

 Algoritam je primenljiv na date ulazne podatke ako nakon


konačnog broja koraka daje rezultate.

 Detereminisanost znači da algoritam za iste ulazne podatke daje


isti rezultat. To važi samo za determinističke algoritme. Pored njih
postoje i sholastički koji nemaju ovu osobinu, pa ovo nije
esencijalna osobina algoritama.

 Masovnost znači da je algoritam primenljiv na veliki broj


ulaznih podataka. Tu postoje određeni problemi. Prvo, ne znamo
šta znači veliki broj ulaznih podataka Dalje, postoje algoritmi koji
nemaju ulazne podatke. Treće, neki algoritmi se pišu za samo jedan
tačno određeni ulazni podatak.

60
4
Tema

61
Strukturirano
programiranje
subtitle

S trukturirano programiranje predstavlja tehnologiju za sistematsku


izradu softvera. Definisano je kao paradigma 70-ih godina koja je
kasnije dopunjena sistem analizom. Tada je konačno postalo moguće
pratiti ceo životni ciklus softvera.

Metodologija koja je prethodila strukturiranom programiranju je


kompozitno programiranje. Korišćeno je od pojave viših programskih
jezika, pa do kraja 60ih, kad je nastala prva velika softverska kriza.

Prva velika softverska kriza je bila uzrokovana činjenicom da nije postojao


softver koji bi mogao iskoristiti novonastale velike mogućnosti hardvera.
Zbog toga su organizovani stručnjaci koji su dijagnostifikovali da je
problem u tome što se u to vreme kompleksan softver nije mogao pisati bez
grešaka.

1968. holandski hemičar E. W. Dijkstra piše čuveni kontroverzni članak:


„Goto Statement Considered Harmful“ u kojem izlaže rezultate
istraživanja po kojima je broj grešaka u softveru proporcionalan broju
upotreba goto naredbe.

Konačno je 1969. definisan programski jezik koji je omogućio pisanje


programa bez upotrebe goto naredbe. U pitanju je Pascal Niklausa
Wirtha.

1972. Dijkstra, Hoare i Dahl su napisali knjigu „Structured Programming“


po kojoj je cela ova oblast i dobila ime. U toj knjizi se nalaze tri članka koji
se između ostalog bave rešavanjem problema bez upotrebe goto i
strukturama podataka.

Tih godina je razrađena i teorija modula. Najveću zaslugu za to ima Parnas


koji je definisano čuveni Princip skrivanja informacija (IHP).

Ovde je bitno pomenuti i sukcesivnu (hijerarhijsku) dekompoziciju programa.


Znači, od najkompleksnijeg načina zadavanja problema njegovim
rastavljanjem na jednostavnije celine dolazimo do određene proizvoljne
dubine.

62
S T R U K T U R I R A N O P R O G R A M I R A N J E

Pod strukturiranim programiranjem podrazumevamo skup


tehnika za razvijanje programskih modela koji koriste strogo
definisane upravljačke strukture i strukture podataka.

Sredstva za analizu algoritama


Osnovno sredstvo za analizu algoritma jeste graf toka programa. To je
digraf (orjentisani graf) koji pokazuje redosled izvršavanja operacija u
programu. Graf toka programa možemo definisati i kao BDA redukovan
na najosnovnije elemente.

Graf toka programa se sastoji od tri elementa:

1. funkcionalni čvor (proces) transformiše neke


informacije. Ima jedan ulaz i jedan izlaz;

2. predikat ima jedan ulaz i dva izlaza;

3. kolektor ima dva ulaza i jedan izlaz.

Primer

Na gornjem dijagramu možemo uočiti jedan od podgrafova. Njega možemo


prikazati posebnim simbolom obrade ako želimo da uprostimo glavni graf.

63
S T R U K T U R I R A N O P R O G R A M I R A N J E

Pravilni programi
Klasa programa koja se razmatra kao ciljna klasa se zove pravilni program.
Pravilni program zadovoljava tri uslova:

1. ima tačno jednu ulaznu granu

2. ima jednu izlaznu granu

3. kroz svaki čvor prolazi se bar jednom od ulaza do izlaza

Prva dva uslova nalažu da ceo pravilni program možemo zameniti tačno
jednim čvorom, a treći uslov eliminiše mogućnost beskonačnih ciklusa i
izolovanih (nedostupnih) delova programa.

Pravilni potprogram
Pravilni potprogram je sastavni deo nekog programa koji je takođe
pravilan. Na datom primeru grafa toka programa zaokružen je jedan
podgraf koji je takođe i pravilan program.

Potprograme uvodimo zbog načina uočavanja dekompozicije programa na


prostije delove. Dekompoziciju vršimo dokle je god moguće poštovati
pravilnost potprograma. Dakle, pronalazimo potprograme koji ne mogu
da se dekomponuju na pravilne potprograme. Takvi potprogrami su prosti
potprogrami.

Prost program je pravilan program čiji svaki pravilan potprogram ima


tačno jedan čvor. Dakle, prost program može da sadrži druge pravilne
programe, ali to su samo procesi i ništa više.

Odavde vidimo da prosti programi predstavljaju neke od osnovnih


naredbi jednog programskog jezika.

Analiza algoritama
Analiza algoritama se direktno bavi problemom koji iskazi treba da
postoje u nekom programskom jeziku. Izgrađena je oko dva centralna
pojma: pojma pravilnog programa i pojma prostog programa.

Kao i dva algoritma isto i dva programa mogu biti funkcionalno


ekvivalentni (za isti ulaz generišu isti izlaz) i ekvivalentni po izvršavanju
(ako ulazne podatke obrađuju na isti način do izlaznih).

Analiza i odnos prostih programa nas navode na određivanje pojma baze


strukturiranih programa. To je skup prostih programa čijom se
superpozicijom (kombinovanjem) može realizovati svaki pravilan
program. Treba skrenuti pažnju da baza strukturnih programa po

64
S T R U K T U R I R A N O P R O G R A M I R A N J E

definiciji nije minimalna, tj. ona može da sadrži i „višak“ prostih


programa. Dakle, baza je redundantna.

Strukturirani program je program sastavljen od prostih programa iz


zadate baze. Dakle sledi da je strukturiran program pravilan program, ali
to ne znači da u njemu po definiciji nema skokova.

Pojam strukturiranog progama je relativan, jer se definiše u odnosu na


zadatu bazu. Tako je jedan program u odnosu na jednu bazu strukturiran,
ali ne mora biti strukturiran u odnosu i na neku drugu bazu.

Kao kandidati za sastavljanje baze razmatraju se programi sa jednim, dva,


tri i četiri čvora, ali naravno ne svi koji zadovoljavaju ovaj kriterijum (npr.
oni koji nemaju funkcionalne čvorove nisu od interesa za bazu, jer „ne
rade ništa“).

Ovakvih programa ima sedam:

1. f
funkcionalni čvor

2. f g sekvenca

3. S
T
 IF-THEN
P

4. S
T
P WHILE-DO

5. 
T REPEAT-UNTIL
S P

6. T f

P IF-THEN-ELSE
 g

7. g T

 DO-WHILE-DO
f P

65
S T R U K T U R I R A N O P R O G R A M I R A N J E

Programi 3 i 6 su programi selekcije, a 4, 5 i 7 iteracije. Ovi prosti


programi predstavljaju osnovne naredbe svih strukturnih programskih
jezika, tj. preslikavaju se u naredbe tih programskih jezika. Odavde
vidimo da je skup naredbi u Pascalu teorijski zasnovan.

Primetimo da među ovih sedam prostih programa ne postoji ekvivalent


pascalske naredbe case. To je zbog toga što case nije prost program, jer ga
možemo zameniti pomoću if-then-else strukture. Razlog za uvođenje case
naredbe je taj što nam je tako programiranje olakšano.

Takođe primetimo da u realizaciji ovih sedam struktura ne postoje


skokovi.

Strukturna teorema i programiranje bez goto


Izdvaja se jedna posebna baza strukturnih programa. Nju čine sekvenca,
iteracija tipa while-do i selekcija tipa if-then-else. Pomoću ove baze se može
izvesti svaki program i na osnovu nje pravimo druge baze koje su nam
potrebne.

1966. C. Boehm i G. Jacopini su izveli strukturnu teoremu koja pokazuje da


se svaki pravilan program može ostvariti superpozicijom ove tri strukture,
tj. da se može ostvariti bez upotrebe skokova, što je bilo ključno za
rešavanje problema koji su tražili uvođenje strukturiranih programa.

Za dokaz teoreme uzećemo jedan pravilan program prikazan sledećim


grafom toka programa:

Naš cilj je da definišemo program


0 funkcionalno ekvivalentan ovom koji se
može sastaviti upotrebom samo pomenute
tri strukture.
A 1
Uočićemo redosled izvršavanja čvorova sa
GTP i pokazaćemo da se može obezbediti
2 3
mehanizam za određivanje sledećeg čvora
T  koji će biti izvršen, a da taj mehanizam
P B
sadrži samo tri date strukture.

Da bismo to postigli, prvo ćemo na GTP


proizvoljnim simbolima obeležiti čvorove (na primeru, uzeti su celi
nenegativni brojevi). Okolinu (ono što se na grafu nalazi pre ulaza i pre
izlaza) isto obeležavamo proizvoljnim simbolom (uzeta je 0). Kolektore ne
označavamo, jer su to pomoćni simboli GTP. Označavanjem čvorova se u
stvari omogućava da svaka ta oznaka bude argument pomenutog
mehanizma čiji je rezultat takođe oznaka čvora.

Zatim, definišemo matricu prelaza koja čini osnovu za određivanje koji će


se čvor sledeći izvršiti. To je kvadratna matrica koja ima onoliko vrsta i
66
S T R U K T U R I R A N O P R O G R A M I R A N J E

kolona koliko ima oznaka čvorova uključujući i oznaku okoline.


Realizujemo je kao logičku matricu, tako što je popunjavamo po vrstama.
Za svaki čvor u nekoj vrsti upisujemo T i . T upisujemo u onoj koloni
koja odgovara čvoru koji neposredno sledi čvoru iz date vrste. Zbog toga u
svakoj vrsti postoji samo jedno T.

Pošto dva čvora mogu da slede neki predikat (ili jedan ili drugi, ne oba) u
odgovarajuće kolone nećemo staviti oznake T i , već stavljamo P i P , od
kojih opet samo jedna može biti tačna i ona nam pokazuje koji se čvor
sledeći izvršava.

Matrica prelaza za gornji graf toka programa izgleda ovako:

0 1 2 3
0  T  
1   T 
2  P  P
3 T   
Sada, definišemo funkciju next koja preslikava skup oznaka čvorova na
samog sebe:
function next(n: integer): integer;
begin
j := 0;
while not L[n, j] do j := j + 1;
next := j;
end;

Sad možemo napraviti prelaznu strukturu koja vodi krajnjoj strukturi.


Koristićemo još jednu teoremu, to je teorema o kanoničkoj formi. Ona kaže:
za svaki pravilan program postoji ekvivalentan program koji se sastoji od
jedne iteracije while-do unutar koje se nalazi struktura case sa onoliko
paralelnih grana koliko ima procesa i predikata u grafu toka programa.

Dakle, kanonička forma za naš primer je:


begin
n := 1; {oznaka prvog čvora koji se izvršava}
while n <> 0 do {0 je oznaka okoline}
case n of
1: begin {obraditi n}; n := next(n) end;
2: begin {obraditi n}; n := next(n) end;
...
k: begin {obraditi n}; n := next(n) end;
end
end;

Sada možemo formulisati strukturnu teoremu: svaki pravilan program


može se transformisati u ekvivalentan formalno strukturiran program uz
korišćenje tri osnovne upravljačke strukture: sekvence, iteracije tipa while-
67
S T R U K T U R I R A N O P R O G R A M I R A N J E

do i selekcije tipa if-then-else. Primetimo da se case ne uklapa u ovu


teoremu, ali tu strukturu vrlo lako zamenjujemo ugnežđenom strukturom
if-then-else.

Minimalna baza strukturiranih programa


Baza koja se sastoji od sekvence, iteracije while-do i selekcije if-then-else
nije minimalna. Možemo isključiti strukturu if-then-else (tj. zameniti je
strukturom while-do) i onda opet prikazati pravilne programe pomoću
struktura iz ove (sada minimalne) baze.

If-then-else možemo zameniti sa while-do na sledeći način:


q : p; r : not p;

if p then A else B 

while

while
q
r
do
do
begin
begin
A,
B,
q
r
:
:


not
not
q
r
end;
end;

68
S T R U K T U R I R A N O P R O G R A M I R A N J E

Uzroci nestrukturiranosti
programa
Strukturiran program je relativan pojam, jer se odnosi na bazu. Ukoliko
ne postoji referenca na neku bazu, pojam strukturiranog programa se
odnosi na programe koji su pisani bez upotrebe skokova ili uopšte koji se
odnose na bazu izgrađenu od sekvence, iteracije tipa while-do i selekcije
tipa if-then-else.

Postoji pet uzroka za nestrukturiranost programa, tj. postoji pet struktura


koje ako se neka od njih pojavi kao podgraf GTP onda je program
nestrukturiran i mora se koristiti goto.

To su sledeće strukture:

 nepravilan put iza selekcije

 T

69
S T R U K T U R I R A N O P R O G R A M I R A N J E

 repeticija sa više izlaza

 repeticija sa više ulaza

70
S T R U K T U R I R A N O P R O G R A M I R A N J E

 repeticije koje se preklapaju

 paralelne repeticije (ovo je inače i nepravilan program)

T T

 

71
S T R U K T U R I R A N O P R O G R A M I R A N J E

Strukturiranje programa
Strukturiranje programa se bavi problemom eliminisanja skokova. Oni
ostaju kao opcija jedino za eventualno iskakanje iz nekog ciklusa. Skokove
eliminišemo transformacijom programa koji ih koristi u funkcionalno
ekvivalentni koji ih nema.

Postoje dva načina za ovu transformaciju: možemo napisati program iz


početka izbegavajući skokove ili koristiti neku od metoda za
transformaciju. Ovaj drugi metod je više korišćen. Najpoznatija metoda je
Aschroft-Manna i bazira se na dokazu strukturnih teorema.

Metoda Aschroft-Manna
Primer
Transformisaćemo program dat sledećim GTP u funkcionalno
ekvivalentan program.

0 To se radi na sledeći način:

 prvo označimo čvorove i okolinu;

A 1  uvodimo jednu upravljačku


promenljivu, sukcesivnim proveravanjem
njene vrednosti izvršiće se odgovarajući
2 čvor;
T
P  zbog ubrzanja procesa, vrednost idućeg
 čvora nećemo tražiti u matrici prelaza, već
se ta vrednost zadaje eksplicitno.
3 B

4
Ova metoda je izuzetno pogodna za automatizaciju.
T
Q
Bazira se na transformaciji nestrukturiranog
 programa (sa goto skokovima) u program bez goto
naredbi.

72
S T R U K T U R I R A N O P R O G R A M I R A N J E

Evo kako izgleda algoritam tog programa:

n1

T
n=1


A
n2

T T
n=2 P n1
 
n3

T
n=3


B
n4

T T
n=4 Q n2

 
n0


n=0
T

Pisanje programa bez upotrebe skokova


Ovo ostvarujemo hijerarhijskom (ili sukcesivnom) dekompozicijom
programa. Najčešće se koristi top-down razvoj programa koji predstavlja
vrlo prirodan način za pisanje programa uopšte rešavanje kompleksnih

73
S T R U K T U R I R A N O P R O G R A M I R A N J E

problema. Program razbijamo na jednostavnija rešenja koja se sukcesivno


izvršavaju.

Primer
 Rešiti sistem linearnih jednačina Ax = b reda n, Ax = b, n.

Sa teorijskog aspekta, jasno je da problem rastavljamo na problem unosa


podataka, određivanja rešenja i izdavanja rezultata. Naravno, svaki od
ovih problema se može dekomponovati na još jednostavnije probleme.
Tako da dekompoziciju problema vršimo do nivoa naredbe programskog
jezika.

Svaki od ovih nivoa dok ne stignemo do naredbe u stvari predstavlja


komentar u programu koji opisuje postupak rešavanja problema.

REŠITI
Ax = b, n

ulaz: odrediti izlaz:


n, A, b rešenja x

odrediti odrediti
A-1 x = A-1b

Rešavanje sistema linearnih jednačina Ax = b, n.

U praksi, ulaz i izlaz nećemo dekomponovati na jednostavnije probleme,


jer su jasni sami po sebi. Doduše, problem određivanja rešenja
dekomponujemo na neke podkorake čiji broj zavisi od toga kako rešavamo
sistem. Na slici je dat jedan primer. Ispod ovog nivoa nećemo ići kad je u
pitanju ovaj zadatak, jer su dalji postupci jednostavni.

Ovakav način rešavanja problema otvara mogućnost paralelnog timskog


rada, zbog toga što su poslovi algoritamski nezavisni. Druga mogućnost
koja nam se otvara jeste korišćenje gotovog softvera.

Ova metoda više nije toliko popularna, njen osnovni nedostatak je taj što je
algoritamski orijentisana.

74
5
Tema

75
Strukture podataka
U dosadašnjem izlaganju najviše reči je bilo o
algoritmima. Ovde ćemo se baviti jednom podjednako
bitnom komponentom svakog programa – strukturama
podataka.

Pojam podatka

N ajosnovniji pojam u računarstvu uopšte jeste pojam podatka. U


memoriji računara se ne nalazi ništa osim podataka (Van
Neumannova koncepcija). Tu se misli na podatke u užem smislu
reči (vrednosti nekih promenljivih) i uputstva kako se ti podaci obrađuju
(programi). Pre konstruisanja ENIAC-a, program je bio realizovan
mehanički.

Podaci odgovaraju diskretnim, zapisanim činjenicama o


fenomenima iz kojih se izvlače informacije. Informacija je
svako povećanje znanja.

Jedinice posmatranja zovemo entiteti. Entitet predstavlja stvar, subjekt,


pojam ili događaj. Svaki podatak se vezuje za neki entitet, pa podatak
definišemo kao uređenu četvorku: (naziv entiteta, naziv osobine, vrednost
osobine, vreme). Na primer: (Petar, težina u kg, 70, decembar 2002.).

Da bi mogli manipulisati podacima, oni moraju biti uređeni. Podatke


možemo definisati kao skupove. Na primer, treba proveriti da li je data
ulazna vrednost (10) elemenat skupa S = {-5, 10, 11, 12, 25}. Znači, treba
kreirati odgovarajući algoritam koji će porediti datu vrednost sa
elementima skupa, tj. sa njegovim prvim, drugim itd. elementom. Postavlja
se pitanje kako odrediti redosled elemenata, ako znamo da je skup
neuređena struktura.

Dakle, mora postojati bar jedno uređenje podataka. Tako da, ako skup S
snabdemo uređenjem, to više neće biti skup. Uređen skup se zove struktura.

Bez strukture podataka nema programa.

Prvi programski jezici (Fortran, BASIC, Cobol) su bili prilično siromašni


strukturama podataka.

Strukture podataka i tipovi podataka su vrlo bliski pojmovi.

76
S T R U K T U R E P O D A T A K A


U Pascalu, Wirth je izjednačio po značaju algoritamski i deklarativni deo
(u kojem su date strukture podataka). On je pokazao da je struktura
podataka potpuno ravnopravna u odnosu na algoritam i da je to stabilniji
deo programa.

A1 A2 Ai An

Odnos algoritma i strukture podataka

Ako posmatramo gornju šemu gde su prikazani algoritmi A1, A2, ..., An
koji svi pristupaju nekoj strukturi podataka S, jasno je da izmena nekog
od algoritama Ai verovatno neće imati uticaj na drugih n-1 algoritama. Ali
svaka izmena strukture S će gotovo sigurno izazvati izmene u skoro svim
algoritmima.

Značaj struktura podataka


Značaj struktura podataka ilustrovaćemo na primeru. Tu se jasno vidi
koliki je uticaj struktura podataka na algoritam.

Treba napisati Pascal program za manipulaciju sa matricama. Program


treba da omogući pristup elementima matrice, obradu tih elemenata,
brisanje, dodavanje novih itd.

Postavlja se pitanje koju strukturu podataka će koristiti naš program.


Uzećemo da je matrica definisana kao izvedeni pascalski tip array:
var A: array[1..m, 1..n] of <tip>;

U ovom slučaju, pristup elementima rešen je na nivou programskog jezika:


A[i, j] := t;
m := A[k, l];

A takođe i obrada elemenata:


for i := 1 to m do for j := 1 to n do Obradi(A[i,j]);

77
S T R U K T U R E P O D A T A K A

Postavlja se pitanje, kako manipulisati matricom ako su m i n veliki


brojevi. Npr, ako su m i n 1000, naša matrica ima milion elemenata, što
traži prilično velik memorijski prostor za smeštanje tih elemenata. Takođe,
pristup i obrada elemenata može trajati prilično dugo. Dakle, učinićemo
znatno ozbiljniji zahvat i razmotrićemo druge načine za realizaciju
strukture podataka.

U inženjeriji je vrlo čest slučaj da u matricama sa velikim brojem


elemenata, vrednost najvećeg broja tih elemenata je nula. Takve matrice se
zovu retke matrice. Zašto onda ne bismo obratili pažnju samo na one
elemente čija je vrednost različita od nule?

Prvo, memorisaćemo samo one čija je vrednost različita od nule. Time smo
matricu pretvorili u niz slogova (p je mnogo manje od m i n.):
var B: array[1..p] of record
vrednost: T;
vrsta, kolona: integer
end;

Sada obrađujemo samo elemente od B:


for k := 1 to p do obradi(B[k].vrednost);

Ovim smo smanjili troškove memorije i vreme obrade, ali sada pristup
elementima A više nije jednostavan. Pristup elementu A[i,j] možemo rešiti
na primer na sledeći način:
k := 1; nadjen := false;
while (k <= p) and (not nadjen) do
if (B[k].vrsta = i) and (B[k].kolona = j) then
nadjen := true
else k := k + 1;
if nadjen then x := B[k].vrednost else x := 0;

Još je komplikovaniji postupak za dodavanje novog elementa u A.

Definicija strukture podataka


Postoji mnogo definicija strukture podataka: od onih intuitivnih do
složenih, strogo matematičkih definicija (npr. uređen skup podataka,
strana 76).

Elemente jedne strukture čine:

 pre svega, skalari;

 neke druge strukture podataka;

 relacije kojima su povezani elementi date strukture.

78
S T R U K T U R E P O D A T A K A

Uređeni par (p, ) jeste skalar, gde je p podatak, a  relacija. Pošto je p


izolovan podatak, ova relacija jeste prazna relacija.

Relacije kojima su međusobno povezani elementi strukture mogu biti


sasvim jednostavne ili pak vrlo složene. Na primer, niz je uređen relacijom
susedstva definisanom između dva elementa na sledeći način {(x i, xi+1) | i =
1, 2, ..., n -1}. Složena relacija je na primer relacija predmet-nastavnik, gde
jedan predmet može da predaje više različitih nastavnika, a sa druge
strane svaki nastavnik može da predaje više različitih predmeta.

U daljem razmatranju posmatraćemo relaciju elemenata nekog niza.


Uzećemo da je ova relacija netranzitivna. Definisaćemo neposredno
susedstvo kao (xi, xi+1) ili posredno kada je xi prethodnik xi+1 i xi+1 je
sledbenik xi.

Skalar je struktura podataka. Ako su S1, S2, ..., Sk strukture


podataka i ako je S = {S1, S2, ..., Sk} tada je uređena n+1-orka
(S, r1, r2, ..., rn) struktura podataka, gde su r1, r2, ..., rn relacije
reda dva ili većeg u skupu S. U opštem slučaju ova n+1-orka je
promenljiva u vremenu.

Grafovi
Za grafičko prikazivanje struktura podataka
se koriste grafovi. Graf je skup snabdeven
a1 a2
jednom binanom relacijom, tj. uređeni par (S,
r). Sastoji se od čvorova (elementi skupa S).
Relacije među tim čvorovima se prikazuju
tako što ih povezujemo granama koje ne
a3 a4
moraju biti orjentisane. Orjentisan graf se
zove digraf (directed graph).

Digrafi su modeli jedne velike klase struktura


podataka. Ne svih, jer se ne mogu sve Digraf
strukture prikazati na ovaj način. U matematici, čvorove grafa
označavamo kružićima, dok je kod struktura podataka uobičajeno da se za
oznake koriste pravougaonici.

X1 X2 X3 ... Xn-1 Xn

Graf niza

Za svaki čvor na digrafu se definiše ulazni stepen čvora, a to je broj grana


koje ulaze u čvor, i izlazni stepen čvora, tj. broj grana koje izlaze iz njega.

79
S T R U K T U R E P O D A T A K A

Operacije nad strukturama podataka


Definicije ovih operacija nisu obuhvaćene definicijom strukture podataka,
jer ih intuitivno pridružujemo toj definiciji. Razlog zbog čega podatke
stavljamo u strukturu (strukturiramo ih, uređujemo) je da bismo nad
njima vršili neke operacije.

Postoje tri grupe operacija:

1. primitivne operacije su sasvim proste operacije i uglavnom se


pojavljuju u sastavu drugih operacija, tj. retko se pojavljuju kao
izolovane. Treba spomenuti operaciju Empty, koja je logička
operacija i vraća vrednost true ako je struktura podataka prazna,
tj. nema elemenata. Druga bitna je operacija Full, takođe logička
koja pokazuje da li je memorijski prostor namenjen čuvanju neke
strukture podataka popunjen.

Treba primetiti da ove dve operacije nisu dualne, jer je Empty


vezana za definiciju neke strukture podataka, a Full sa
neposrednom realizacijom te strukture u memoriji. Pošto se
jedna struktura može realizovati na više načina, Full u jednom
slučaju može da ima smisla, a u drugom ne;

2. osnovne operacije su najbitnije i služe za međusobno


razlikovanje struktura podataka koje imaju isti digraf. Postoje tri
grupe ovih operacija: operacije pristupa, uklanjanja i dodavanja.
Ove operacije ulaze u definiciju strukture podataka.

Osnovne operacije su:

a) pristup – to su semantički jednostavne operacije. Svode se na


uočavanje (izdvajanje) nekog elementa iz strukture podataka
radi čitanja ili izmene podatka (informacionog dela, tj. sadržaja
elementa). Izdvojeni element se zove tekući element i postoji
mehanizam za izmenu tekućeg elementa.

Treba definisati kriterijum pristupa nekom podatku. To je


predikat koji daje T za tačno jedan element iz strukture.
Ako se takav element može naći u datoj strukturi, pristup je
uspešan. U suprotnom, traženog elementa nema.

Postoje tri načina pristupa u okviru strukture podataka od


kojih su svi ravnopravni, ali nejednako zastupljeni. Kod
pojedinih struktura podataka neki od ovih načina nisu
mogući ili jednostavno nemaju upotrebni značaj. Način
pristupa može biti:

80
S T R U K T U R E P O D A T A K A

I prema poziciji: kriterijum je mesto elementa, može se dati i


implicitno, koristi se kod nizova;

II prema informacionom sadržaju (asocijativni pristup,


traženje): kao argument traženja se daje deo informacionog
sadržaja elementa i to takav deo da potpuno definiše dati
element. Tada se algoritamski proverava da li takvog
elementa ima u datoj strukturi. Ako on postoji, traženje je
uspešno i na raspolaganje se stavlja ostatak informativnog
sadržaja elementa. Deo informativnog sadržaja koji
jednoznačno definiše svaki element se naziva ključ;

III navigacija – ovaj način pretraživanja izgrađen je oko pojma


tekućeg elementa. Tekući element uvek postoji i njemu se
implicitno pristupa;

b) uklanjanjese vrši na sledeći način: izvuče se traženi element iz


strukture i potom se ažuriraju veze, kako bi se uklonile sve
prema sada nepostojećem elementu;

c) dodavanje se izvodi slično kao uklanjanje, jedina razlika je što se


novi element umeće u strukturu, a veze se ažuriraju kako bi se i
novi element našao raspoređen na pravo mesto.

Sve tri osnovne operacije mogu biti definisane sa određenim


ograničenjima, a uklanjanje i dodavanje uopšte ne moraju biti
definisane za neku strukturu.

3. složene operacije su:

a) pretraživanje – razlika između ove i operacije traženja je u tome


što rezultat ove operacije može biti više od jednog elementa;

b) sortiranje
– to je uređivanje (po pravilu) linijske strukture
podataka po nekom kriterijumu

c) kopiranje;

d) spajanje dve ili više struktura u jednu;

e) razlaganje jedne strukture podataka na dve ili više.

Klasifikacija struktura podataka


Klasifikacija struktura podataka vrši se na tri osnovna načina:

1. prema nivou apstrakcije;

81
S T R U K T U R E P O D A T A K A

2. prema mestu memorisanja;

3. prema tipu relacije.

Klasifikacija struktura podataka prema nivou apstrakcije


Postoji izuzetno velika i bitna razlika između logičkih i fizičkih struktura
podataka. Nije isto kako logički definišemo neku strukturu i kako je posle
realizujemo u memoriji računara.

Logička struktura je ona koja se pojavljuje u modelu i nezavisna je od


računara, programa i memorije. Data rekurzivna definicija strukture
podataka se odnosi upravo na ovu logičku strukturu.

Fizička struktura podataka (tj. fizička realizacija) predstavlja strukturu


onako kako je implementirana u računaru.

Jasno je da za jednu logičku strukturu može da postoji više načina njene


fizičke realizacije.

Primer
Uzećemo primer strukture matrice. Njena logička struktura se sastoji od
vrsta i kolona. Sa druge strane, memorija računara je po svojoj prirodi
jednodimenzionalna (linijska) struktura. Zbog toga moramo smisliti
određeni način kako da dvodimenzionalnu strukturu transformišemo u
jednodimenzionalnu i kasnije tu jednodimenzionalnu opet u
dvodimenzionalnu. U Fortranu, na primer, to je bilo rešeno tako što se
matrica razdvajala na kolone i onda su one upisivane sekvencijalno jedna
iza druge u memoriju.

a b c d

e f g h a b c d e f g h i j k l
i j k l

Primer logičke i fizičke strukture matrice

Klasifikacija struktura podataka prema mestu memorisanja


Prema mestu memorisanja strukture podataka delimo na operativne i
masovne.

Operativne su one koje se čuvaju u operativnoj memoriji računara (npr.


RAM), a masovne se čuvaju u masovnoj memoriji (npr. tvrdi disk).

Razlike između ove dve kategorije su i kvalitativne i kvantitativne.


Operativne strukture su manjeg kapaciteta, ali im se brže pristupa.
Obrnuto je kod masovnih. Takođe, masovne su permanentne, dok je život
operativnih samo dok traje program.

82
S T R U K T U R E P O D A T A K A

Klasifikacija struktura podataka prema tipu relacije


Ova klasifikacija je karakteristična samo za strukure podataka tipa (S, r),
tj. za one čiji je skup snabdeven samo jednom binarnom relacijom.
Ovakvih struktura ima mnogo i za sve se može konstruisati odgovarajući
digraf.

Postoje tri vrste struktura i to su:

1. linearne strukture – imaju digraf koji zadovoljava dva uslova:


svi čvorovi osim tačno jednog imaju ulazni stepen jedan i svi osim
tačno jednog imaju izlazni stepen jedan. Drugačije rečeno, svaki
element osim jednog ima tačno jednog prethodnika i svaki element
osim jednog ima tačno jednog sledbenika. Ovaj odnos prethodnik-
sledbenik je fundamentalan za linearne strukture podataka.

Posebna varijanta linearnih struktura su tzv. cirkularne


strukture, gde svi čvorovi imaju ulazni stepen jedan i izlazni
stepen jedan.

2. strukture tipa stabla – njihov digraf se zove stablo. U stablu


postoji tačno jedan čvor s ulaznim stepenom nula. U sve ostale
čvorove ulazi tačno jedna grana. Takođe, ovaj digraf je slabo
povezan, što znači da su svaka dva čvora povezana nekim putem
bez obzira na orjentaciju grana. Bitna karakteristika je da svaki
element strukture osim jednog ima tačno jednog prethodnika, a
svaki ima jednog ili više sledbenika. Dakle, prethodnik jeste
funkcija, dok sledbenik nije.

3. mrežne strukture podataka – svaki element ima proizvoljan broj


prethodnika i sledbenika. Bitno je samo da su svi čvorovi slabo
povezani.

Klasifikacija operativnih struktura


Pojedine strukture podataka ne omogućavaju neke ili sve osnovne
operacije (uklanjanje, dodavanje, pristup). Prema ovim ograničenjima
strukture podataka mogu biti:

 statičke– ne postoji uklanjanje i dodavanje;

 poludinamičke– definisane su sve osnovne operacije, uz


specifičan pristup; i

 dinamičke– definisane su sve osnovne operacije, ali na račun


brzine i fleksibilnosti.

83
S T R U K T U R E P O D A T A K A


Nizovi mogu biti
statički i
dinamički. Ovde
ćemo se baviti statičkim
nizovima.

Statičke strukture podataka


Kod ovih struktura nije moguće uklanjanje i dodavanje elemenata, ali je
pristup veoma fleksibilan i obavlja se velikom brzinom.

Osnovni pristup je pristup po poziciji. Kod statičkih struktura je ovaj tip


pristupa unapred određen. Ovaj tip struktura se karakteriše pozicijom kao
osnovnim identifikacionim svojstvom, a svaka pozicija određena je
oznakom pozicije kojih može biti više različitih. Oznake pozicije mogu da
budu u uređenom ili neuređenom skupu.

Postoje dve osnovne vrste statičkih struktura podataka i to su:

 indeksne strukture (nizovi), koje imaju uređene oznake pozicija;

 slogovi, koji nemaju uređene oznake pozicija i

 tabele koje su nizovi slogova.

Nizovi
Nizovi spadaju u najznačajnije i najstarije strukture podataka. Zovu se i
višedimenzionalne strukture. Kod Pascala, nizovi se odnose na vektore, na
matrice i na višedimenzionalne nizove, što nije bio slučaj i sa starijim
programskim jezicima.

Nizovi su jedinstvene linearne strukture. Označavamo ih kao


uređenu dvojku A = (S(A), r(A)), gde je S(A) skup, a r(A)
relacija definisana nad tim skupom.

Pristup je dozvoljen svakom elementu niza, a uklanjanje i dodavanje nisu


definisani. Pristup elementima statičkog niza je fleksibilan i brz, jer je
pozicija elementa unapred poznata. Moguće su sve tri vrste pristupa
(prema poziciji, prema informacionom sadržaju i navigacijom). Pristup
prema poziciji je najznačajniji i ostvaruje se prema indeksu pozicije.

84
S T R U K T U R E P O D A T A K A

Niz čiji su elementi


Deskriptor je
skalari jeste vektor, a
obavezan!
niz vektora je matrica.
Kod nizova postoji podgrupa koja se naziva
multiindeksna struktura i nju definišemo rekurzivno na sledeći način.

Vektor je multiindeksna struktura reda jedan. Multiindeksna


struktura reda k je niz Nk = (S(Nk), r(Nk)) u kojem su elementi
skupa S(Nk) multiindeksne strukture reda k-1.

Fizička realizacija
Neposredna fizička realizacija jedne strukture podataka može biti:

 sekvencijalna i

 spregnuta.

Kod sekvencijalne realizacije neke strukture, zauzima se kompaktan


memorijski prostor u koji se smeštaju elementi strukture. Spregnuta
realizacija neke strukture podataka se izvodi tako što se sprega između
elementa te strukture i mesta njihovog smeštanja u memoriji ostvaruje
pokazivačima. Dakle elementi jedne strukture se mogu smestiti na
različitim lokacijama u memoriji.

Jasno je da je kod sekvencijalne realizacije neke strukture maksimalni


broj elemenata te strukture ograničen, dok kod spregnute ista struktura
teoretski može imati neograničen broj elemenata. (U stvarnosti nas
ograničava samo količina raspoložive memorije.) Sa druge strane, osnovne
operacije se obavljaju mnogo brže na strukturama koje su realizovane
sekvencijalno, nego na onim realizovanim spregnuto.

Svaka struktura podataka je snabdevena jednom dopunskom strukturom


koja sadrži podatke o toj osnovnoj strukturi i naziva se deskriptor.
Deskriptore najčešće kreira kompajler, a ako oni ne postoje u
programskom jeziku, kreira ih sâm programer.

Niz se u programskim jezicima realizuje sekvencijalno. Deskriptor niza


može da sadrži ime tog niza (X), vrstu podataka (V) i oznaku tipa (char). A
mora da sadrži adresu početka niza (adr(X[-5])), opseg indeksâ (-5 do 4) i
veličinu jednog elementa u osnovnoj adresnoj jedinici (na današnjim
računarima to je bajt - u primeru 1 bajt).

X: array[-5..4] of char;
x[- x[- ... x[3 x[4 V X
5] 4] ] ] adr(X[-5])
Realizacija niza u memoriji -5 4
char 1

85
S T R U K T U R E P O D A T A K A

Deskriptor niza

Ako pretpostavimo da je p najmanja i k najveća vrednost indeksa i da su p


i k celi brojevi, onda pristup u opštem slučaju adresa elementa kojem
pristupamo se određuje tako što se sabere adresa početka niza sa
proizvodom rastojanja tekućeg elementa od početka niza i veličine jednog
elementa. Dakle: adr(B[i]) = adr(B[p]) + adr(i-p) * l(T). Vidi se da u ovom
postupku dimenzije niza ne igraju ulogu, pa se samim tim opseg nigde ne
prenosi u potprogram.

Kad su u pitanju multiindeksne strukture, pristup se može ubrzati ako je


adresa unapred poznata. Na primer, BASIC i Fortran koriste metod
linearizacije koji se svodi na „sečenje“ matrice na vrste ili kolone. Ovaj
metod predviđa da se primeni jedna formula koja nam odmah daje adresu
elementa. Npr. ako je M niz definisan na sledeći način:
M: array[p1..k1, p2..k2, ..., pn..kn] of T;

onda bi se adresa niza računala na sledeći način:


n
adr M j1 ,...,jn    adr M p 1 ,...,p n    l T     jm  p m   D m
m 1

Prvi način za izračunavanje Dm je ako sečemo matricu na vrste: Dm = (km + 1


- pm + 1 + 1)  Dm + 1, Dn = n, m = n - 1, n - 2, ..., 1 i ovo je rekurzija unazad.
Drugi način je ako matricu sečemo na kolone i tada je Dm = (km - 1 - pm - 1 +
1)  Dm - 1, D1 = 1, m = 2, 3, ..., n i ovo je rekurzija unapred.

Iliffeovi vektori
Illifeovi vektori se primenjuju ako želimo veliku brzinu obrade, a pri tom
to što ova struktura traži nešto više memorije nije problem. Ovu strukturu
mora programer sâm da realizuje, jer nije sastavni deo ni jednog
programskog jezika. Na primer:
X: array[2..3, -1..1, -2..-1] of T;

Illifeovi vektori se retko programiraju na Pascalu, već na nekom drugom


programskom jeziku tipa Assemblera. To se radi, na primer, na C-u koji
ima brzinu približnu brzini Assemblera. C nudi i tu prednost što se za
donji indeks niza podrazumeva 0, a ne 1 kao kod Pascala.

Kao i nizovi, Iliffeovi vektori najčešće imaju dve dimenzije, a retko kad
više od tri. Jedina razlika u odnosu na strukturu niza je u tome što Iliffeovi
vektori ne sadrže adrese, već samo vrednosti elemenata.

Za svaki nivo indeksâ se odvaja jedan Iliffeov vektor koji se svaki stvara na
bazi raspona indeksâ. Ako nivo indeksâ ne obuhvata nulu, stvaraju se
pseudoelementi u kojima ne postoji ništa. Za svaki sledeći nivo indeksa

86
S T R U K T U R E P O D A T A K A

Dve bitne osobine slogova


su semantička
konvergencija i
pitanje relacije.
formiramo skup Iliffeovih vektora. Za poslednji nivo, ovaj se skup opet
dopunjava do nule.

deskriptor 0
1 a2 = a1 + 3l(T)
a1 2
3 x[3, 1, -2]

a3 = a2 + 1l(T)
x[2, -1, -2]
-1 -1
0 0
1 1

2 2 2 3 3 3
-1 2 0 2 1 2 -1 3 0 3 1 3
-2 -1 -2 0 -2 1 -2 -1 -2 0 -2 1
-1 -1 -1 -1 -1 -1

Shema Illifeovog vektora

Slogovi
Formalno gledano, slogovi podsećaju na nizove. Svaki skalar možemo
shvatiti kao trivijalni slog sa jednim elementom.

Ovo je još jedna statička struktura koja se ne može proširivati, a ne mogu


se ni uklanjati neki elementi. S druge strane, pristup je omogućen svakom
elementu.

Semantička konvergencija se odnosi na interpretaciju informacionog


sadržaja sloga. Element sloga sâm za sebe nema semantiku, tj. postoji
takva međuzavisnost elemenata sloga da oni samo zajedno imaju značenje.
Zbog te međuzavisnosti, elemente sloga drugačije zovemo polja.

Pitanje relacije se postavlja u vezi sa 'A' x y


definisanjem odgovarajuće relacije
među elementima sloga kako bi on oslikavao realni model. Na primer, ako
relaciju definišemo kao binarnu, a uzmemo da slog opisuje tačku u
Dekartovom koordinatnom sistemu dolazi do neslaganja sa modelom. Ime
tačke je u relaciji sa apscisom, ali ne i sa ordinatom (ili obrnuto). Zbog toga
se relacija drugačije uređuje.

87
S T R U K T U R E P O D A T A K A

Slog R je uređeni par (S(R), r(R)), gde je S(R) skup poljâ, a


r(R) relacija koja se sastoji od jedne uređene n-torke u koju
ulaze svi elemenit iz S(R). r(R) = {(x1, ..., xn), n = |S(R)| i (xi, xj
 S(R)) i  j  xi  xj.

Za slogove važi da se vrlo retko pojavljuju izolovani. Najčešće su elementi


neke druge složenije strukture podataka. Jedan od specijalnih slučajeva je
deskriptor.

U programskim jezicima, tip sloga karakteriše da su njegova polja u


opštem slučaju nejednakog tipa. Pristup poljima je definisan kao pristup
po poziciji, dok navigacije i pristupa po sadržaju nema. Pristup po poziciji
se obavlja putem oznake pozicije i bitno je da u skupu pozicija ne postoji
uređenje, tj. ne zna se da li postoji i šta je sledbenik, odnosno prethodnik.
Pristup po poziciji ostvarujemo bijektivnim preslikavanjem naziva polja
nekog sloga na poziciju.

Fizička realizacija
Teorijski, fizička realizacija sloga je dvojaka: i sekvencijalna i spregnuta. U
praksi je ovo retko, jer je osnovna (koja je i gotovo uvek zastupljena)
sekvencijalna realizacija. Može se pojaviti i kombinacija ove dve.

U programskim jezicima opšte namene slog je isključivo sekvencijalno


realizovan, a ukoliko se nađe potreba za spregnutom realizacijom,
ostavljeno je prostora da je program sâm kreira. Dakle, jedina fizička
realizacija podržana direktno od strane programskog jezika jeste
sekvencijalna. Tipičan primer izolovanog sloga, a dakle i spregnuto
realizovanog, jeste deskriptor.

Za sekvencijalnu realizaciju vezuje se problem različitih vrsta polja u


jednom slogu, pa na primer polja mogu da imaju različite dužine. Dakle
svako polje se opisuje na različit način i stoga se svako opisuje posebno.
Zbog ovoga je deskriptor sloga znatno složeniji od deskriptora bilo koje
druge strukture podataka. Programski jezici po pravilu direktno
podržavaju strukturu sloga, tako da programer najčešće ne dolazi u dodir
sa deskriptorom.
A0 A0 + 30 A0 + 40 A0 + 42 A0 + 44
prezime ime indeks god_upisa god_studij
a
Kompaktan memorijski prostor odvojen za skladištenje sloga

Tipičan deskriptor sadrži podatke na nivou celog sloga. Na primer, može


da sadrži indikator tipa (koji pokazuje da se radi o slogu), naziv sloga,
adresu početka memorijskog prostora rezervisanog za skladištenje sloga,
može da sadrži ukupnu dužinu sloga, ali mora da sadrži broj polja u slogu.
88
S T R U K T U R E P O D A T A K A

R STUDENT 5 A0 Informacije o svakom polju se memorišu


posebno i to: indikator tipa, dužina u
S 30 prezime 0 osnovnim adresabilnim jedinicama, naziv i
S 10 ime 30
adresa polja. Adresa se može dati relativno
I 2 indeks 40
I 2 god_upisa 42
(u odnosu na početak memorijskog prostora
I 2 god_studija 44 odvojenog za slog) ili apsolutno. Ako je tip
Primer deskriptora sloga sa deskriptorom nekog od polja slog onda se ceo deskriptor
polja tog sloga smešta u opis datog polja. Ovo važi
za svako polje.

Kod spregnute realizacije, u opisu poljâ ne stoje adrese tih polja u


memoriji, već pokazivači na dinamičku memoriju.

Kad se u programu traži pristup polju, prevodilac za dato ime polja


pregleda deskriptor, traži opis odgovarajućeg polja, i tu pročita njegovu
adresu. Ako je ona data apsolutno vraća njenu vrednost ili računa početnu
adresu polja, ako je adresa data relativno.

Primena sloga je kranje široka i teško je izdvojiti neku za koju se može reći
da preovladava. Karakteristično je da se svaka baza podataka sastoji
upravo od slogova.

Tabele
Struktura tabele predstavlja niz čiji su elementi slogovi. Ova struktura ima
posebne primene, jer objedinjuje slogove.

Zavisno od tipa niza, tabela može biti statička ili dinamička.

Tipične obrade su sortiranje i traženje na osnovu zadatog ključa (dakle


pristup je po informacionom sadržaju). Traženje može biti od prvog na
dalje ili neka specifična vrsta traženja.

89
S T R U K T U R E P O D A T A K A

U prevodu, stack znači


„naređana gomila“.

Poludinamičke strukture
podataka
Za ove strukture podataka uz određena ograničenja definisane su sve tri
osnovne operacije. Ova ograničenja nisu iznuđena, već su posledica
posebnih namena ovih struktura podataka. Dinamičke strukture podataka
promenljive su u vremenu.

Uvešćemo jednu primitivnu funkciju koja će nam pokazivati je li neka


struktura prazna i nazvaćemo je Empty(F), gde je F neka poludinamička
struktura podataka. Drugačije rečeno, ova funkcija nam pokazuje da li
data struktura F ima elemenata. Treba napomenuti da je stanje prazne
strukture specijalno stanje.

U poludinamičke strukture podataka spadaju stek, red, dek i sekvenca.


Zajednička osobina im je da su linearne i da je pomenuta funkcija
Empty(F) definisana za svaku od njih.

Stek (stack)
Ovo je najvažnija od poludinamičkih struktura s obzirom na svoju ulogu,
ima je svaki program (makar i implicitno). Teorijski, ova struktura je
najjednostavnija od svih.

Stek je uređeni par L = (S(L), r(L)), gde je r(L) binarna


relacija definisana nad skupom S(L).

 x i1 , x i  i  1, 2, n  1 n  2
S(L) = {x1, x2, ..., xn} i r  L   
  n2

Xn Xn-1 ... Element koji je bez


X1
prethodnika (u smislu
relacije - prvi) se zove vrh steka. Element koji je bez sledbenika (u smislu
relacije - poslednji) se zove apsolutno dno steka. Vrh steka je od najvećeg
interesa.
90
S T R U K T U R E P O D A T A K A

Pored spomenute primitivne funkcije Empty(L), za stek je definisana i


funkcija Prvi(L), koja očitava prvi element strukture.

Sve tri osnovne operacije se vrše isključivo na vrhu: pristupa se implicitno


vrhu, vrh se uklanja, a novi element se dodaje „ispred“ vrha steka. Tj.
pristup je omogućen samo poslednje upisanom elementu, a takođe se
uklanja poslednji upisan elemenat. Odavde je stek dobio drugačiji naziv
LIFO red (Last In First Out).

Pristup se izvršava operacijom Top, koja ne mora biti izvršena kad se


pozove. Da li će se Top izvršiti ili ne, zaviis od toga da li je stek prazan.
Uklanjanje se vrši operacijom Pop, a dodavanje operacijom Push. U praksi
su Top i Pop najčešće kombinovani, pa se kaže da je očitavanje
destruktivno.

Od složenih operacija tu je operacija pražnjenja steka (uklanjanje svih


elemenata dok Empty ne pokaže true). Ova operacije je više teorijske
prirode, jer je osnovna osobina steka velika brzina, a ovom operacijom
usporavamo obradu.

Fizička realizacija
Fizička realizacija steka obavlja se na oba standardna načina: i
sekvencijalno i spregnuto. Osnovni način realizacije je sekvencijalni, jer je
brži što se i najviše očekuje od steka. Ovaj način uvodi ograničenje
maksimalnog broja elemenata na steku. Podrazumeva se deskriptor koji se
ne vidi. Važno je napomenuti da programski jezici nemaju ugrađen stek
kao tip podatka, ali ga svi programi imaju implicitno.

L ST
Amin vr Amax Amax Amin
h
vrh
opis
Realizacija steka u memoriji
elemenata
Deskriptor steka

Stek se proteže od minimalne adrese do aktuelnog vrha. Vidimo da


funkcija Prvi(L) u stvari očitava adresu vrha iz deksriptora steka.

Procedura Top se izvršava na sledećin način: prvo se proverava je li stek


prazan (tj. da li je vrh < Amin). Ako nije, putem primitivne funkcije Prvi(L)
se pristupi elementu na vrhu i on se očita. Uklanjanje se slično izvršava:
isto se proveri je li stek prazan, pa ako nije vrh se umanji za vrednost
veličine jednog elementa steka. Dodavanje se izvršava tako što se vrh
pomeri na sledeće mesto i upiše novi sadržaj.

Kod sekvencijalne realizacije postoji i ograničenje kada je vrh = A max i tada


dodavanje više ne može da se izvrši, dok se ne ukloni neki element. Kao
posledica ovoga uvodi se operacija Full(F) koja proverava je li stek
prepunjen.

91
S T R U K T U R E P O D A T A K A

Ukoliko se pokuša upis u prepunjen stek dolazi to tzv. overflow stanja. U


terminologiji je poznato i tzv. underflow stanje koje nastaje kad se očitava
ili uklanja element iz praznog steka. Ove dva stanja nisu dualana, jer je
underflow posledica logičkih karakteristika steka, a overflow isključivo
njegove sekvencijalne realizacije.

Nestandardna realizacija steka jeste spregnuta fizička realizacija koja


postoji samo ako je bezuslovno neophodno da se izbegne oveflow stanje.
Deskriptor tad mora da sadrži adresu vrha, a elementi su pokazivačima
spregnuti po adresi. Ovakva realizacja steka se zove i fizička lista.

Ako stek realizujemo sekvencijalno, sve tri osnovne operacije su sporije.


Kao što je rečeno, od steka se najpre očekuje brzina, pa se onda on gotovo
uvek realizuje sekvencijalno. A da bi se makar donekle izbegao problem
prepunjenosti steka, za smeštaj elemenata ove strukture odvaja se prilično
velik memorijski prostor.

Primena
Stek se primenjuje gde god se
S1
pojavljuje neka vrsta rekurzije. Na
primer kod prevođenja izraza na S2
mašinski jezik, izrazi se prvo prevode S3
iz infiksne (a+b) u postfiksnu (ab+) ili
prefiksnu (+ab) notaciju (najčešće u
postfiksnu, jer je taj zapis izraza
najsličiniji onom na mašinskom
jeziku). Kod poslednje dve za
naznačavanje redosleda izvršavanja
operacija nisu potrebne zagrade. S3
Standardni algoritam za prevođenje S2
izraza iz jedne u drugu notaciju ne S1
može da funkcioniše bez steka. stek

Prilikom rekurzije, potprogramu se mora proslediti tzv. adresa povratka


(na koju se upisuje rezultat tog potprograma). Bez obzira koliko se duboko
zalazi u rekurziju, da bi se vratili na prethodni nivo uvek se koristi
poslednja upisana adresa koja se potom ukloni. Zbog toga se koristi stek.

Dakle, druga veoma važna primena steka jeste razmena podataka među
programima i potprogramima. Skup podataka koji sadrži stvarne parametre i
adresa povratka se smeštaju na stek, odakle ih čita potprogram. On rezultate
obrade upisuje na stek, a povratni parametar na datu adresu.

92
S T R U K T U R E P O D A T A K A

potprogram A'
A A
A' P A' param.

kôd
program param. program potprogram
A'

stek
Pascalski i fortranski način razmene podataka između programa i potprograma

Ranije se postupak razmene podataka odvijao u zaglavlju potprograma.


Standardni fortranski način razmene parametara jeste da se adresa na
kojoj se nastavlja izvršavanje glavnog programa posle završetka
potprograma upiše na nultu relativnu adresu memorijskog prostora
predviđenog za potprogram. Iza tog podatka bi se nalazili stvarni
parametri, a tek potom instrukcije potprograma.

Ovaj način razmene parametara bio je nefleksibilan i narušavao je princip


da program i potprogram budu relativno nezavisne celine. Takođe,
rekurzija nije bila moguća, jer se nije moglo upisati više povratnih adresa.

Sada svi programski jezici predviđaju isključivo stek za prenos


parametara i zbog toga je stek jedna od najvažnijih struktura podataka.

Red (queue)
Red se drugačije zove red čekanja ili FIFO red (First In First Out). Ovo je
takođe jedna od vrlo važnih struktura podataka . Formalno, red veoma liči
na stek, ali je područje primene reda sasvim drugačije.

Red je uređeni par F = (S(F), r(F)) gde je S(F) skup, a r(F)


binarna linearna relacija definisana nad tim skupom.

 x i1 , x i  i  1, 2, n  1 n  2
S(F) = {x1, x2, ..., xn}, r  L   
  n2

Iz definicije reda vidimo da ima isti digraf kao i stek.

Xn Xn-1 ... X1

Digraf reda

Osobine reda su da je relacija r linearna, pristup je dozvoljen samo prvom


elementu, uklanja se takođe prvi element, a razlika u odnosu na stek je da
se dodavanje uvek izvršava iza poslednjeg elementa.
93
S T R U K T U R E P O D A T A K A

Za red su definisane dve primitivne funkcije: Prvi(F) (vidi stranu 91) i


Poslednji(F) koja vraća adresu poslednjeg elementa reda. Ova adresa se
čuva u deskriptoru. Funkcija Prvi(F) potrebna je zbog pristupa i
uklanjanja, a Poslednji(F) zbog dodavanja elemenata.

Primitivna funkcija za pristup prvom elementu reda jeste Front(F), za


uklanjanje se koristi Pop, za dodavanje Push. (Ovo su uobičajeni nazivi
funkcija). Ako uvedemo operaciju Rear(F) za pristup poslednjem elementu
reda, red gubi definicione osobine, ali se i ova struktura svrstava u redove i
nema posebno ime.

Od izvedenih funkcija bitna je Empty(F), a od izvedenih operacija to su


operacija pražnjenja reda i određivanje tzv. „dužine“ reda (broj elemenata
u redu).

Fizička realizacija
Postoje dva načina fizičke realizacije reda: sekvencijalna i spregnuta. Od
reda se, kao i od steka, očekuje brzina, pa je osnovni način sekvencijalna
fizička realizacija. Kao i kod steka, ovakvom realizacijom se izdvaja
kompaktan memorijski prostor koji će služiti za smeštanje elemenata reda.

RD F
Amax Amin
Amin poslednji prvi Amax prvi
poslednji
Realizacija reda u memoriji opis
elemenata
Deskriptor reda

Red se nalazi između adrese prvog i poslednjeg elementa. Uklanjanje


elemenata se obavlja ne jednom kraju, a dodavanje na drugom. Tako da su
oba kraja reda pokretna i nastaje problem lažne prepunjenosti reda.

Uzećemo za primer red sa prethodne slike koji sadrži jedan element x.


Posle izvršavanja operacije umetanja Push(F,a) red sadrži dva elementa, i
novi element a se nalazi „levo“ od elementa x. Izvršićemo Pop(F) čime smo
uklonili element x. Izvršićemo Push(F,b), pa Pop(F) i ako bismo sad hteli
da izvršimo Push(F,c) pošto se nalazimo na poslednjoj raspoloživoj adresi
element c ne može da se upiše u red. Ispada da je red popunjen, a očigledno
da sadrži samo jedan element.

Zbog toga pribegavamo rešenju da novi element upišemo na početak reda.


Ovo je tzv. cirkularna realizacija reda. Na ovaj način smo rešili problem
lažne prepunjenosti, ali se pojavio novi problem.

94
S T R U K T U R E P O D A T A K A

Za njegovo ilustrovanje, definisaćemo funkciju Prethodni(x,F) na sledeći


način:

x  l  F  x  A min
Prethodni x, F   
 A max x  A min

Počnimo da sukcesivno uklanjamo elemente iz reda sve dok ne bude


Prvi(F) = Poslednji(F). Sada red sadrži jedan element i ako još jednom
izvršimo Pop(F) red će postati prazan. Sada je Prethodni(Poslednji(F),
F) = Prvi(F).

Ukoliko uradimo suprotno, tj. u red upisujemo nove elemente jedan za


drugim dok ga ne popunimo, opet ćemo dobiti da je
Prethodni(Poslednji(F), F) = Prvi(F), ali u ovom slučaju to znači da je red
pun.

Dakle sada postoji nemogućnost razlikovanja potpuno praznog od potpuno


punog reda. Postoji nekoliko načina da se reši ovaj problem.

1. U deskriptoru ćemo u svakom momentu memorisati aktuelni


broj elemenata. Ovaj način usporava operacije, jer je posle svakog
upisa ili brisanja elementa potrebno pristupiti deskriptoru i
ažurirati broj elemenata. Doduše ova operacija nam omogućava da
nam je u svakom momentu na raspolaganju informacija o
aktuelnoj dužini reda.

2. U deskriptor se smešta statusno polje S koje može da ima dve


vrednosti: 0 i 1. Ako je S = 0 red je prazan, u suprotnom red nije
prazan. Tako da statusno polje i funkcija Prethodni(x,F) zajedno
daju informaciju o tome je li red prazan ili ne. Ovaj način takođe
usporava obradu reda, jer se polje S mora ažurirati posle svakog
upisa i/ili brisanja.

3. Ovaj način predviđa da se upis onemogući na jednu memorijsku


lokaciju koja se uvek nalazi iza lokacije Poslednji(F). Ako se ta
lokacija zove Prazna, onda je Prethodni(Poslednji(F), F) = Prazna.

Ukoliko sada želimo da ispraznimo niz, elemente brišemo dokle


god se Prethodni(Poslednji(F), F) ne poklopi sa lokacijom
Prvi(F). U red možemo dodavati elemente sve dok
Prethodni(Prazna, F) nije Prvi(F), tj.
Prethodni(Prethodni(Poslednji(F), F), F) nijr prvi. Ovo znači da
je red pun.

Kod spregnute realizacije ne postoji problem prepunjenosti reda. Red se


spregnuto realizuje u deskriptoru i elementi reda su slobodno distribuirani
po memoriji. Međusobno su povezani pokazivačima.

95
S T R U K T U R E P O D A T A K A

Primena
Primena redova je vrlo široka. Prilikom prenosa poruka na daljinu veoma
je bitno da one stižu istim redom kojim su poslate. Na računaru redovi
postoje kod ulaznih uređaja (npr. bafer tastature i miša). Drugi primer
reda kod računara je red čekanja za štampač.

Dek (deque)
Dek je red sa dva kraja. Odatle i engleski naziv (Double Ended QUEue).
Ova struktura ima više teorijsku primenu.

Dek objedinjava osobine steka, reda i svih sličnih struktura podataka.


Karakteriše se linearnom strukturom s tim da su sve tri osnovne operacije
definisane na oba kraja. Dakle, krajevi su ravnopravni. Označavamo ih kao
levi i desni kraj.

Dek se može realizovati i spregnuto i sekvencijalno. Ako ga realizujemo


sekvencijalno, nastaju svi problemi kao i kod sekvencijalno realizovanih
redova. Dok red cirkuliše u jednom, dek cirkuliše u oba smisla.

Dek se češće realizuje spregnuto, jer prilikom fizičke realizacije dolazi do


toga da krajevi nisu ravnopravni, jer se kretanje vrši u jednom smeru. Za
spregnutu realizaciju je vezan problem uklanjanja krajnjeg elementa. Dok
je levi lako ukloniti, moramo proći kroz celu strukturu da bismo došli do
desnog elementa.

Logička struktura deka je strogo simetrična, dok fizička nije. Kretanje se


vrši pomoću dva pokazivača, a u sprezi su po dva susedna elementa.

Sekvenca
Sekvenca je linijska struktura kod koje je pristup dozvoljen svakom
elementu, a uklanjaju se samo svi elementi odjednom. Postoji i varijanta
uklanjanja gde se uklanjaju svi elementi počev od zadate pozicije.
Dodavanje novih elemenata se uvek vrši iza poslednjeg elementa.

Sekvenca je uređeni par D = (S(d), r(D)), gde je S skup, a r


binarna relacija.

Za sekvencu su definisane sve tri vrste pristupa, ali se najviše koristi


navigacija. Za sekvencu je karakteristično da uvek ima definisan tekući
element. Pristupa se tekućeme elementu, pa sledećem iza njega itd.

Definisana je i jedna primitivna operacija koju ćemo nazvati Prvi(D). Ova


operacija kao tekući označava prvi element iz strukture. Pristup se odvija
tako što se proveri je li markiran tekući element i potom se njemu pristupa.
Zatim se pomera marker na sledeći element, pa se njemu pristupi i tako
96
S T R U K T U R E P O D A T A K A

dalje. Stoga je operacija Prvi(D) izolovana (izvršava se samo jednom na


početku pristupa elementima strukture).

Sekvencu karakteriše i njeno stanje koje je određeno ne samo rasporedom


elemenata već i vrednošću tekućeg elementa.

Posle dodavanja elementa, po pravilu taj novododati se označava kao


tekući. Pošto je pristup omogućen bilo kom elementu strukture (koji se
onda označi kao tekući), može se i ukloniti bilo koji element strukture.
Posle uklanjanja, kao tekući se može označiti prethodni ili sledeći iza tog
elementa.

Za sekvencu je karakteristična redosledna obrada. Ako procedura


PostaviPrvi(D) označava tekući element, posle njenog izvršavanja doveli
smo sekvencu u početno stanje. Zatim se pristupa redom svakom elementu
i svaki taj element se obradi na neki način (zapamtimo da i nemenjanje
elementa spada u trivijalne obrade).

Postoji veći broj operacija za rad sa tekućim elementom. Na primer,


postavljanje za tekući nekog n-tog elementa kada se počev od prvog redom
pristupa elementima dok se ne dođe do tog n-tog elementa. Treba
napomenuti da je ovim postupkom sekvenca promenila stanje iako su svi
elementi zadržali svoj informacioni sadržaj. To je zbog toga što je
promenjen tekući element.

Tipična sekvenca se ne nalazi u operativnoj, već u permanentnoj memoriji


i to je datoteka.

Fizička realizacija
Imajući u vidu da je glavni predstavnik sekvence datoteka, ova se
struktura realizuje sekvencijalno-spregnutom realizacijom, tj. mešavinom
ove dve. Ovo je jedina strukutra koja se ovako organizuje.

Ovakav način realizacije podrazumeva da se elementi sekvence nalaze u


blokovima koji mogu biti elementi i sami sebi. Ti blokovi su spregnuto
realizovani, tj. ne moraju biti susedni u memoriji, već su međusobno
povezani pokazivačima. Doduše, elementi unutar blokova su obavezno
raspoređeni sekvencijalno.

Deskriptor sekvence sadrži adresu prvog, kao i adresu tekućeg elementa.


Adresa tekućeg elementa sastoji se obavezno od oznake bloka u kom se
nalazi taj tekući i oznake samog elementa unutar datog bloka.

97
S T R U K T U R E P O D A T A K A

Dinamičke strukture podataka


Glavna karakteristika ovih struktura je da osnovne operacije nemaju
nikakvih ograničenja osim definicionih. Neke od ovih struktura su
linearne, ali postoji čitava grupa dinamičkih struktura koje su nelinearne.
Dinamičke strukture podataka su znatno fleksibilnije od statičkih i
poludinamičkih.

Pristup je uvek omogućen svakom elementu. Kod nekih dinamičkih


struktura pristup se vrši po poziciji, a kod nekih ne. Pristup po
informacionom sadržaju je najizraženiji. Navigacija je takođe moguća.

Određene strukture iz ove grupe postavljaju određena ograničenja


prilikom uklanjanja elemenata. Takva ograničenja postoje i kod
dodavanja elemenata i usmerena su praktičnoj upotrebi te strukture.
Jedino ograničenje koje sigurno postoji je da struktura po uklanjanju i/ili
dodavanju elementa ne sme promeniti svoje definicione osobine.
Uklanjanje se ograničava na račun brzine pristupa.

Postoje tri grupe dinamičkih struktura podataka. To su:

1. liste sa dinamičkim nizovima, najjednostavnije dinamičke


strukture;

2. stabla, veoma važna klasa dinamičkih strukura podataka i

3. mreže (vidi stranu 83).

Liste i dinamički nizovi


U okviru ove grupe, izdvajaju se četiri strukture:

1. jednostruko spregnuta lista;

2. dinamički niz;

3. dvostruko spregnuta lista i

98
S T R U K T U R E P O D A T A K A

4. višestruko spregnuta lista.

Jednostruko spregnuta lista je najvažniji predstavnike ove grupe, a


drugačije se zove i linearna lista ili lanac. Ova struktura je krajnje
fleksibilna.

Jednostruko spregnuta lista je uređeni par P = (S(P), r(P)),


gde je r(P) linearna relacija definisana na skupu S(P).

Ono što karakteriše ovu strukture je, prvo, da je pristup dozvoljen svakom
elementu, zatim ukloniti se može bilo koji element, a dodati se isto može
bilo gde. Jedino ograničenje postavlja činjenica da je ova struktura
linearna.

Definisane su sve tri vrste pristupa. Pristup po poziciji je nešto sporiji, jer
se ne može unapred izračunati adresa elementa. Dakle, za pristup nekom
k-tom elementu mora se pristupiti redom svakom do tog k-tog. U ovome se
ogleda razlika između statičkog niza i liste. Pristup prema informacionom
sadržaju isto zahteva da se pođe od prvog elementa dok se ne nađe traženi.
U svakom slučaju, listu možemo snabdeti mehanizmom za navigaciju i tad
će u svakom trenutku postojati jedan tekući element.

Zbog ovoga listu možemo realizovati na više načina. Svakako, postoji


primitivna funkcija Prvi(P). Ukoliko se očekuje da će biti mnogo
dodavanja na kraju liste, snabdećemo je i primitivnom funkcijom
Poslednji(P). Od liste se takođe može očekivati da bude sortirana. Tada su
elementi uređeni u rastućem ili opadajućem redosledu po vrednosti ključa.

Zbog ovoga svega se jednostruka lista mora projektovati. Moramo imati u


vidu za čega će se koristiti. Ako napravimo jednu listu za više namena, lista
će sigurno biti sporija (npr. mehanizam za navigaciju će postojati samo
ako nam je potreban).

Kao što je već rečeno, ukloniti se može svaki element, ali ovaj postupak
nikako nije trivijalan. Na primer, mora se voditi računa o specijalnim
slučajevima. Ako je lista prazna, neće doći do uklanjanja. Ako se uklanja
prvi ili poslednji element, uz njega se uklanja samo jedna veza.

Opšti slučaj uklanjanja je kad se ne uklanja ni prvi ni poslednji element i


tada se posle uklanjanja elementa, mora ubaciti nova veza kako bi očuvali
linearnost strukture. Takođe se moraju ažurirati veze za Prvi(P) i (ako
postoji) za Poslednji(P).

Ako je definisana navigacija, prilikom uklanjanja, prvo se pronađe


element koji treba ukloniti i označi se kao tekući. Posle obavljenog
uklanjanja, tekući više ne postoji i mora se voditi računa koji će element
biti novi tekući.
99
S T R U K T U R E P O D A T A K A

Svi ovi problemi su posledica velike fleksibilnosti liste.

Slični problemi nastaju i prilikom dodavanja elemenata. To može biti


dodavanje u praznu listu (kad se ne ažurira ni jedna veza) ili dodavanje
ispred prvog ili iza poslednjeg elementa. U opštem slučaju dodavanje se
izvrši između dva elementa, raskine se stara veza i dodaju dve nove. Ako
postoji mehanizam navigacije, treba voditi računa o tekućem elementu. Po
pravilu, novododati element postaje tekući element.

Takođe, postavlja se pitanje pozicije novog elementa. U listama gde


redosled elemenata nije bitan, uvek dodajemo ispred prvog da ne bismo
prolazili kroz celu listu tražeći poslednji. Ukoliko je redosled bitan,
možemo zadati poziciju novog elementa, ali se postavlja pitanje da li
element koji se trenutno nalazi na toj poziciji treba pomeriti ispred ili iza
novog elementa. (Ovaj problem se najčešće rešava pomoću dve procedure
za dodavanje, gde jedna dodaje ispred, a druga iza datog elementa.)

Ako je lista sortirana, pozicija dodavanja je unapred poznata. Nađu se dva


susedna elementa takva da je ključ jednog „manji“ od ključa novog, a
ključ ovog manji od ključa drugog elementa. Novi element se ubaci između
ta dva elementa. U sortiranu listu element se najčešće ovako dodaje, tj. lista
ostaje sortirana u svakom trenutku. U nekim specijalnim situacijama
element se dodaje bilo gde, pa se sortiranje vrši naknadno, što je sporije.

...

Logička struktura jednostruko spregnute liste liste

Fizička realizacija liste je isključivo spregnuta. Liste primenjujemo gde


god je potrebna fleksibilna struktura. Mnogi redovi čekanja operativnog
sistema imaju strukturu liste.

Dinamički nizovi su na prvi pogled veoma fleksibilne strukture. Imaju sve


osobine statičkih nizova, ali su uklanjanje i dodavanje definisani za bilo
koji element. Dakle, dinamički nizovi imaju sve osobine liste, s tim što je
pristup po poziciji znatno brži, jer se (kao kod statičkih nizova) pozicija
može lako izračunati unapred. Doduše, zbog operacija uklanjanja i
dodavanja dinamički nizovi su znatno specifičnija struktura nego liste.

Ako želimo da pristup po poziciji bude definisan kao i kod statičkog niza,
posle svakog uklanjanja i dodavanja moramo ažurirati pozicije elemenata.
Zbog ovoga su operacije spore, pa dinamički nizovi nemaju praktične
osobine liste. Takođe, fizička realizacija mora biti sekvencijalna, pa može
doći do prepunjenosti.

Primena dinamičkih nizova nije široka, ali se oni vrlo često koriste. To
zbog toga što tip podataka string ima osobine dinamičkog niza.

100
S T R U K T U R E P O D A T A K A

Dvostruko spregnute liste dosta podsećaju na jednostruko spregnute.


Koriste se mnogo više. Ova strukutra nije linearna i omogućene su veze u
oba smera. Ove liste se zovu i simetrične liste.

Dvostruko spregnuta lista je uređeni par: DP = (S(DP), r(DP)),


gde r nije linearna relacija, r = r1  r2, r1  r2 =  i
(a,b)  r 1 (b,a)  r2. Vidimo da su (S, r1) i (S, r2)
jednostruko spregnute liste.

...

Logička struktura dovstruko spregnute liste

Fizička realizacija je isključivo spregnuta, pa se dakle svaki element


proširuje sa dva pokazivača.

Treba voditi računa da dvostruka lista (tj. lista sa dve relacije) nije isto što i
dvostruko spregnuta lista. Pošto se relacija uspostavlja na bazi nekog
kriterijuma, kod ovih drugih, jedna relacija je taj kriterijum, a druga
suprotan kriterijum. Kod dvostruke liste, jedan i drugi kriterijum ne
moraju imati nikakve veze.

karakteriše da postoji više različitih relacija


Višestruko spregnute liste
među elementima. Ni jedna od ovih relacija ne mora da uključuje sve
elemente.

Višestruko spregnuta lista je uređena n+1-orka VP = (S(VP),


r1, r2, ..., rn) gde je svaki uređeni par (S, ri) jednostruko
spregnuta lista i Si  S(VP).

Logička struktura višestruko spregnute liste

Stabla
Stablo (zove se još i drvo) je izuzetno važna struktura podataka. Modelira
više fundamentalnih odnosa iz realnog svega (hijerarhijski odnosi, odnos
opšte-pojedinačno, postupak dekompozicije itd.).

101
S T R U K T U R E P O D A T A K A

Osnovna osobina stabla je da ono nije linearno. Stablo kao digraf


zadovoljava sledeće osobine:

 postoji tačno jedan čvor ulaznog stepena nula;

 u svaki čvor osim jednog ulazi po jedna grana (svaki ima tačno
jednog prethodnika) i

 stablo je slabo povezano.

Element u stablu ulaznog stepena nula se zove koren stabla. Čvorovi


digrafa iz kojih ne izlazi ni jedna grana se zovu listovi. Put u stablu je
uređena n-torka (x1, x2, ..., xn), gde su xi čvorovi. Dužina puta jednaka je
broju grana (n-1). Visina stabla odgovara broju čvorova na najdužem putu
(n). Dakle, visina stabla je dužina najdužeg puta uvećana za jedan. U
stablu postoji tačno jedan put od korena do bilo kog čvora, tj. koren je
povezan sa svim čvorovima tačno jednim putem. Najduži put u stablu uvek
počinje od korena i završava se u listu. Nivo čvora jeste udaljenje čvora od
korena. Za stabla se ne koriste termini prethodnik i sledbenik, već
nadređeni i podređeni. Red stabla odgovara najvećem proju podređenih u
stablu. Podstablo čini čvor sa svim svojim podređenim čvorovima.

1 Za ovo stablo koren je element 1, a listovi su


elementi 5, 6 i 7. Jedan od puteva čine
2 3 4 elementi 1, 2 i 5, dužina ovog puta je 2 i ovo
je jedan od najdužih puteva. Visina stabla je
5 6 7 3. Nivo korena je 0, nivo elemenata 2, 3 i 4 je
1, a nivo elemenata 5, 6 i 7 je 3. Red ovog
stabla je 3.

Postoje dva specijalna stabla, to su: puno i kompletno stablo. Kompletno


stablo reda n je takvo da svi čvorovi stabla (osim listova) imaju izlazni
stepen n. Kod punog stabla su svi putevi od korena do nekog lista iste
dužine. Ove dve osobine niti uključuju niti isključuju jedna drugu, tj. nisu
ni u kakvoj korelaciji. Najbolje je da je stablo tako konstruisano da je što
bliže punom i kompletnom stablu. Tada je operacija pristupa najbrža.

Stablo koje pokazuje dobre osobine (tj. približno je puno i kompletno) zove
se balansirano stablo. Za bilo koja dva čvora istog nivoa balansiranog
stabla važi da se broj elemenata u njihovim podstablima razlikuje najviše
za jedan element. Postoje algoritmi za balansiranje stabla i oni zavise od
konkretnog stabla. Primenom ovih algoritama ubrzavamo pristup
elementima stabla.

Stablo kao struktura podataka


Stablo ne možemo odmah precizno definisati, jer se među stablima nalaze
raznorodne strukture. Jedina zajednička osobina im je da imaju digraf
tipa stabla. Dodavanja i uklanjanje su u načelu svuda dozvoljeni, ali ipak

102
S T R U K T U R E P O D A T A K A

postoje ograničenja koja zavise od slučaja do slučaja. Npr. postoji


ograničenje reda iznad kojeg se ne može ići.

Karakteristike stabla su:

1. digraf je tipa stabla;

2. dozvoljen je pristup svakom elementu i

3. dodavanje i uklanjanje su definisani u skladu sa specifičnim


osobinama datog stabla.

Teorijski, pristup stablu je moguć na sva tri načina. Međutim, pristup po


poziciji je specifičan i redak, jer stablo nije linearna struktura. Zbog toga
se koristi pristup po informacionom sadržaju ili navigacija.

Najčešće se elementima stabla pristupa po informacionom sadržaju i ovaj


se pristup obavlja po ključu. Počinje se od korena i na bazi argumenta
traženja (ključa) i informacionog sadržaja elementa se odlučuje kojem se
sledećem elementu pristupa. Suštinski problem koji se ovde javlja je taj da
podređeni elementi istog nivoa čine skup koji nije uređen i ne možemo
odrediti prvi, drugi itd. element. Dakle, ne može se formirati algoritam koji
bi proverio da li se u tom skupu nalazi dati ključ.

Zbog toga u strukturi podataka mora postojati uređenje skupa podređenih


nekog elementa. Ovo uređenje može biti eksplicitno i tada je definisano na
nivou logičke strukture podataka i može biti implicitno kada se definiše na
nivou fizičke realizacije. Na osnovu ove osobine stabala, vrši se njihova
osnovna podela. Eksplicitno uređenje imaju tzv. n-arna stabla, a implicitno
tzv. generalisana (uopštena) stabla. Jedina zajednička osobina za ove dve
vrste je već pomenuti digraf tipa stabla.

N-arna stabla
N-arna stabla reda n su ona gde svaki element ima tačno nula ili n
podređenih. U svakom trenutku, postoji n mesta rezervisanih za smeštanje
podređenih elemenata nekog elementa, ali ta mesta ne moraju biti uvek
popunjena (mogu biti nezauzeta). Zbog toga skup podređenih nivoa n ima
osobine statičkog niza.

X X X

A B B A A B C

Prva dva stabla su binarana i razlikuju se po rasporedu elemenata, a treće je ternarno, ali pozicija c nije zauzeta

Iz ovih definicionih osobina sledi definicija n-arnog stabla.

103
S T R U K T U R E P O D A T A K A

N-arno stablo je uređena n+1-orka Tn = (S(Tn), r1, r2, ..., rn)


sledećih karakteristika: (S(Tn), r1  r2  ...  rn) ima osobine
digrafa stabla i [(a,b)  ri  (a,c)  ri]  (b = c), i = 1, 2, ..., n.

Ova druga osobina n-arnih stabala govori da različiti podređeni ne mogu


biti u istoj relaciji sa jednim nadređenim, tj. sve relacija n-arnog stabla su
funkcije. Tako je samim zadavanjem relacije za svaki element oređen
njegov podređeni.

Binarna stabla
Binarna stabla su posebna vrsta n-arnih, to su n-arna stabla reda dva. Za
ova stabla postoji jedna vrlo karakteristična izvedena operacija. To je
obilazak binarnog stabla.

B C

D E F

G H I

Logička struktura jednog binarnog stabla

Obilazak binarnog stabla


Prilikom obilaska stabla pristupa se svakom njegovom elementu u cilju
obrade. Postoji više načina da se to uradi.

Može se pristupati redom elementima na svakom nivou. Npr, za dato


stablo redosled bi bio ABCDEFGHI. Ovakav način pristupa nije čest, jer
je prilično komplikovan za izvođenje.

Za obilazak, u principu, postoji šest algoritama od kojih su po dva dualna.


Svaka od ovih metoda jeste rekurzivna i svaka se rekurzija bazira na tri
stavke:

1. prisup datom elementu;

2. njegovom levom podstablu i

3. njegovom desnom podstablu.

Pošto je redosled stavki proizvoljan, dobijamo šest algoritama.

Obilazak s leva u desno se izvodi tako što se prvo pristupa levom podstablu
(2), zatim elementu (1), pa desnom podstablu (3). Proces uvek počinje od
104
S T R U K T U R E P O D A T A K A

korena. Dakle, pristupa se korenu, ali se ovaj element ne obrađuje, već se


memoriše u neku strukturu L (za naše stablo, memoriše se A). Zatim se
prelazi u levo podstablo i opet se izvršavaju koraci 2, 1 i 3. (Sada se
memoriše B, a u sledećem koraku D). Kada smo stigli do elementa koji
nema levo podstablo (G), obrađujemo ga. Zatim obrađujemo element koji
je poslednji memorisan u strukturi L (to je D za naš primer). Obrađujemo
desno podstablo tog elementa. (Posle ovog koraka potpuno je obrađeno
podstablo D.) Nastavimo li ovim algoritmom, potpuno ćemo obraditi celo
stablo. Dakle, redosled obrade je sledeći: GDHBAECIF.

Očigledno je da je pomenuta struktura L LIFO red, tj. stek. Njega možemo


kreirati sami (sporiji način) ili se ono kreira implicitno, zbog rekurzija.

Obilazak s vrha ka dnu pretpostavlja da je redosled obrade: element, levo


podstablo, desno podstablo. Za naš primer, elemente obrađujemo sledećim
redosledom: ABDGHCEFI.

Obilazak sa dna ka vrhu se vrši na sledeći način: levo podstablo, desno


podstablo, element. Na primeru, redosled je: GHDBEIFCA.

Fizička struktura
Pošto je logička struktura stabla data na bazi fizičke, fizička struktura
stabla je određena definicijom.

N-arna stabla realizujemo isključivo spregnuto. Svi elementi imaju isti


oblik i svaki od njih proširujemo sa tačno n pokazivača. Deksriptor stabla,
između ostalog, mora sadržati adresu korena.

B C

D E F

G H I

Fizička struktura binarnog stabla sa prethodne slike

U specijalnom slučaju, stablo možemo realizovati sekvencijalno. Takvo


stablo mora biti binarno i ne sme biti veliko. Inače se za realizacuju
binarnog stabla koristi specijalna tehnika niti ili prošivki.

Tehnika niti
Pretpostavka je da imamo binarno stablo i da se očekuje intenzivan
obilazak. Svrha upotrebe niti je da se eliminiše stek i još više ubrza
obilazak. Postoje dve varijante ove tehnike, tj. prošivke mogu biti
jednostruke ili dvostruke.

105
S T R U K T U R E P O D A T A K A

Kod jednostrukih niti bira se jedan od pokazivača pridruženih elementu


(npr. desni). Ako taj pokazivač ima vrednost (pokazuje na neki podređeni
element), ostavlja se kakav jeste. Ako je njegova vrednost nil (ne pokazuje
„ni na šta“, na slici označeno *) onda se koristi za obilazak i u njega se
upiše adresa sledećeg kojem treba pristupiti. Dakle, prilikom obilaska
prate se pokazivači i prošivke.

B * C

D * E * F *

* G * * H * * I *

Stablo sa pokazivačima i jednostrukim nitima

Da nam prošivke ne bi pravile probleme prilikom obrade (tada se mora


znati koji je element nadređeni, a koji podređeni i to nam govore isključivo
pokazivači), svaki element proširujemo statusnom bajtom. On pokazuje da
li je u pitanju pokazivač ili prošivka.

Kod tehnike dvostrukih niti koriste se oba pokazivača (ako su slobodni).


Ovaj drugi se koristi za obilazak u obrnutom smeru, tj. pokazuje na
prethodni. Dvostruke prošivke koristimo samo pod pretpostavkom da se
koriste oba smera obilaska, tj. da algoritam obilazu strukturu stabla u oba
smera.

Sekvencijalna fizička realizacija


Kao što je već rečeno, ovako se realizuju isključivo binarna stabla koja
nisu velika i to u izuzetnim slučajevima.

Kao i za druge sekvencijalno realizovane strukture, odvaja se određen


memorijski prostor sa relativnim adresama. Koren se smešta u relativnu
adresu jedan. Za ostale elemente važi da ako je taj element na relativnoj
adresi k, njegov levi podređeni se smešta na adresu 2k, a desni na 2k+1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
A B C D E F G H I
Sekvencijalna realizacija stabla iz primera

Prednost ovakve realizacije je u tome što se adresa elementa može


izračunati unapred, pa je pristup direktan.

Ovakav način realizacije se koristi za statična stabla ili za ona koja se vrlo
malo proširuju (zbog vrlo lakog prepunjavanja memorije).

Binarna stabla se retko realizuju samostalno, već kao pomoćna struktura


nekih algoritama (npr. algoritma sortiranja).

106

You might also like