Documente Academic
Documente Profesional
Documente Cultură
a) ultim
Fig. 2.2 Liste circulare
d
1
d
2
d
n-1
d
n
ultim
b)
2.3 Operaii primitive asupra listelor
Accesul la informaia stocat ntr-o variabil de tip list revine efectund una
sau mai multe dintre operaiile primitive: regsirea nodului (dac exist) care
corespunde unei chei date (condiie impus asupra valorii cmpului de informaie),
inserarea unei noi componente n list, eliminarea componentei (componentelor) cu
proprietatea c valorile cmpurilor de informaie satisfac o anumit cerin i
nlocuirea cmpului de informaie corespunztor unei componente printr-o informaie
dat.
Accesarea componentelor unei liste reprezentat printr-o structur static
poate fi realizat att secvenial, ct i direct, utiliznd valorile indicelui considerat
pentru indexare, n timp ce accesarea componentelor unei liste dinamice se
realizeaz, de regul, numai secvenial, ncepnd cu prima component i continund
cu urmtoarele, pe baza valorilor cmpurilor de legtur. Convenional, numim cap
al listei dinamice pointerul a crui valoare este adresa primei componente a listei.
1. Parcurgerea integral a datelor memorate ntr-o list. Se presupune c
declarrile de tip pentru definirea structurilor de liste menionate anterior sunt
globale, relativ la procedurile descrise n continuare.
18
Structura de list n limbajul Pascal
a) Lista reprezentat prin structur static (masiv unidimensional)
procedure parcurgere1(var l:lst; n:word);
var i:word;
begin
for i:=1 to n do
prelucrare(l[i]);
end;
b) Lista reprezentat prin structur dinamic simplu nlnuit
procedure parcurgere2( var cap:lista);
var p:lista;
begin
p:=cap;
while(p<>nil) do
begin
prelucrare(p^.inf);
p:=p^.leg;
end;
end;
c) Lista reprezentat prin structur dinamic dublu nlnuit
procedure parcurgere3( var cap:lista);
var p:lista;
begin
p:=cap;
while(p<>nil) do
begin
prelucrare(p^.inf);
p:=p^.dr;
end;
end;
2. Regsirea unei date d ntr-o colecie memorat ntr-o list
n continuare se presupune c funcia egal(a,b:tip_informatie):boolean
returneaz valoarea true dac a i b coincid, altfel returneaz false. Funciile Pascal
exista1, exista2 i exista3 calculeaz valoarea true, dac data d se afl n colecia
memorat n lista dat ca argument, altfel calculeaz valoarea false.
a) Lista reprezentat prin structur static (masiv unidimensional)
function exista1(l:lst; n:word; d:tip_informatie):boolean;
var i:word;
c:boolean;
begin
c:=false;
i:=1;
while(i<=n)and(not c) do
if egal(d,l[i]) then c:=true
else i:=i+1;
exista1:=c;
end;
b) Lista reprezentat prin structur dinamic simplu nlnuit
function exista2(cap:lista;d:tip_informatie):boolean;
var p:lista;
19
Programarea calculatoarelor - Tehnica programrii n limbajul Pascal
c:boolean;
begin
p:=cap;
c:=false;
while(p<>nil)and(not c) do
if egal(d,p^.inf) then c:=true
else p:=p^.leg;
exista2:=c;
end;
c) Lista reprezentat prin structur dinamic dublu nlnuit
function exista3(cap:lista;d:tip_informatie):boolean;
var p:lista;
c:boolean;
begin
p:=cap;
c:=false;
while(p<>nil)and(not c) do
if egal(d,p^.inf) then c:=true
else p:=p^.dr;
exista3:=c;
end;
3. Inserarea unei date, d, ntr-o list
Includerea unei noi componente ntr-o list poate fi realizat, n funcie de
cerinele problemei particulare, la nceputul listei, dup ultima component din list,
naintea/dup o component cu proprietatea c valoarea cmpului de infor-
maie ndeplinete o anumit condiie. Presupunem c funcia condiie
((a,b:tip_informatie):boolean calculeaz valoarea true dac a i b verific condiia
formulat pentru inserare, altfel calculeaz valoarea false. De asemenea, procedura
atribuie(var destinatie:tip_informatie; sursa:tip_informatie) realizeaz copierea datei
sursa n destinatie.
Deoarece prin inserarea unei componente se poate ajunge la depirea
spaiului disponibil de memorie, este necesar verificarea prealabil a posibilitii
realizrii operaiei (dac se poate aloca spaiu de memorie pentru componenta de
inserat). n cazul listelor reprezentate prin structuri statice, aceast verificare va fi
realizat prin compararea lungimii efective n a listei cu dimensiunea declarat max.
n cazul listelor dinamice, este utilizat funcia Pascal predefinit MaxAvail, care
calculeaz lungimea maxim a zonelor nealocate contigue din memoria Heap.
Valoarea returnat pentru parametrul test este true, dac inserarea a fost posibil,
altfel este false.
De exemplu, inserarea la nceputul listei decurge astfel:
a) Lista reprezentat prin structur static (masiv unidimensional)
procedure inserare_la_inceput1(var l:lst; var n:word;
d:tip_informatie;var test:boolean);
20
Structura de list n limbajul Pascal
var i:word;
begin
test:=true;
if n=max then test:=false
else
begin
for i:=n downto 1 do atribuie(l[i+1],l[i]);
atribuie(l[1],d);
n:=n+1;
end;
end;
b) Lista reprezentat prin structur dinamic simplu nlnuit
procedure inserare_la_inceput2(var
cap:lista;d:tip_informatie;var test:boolean);
var p:lista;
begin
test:=true;
if MaxAvail<sizeof(nod) then test:=false
else
begin
new(p);
atribuie(p^.inf,d);
p^.leg:=cap;
cap:=p;
end;
end;
c) Lista reprezentat prin structur dinamic dublu nlnuit
procedure inserare_la_inceput3(var
cap:lista;d:tip_informatie;var test:boolean);
var p:lista;
begin
test:=true;
if MaxAvail<sizeof(nod) then test:=false
else
begin
new(p);
atribuie(p^.inf,d);
p^.dr:=cap;p^.st:=nil;
cap:=p;
end;
end;
Procedurile de inserare la nceputul listei pot fi folosite i pentru crearea unei
liste n care s fie memorat o colecie de date {d
1
, d
2
,, d
n
}. Procedura copiaza(var
d:tip_informatie; var i:word) realizeaz copierea n d a datei d
i
din colecia
considerat. Utiliznd procedurile de inserare deja descrise, operaia de creare a unei
liste poate fi realizat astfel:
a) Lista reprezentat prin structur static (masiv unidimensional)
procedure creeaza1(var l:lst; n:word; var test:boolean);
var i,j:word;
21
Programarea calculatoarelor - Tehnica programrii n limbajul Pascal
d:tip_informatie;
begin
test:=true;
if n>max then test:=false
else
begin
i:=1;
while(i<=n) do
begin
copiaza(d,i);
inserare_la_inceput1(l,i,d,test)
end;
end;
end;
b) Lista reprezentat prin structur dinamic simplu nlnuit
procedure creeaza2(var cap:lista;n:word;var test:boolean);
var i:word;
begin
i:=0; cap:=nil;
test:=true;
while(i<n)and(test) do
begin
i:=i+1;copiaza(d,i);
inserare_la_inceput2(cap,d,test);
end;
end;
4. Eliminarea (tergerea) unei date, d, dintr-o list
Modificarea coninutului unei liste prin eliminarea uneia sau mai multor
componente poate fi descris secvenial, astfel nct este suficient s dispunem de o
procedur care realizeaz eliminarea unei singure componente.
Criteriile de eliminare pot fi formulate diferit, cele mai uzuale fiind: prima
component, ultima component, prima component care ndeplinete o anumit
condiie, respectiv componenta ce precede/urmeaz prima component care
ndeplinete o condiie dat.
n aceste cazuri este necesar verificarea existenei n lista considerat a
componentei ce trebuie eliminat. Verificarea asigur i testarea faptului c lista
prelucrat este vid sau nu. Analog operaiilor de inserare, n cadrul procedurilor
urmtoare, parametrul test returneaz valoarea true, dac eliminarea este efectiv,
altfel returneaz false.
De exemplu, eliminarea primei componente dintr-o list are loc astfel:
a) Lista reprezentat prin structur static (masiv unidimensional)
procedure elimina_prima1(var l:lst; var n:word; var
d:tip_informatie;var test:boolean);
var i:word;
begin
test:=true;
if n=0 then test:=false
else
begin
atribuie(d,l[1]);
22
Structura de list n limbajul Pascal
for i:=1 to n-1 do atribuie(l[i],l[i+1]);
n:=n-1;
end;
end;
b) Lista reprezentat prin structur dinamic simplu nlnuit
procedure elimina_prima2(var cap:lista;var d:tip_informatie;var
test:boolean);
var p:lista;
begin
test:=true;
if cap=nil then test:=false
else
begin
p:=cap;
cap:=cap^.leg;
atribuie(d,p^.inf);
dispose(p);
end;
end;
c) Lista reprezentat prin structur dinamic dublu nlnuit
procedure elimina_prima3(var cap:lista;var d:tip_informatie;var
test:boolean);
var p:lista;
begin
test:=true;
if cap=nil then test:=false
else
begin
p:=cap;
cap:=cap^.dr;
cap^.st:=nil;
atribuie(d,p^.inf);
dispose(p);
end;
end;
2.4 Liste circulare
n anumite cazuri, este preferabil renunarea la structura de tip linear a
listelor i utilizarea unei legturi de la ultima component ctre capul listei, rezultnd
ceea ce se numete list circular (figura 2.2).
Avantajul utilizrii acestui tip de structur este posibilitatea de accesare
dintr-un element al listei a oricrui alt element. n continuare sunt prezentate module
pentru realizarea unor operaii de baz n lucrul cu liste circulare.
type
tip_informatie=string;
clista=^nod;
nod=record
inf:tip_informatie;
leg:clista;
end;
23
Programarea calculatoarelor - Tehnica programrii n limbajul Pascal
procedure atribuie(var d:tip_informatie;s:tip_informatie);
begin
d:=s;
end;
procedure inserare_la_inceput(var
ultim:clista;d:tip_informatie;var test:boolean);
var
p:clista;
cap:clista;
begin
test:=true;
if MaxAvail<sizeof(nod) then test:=false
else
begin
new(p);
atribuie(p^.inf,d);
if ultim=nil then
begin
ultim:=p;
ultim^.leg:=ultim;
end
else
begin
cap:=ultim^.leg;
p^.leg:=cap;
ultim^.leg:=p;
end;
end;
end;
procedure inserare_la_sfarsit(var
ultim:clista;d:tip_informatie;var test:boolean);
var
p:clista;
cap:clista;
begin
test:=true;
if MaxAvail<sizeof(nod) then test:=false
else
begin
new(p);
atribuie(p^.inf,d);
if ultim=nil then
begin
ultim:=p;
ultim^.leg:=ultim;
end
else
begin
cap:=ultim^.leg;
p^.leg:=cap;
ultim^.leg:=p;
ultim:=p;
end;
end;
end;
procedure elimina_la_inceput(var ultim:clista;var
d:tip_informatie;var test:boolean);
var
cap:clista;
24
Structura de list n limbajul Pascal
begin
test:=true;
if ultim=nil then test:=false
else
begin
cap:=ultim^.leg;
atribuie(d,cap^.inf);
if cap=ultim then
begin
dispose(ultim);
ultim:=nil;
end
else
begin
ultim^.leg:=cap^.leg;
dispose(cap);
end;
end;
end;
procedure elimina_la_sfarsit(var ultim:clista;var
d:tip_informatie;var test:boolean);
var
p:clista;
cap:clista;
begin
test:=true;
if ultim=nil then test:=false
else
begin
cap:=ultim^.leg;
atribuie(d,ultim^.inf);
if cap=ultim then
begin
dispose(ultim);
ultim:=nil;
end
else
begin
p:=cap;
while(p^.leg<>ultim) do p:=p^.leg;
p^.leg:=cap;
dispose(ultim);
ultim:=p
end;
end;
end;
procedure afisare(ultim:clista);
var p,cap:clista;
begin
if ultim=nil then writeln('Lista vida')
else
begin
cap:=ultim^.leg;
p:=cap;
repeat
write(p^.inf,' ');
p:=p^.leg;
until p=cap;
writeln;
end;
end;
25
Programarea calculatoarelor - Tehnica programrii n limbajul Pascal
2.5 Stive i cozi
Accesul la informaia memorat ntr-o list linear pentru efectuarea
operaiilor de inserare i eliminare este permis la oricare dintre componentele
coleciei. Aa dup cum a rezultat n 2.3, identificarea poziiei n care trebuie
efectuat inserarea/eliminarea presupune iniierea unei secvene de operaii de
cutare, ceea ce determin creterea timpului de lucru. Pe de alt parte, o mulime de
aplicaii pot fi modelate utiliznd liste lineare n care introducerea i, respectiv,
eliminarea informaiilor sunt permise numai la capete. Astfel au fost definite tipurile
de list stiv i coad, care impun un tip de organizare a aplicrii operaiilor de
inserare i eliminare.
Stiva
Se numete stiv o list organizat astfel nct operaiile de inserare i
eliminare sunt permise numai la prima component. Acest mod de organizare
corespunde unei gestiuni LIFO (Last In First Out) a informaiei stocate.
Modelul corespunde unei stive de cri. Adugarea unei noi cri n stiv se
face deasupra primei cri, iar extragerea este posibil numai pentru prima carte.
Operaiile de inserare i eliminare ntr-o stiv pot fi descrise prin intermediul
procedurilor inserare_la_inceput1, inserare_la_inceput2, elimina_prima1,
elimina_prima2. Operaiile elementare pentru gestiunea informaiei memorate ntr-o
stiv sunt:
- push(S,d,test) inserarea informaiei d n stiva S;
- pop(d,S,test) preluarea cu eliminare a informaiei memorate n prima
celul a stivei S;
- top(d,S,test) preluarea fr eliminare a informaiei deinute de prima
component a stivei S.
Parametrul test returneaz true dac operaia este posibil, altfel false.
Coada
Se numete coad o list organizat astfel nct operaia de inserare este
permis la ultima component, iar operaia de eliminare este permis numai la prima
component. Acest mod de organizare corespunde unei gestiuni FIFO (First In First
Out) a informaiei stocate.
Modelul corespunde unei cozi de ateptare la un magazin. O nou persoan
se aaz la coad dup ultimul cumprtor, iar persoana care i achit nota de plat
(primul cumprtor) prsete coada.
Implementarea unei liste coad poate fi efectuat att printr-o structur
static (masiv unidimensional), ct i printr-o structur dinamic de tip list. n
scopul eficientizrii operaiilor de inserare/extragere, n cazul implementrii cozilor
prin structuri dinamice lineare, este necesar utilizarea a dou informaii: adresa
26
Structura de list n limbajul Pascal
primei componente i adresa ultimei componente. Aceste informaii pot fi meninute
explicit prin utilizarea a doi pointeri sau prin utilizarea unui pointer i a unei structuri
de list circular.
1. Operaiile de inserare i eliminare pentru list coad reprezentat static
sunt descrise de procedurile inserare_la_sfarsit1 i eliminare_la_inceput prezentate
n cadrul seciunii 2.3.
2. Reprezentarea unei liste coad printr-o structur dinamic circular
utilizeaz o singur variabil adres, ultim, pentru referirea ultimei componente a
listei. Operaiile de inserare i eliminare sunt descrise de procedurile inserare_coada
i eliminare_coada.
procedure inserare_coada(var ultim:lista; d:tip_informatie; var
test:boolean);
var p:lista;
begin
test:=true;
if MaxAvail<sizeof(nod) then test:=false
else
begin
new(p);
atribuie(p^.inf,d);
if ultim=nil then
begin
ultim:=p;
ultim^.leg:=ultim;
end
else
begin
p^.leg:=ultim^.leg;
ultim^.leg:=p;
ultim:=p;
end;
end;
end;
procedure elimina_coada(var ultim:lista; var d:tip_informatie;
var test:boolean);
var prim:lista;
begin
test:=true;
if ultim=nil then test:=false
else
begin
prim:=ultim^.leg;
atribuie(d,prim^.inf);
if ultim^.leg=ultim then
begin
dispose(ultim);
ultim:=nil;
end
else
begin
ultim^.leg:=prim^.leg;
dispose(prim);
end;
end;
end;
27
Grafurile sunt structuri de date cu aplicaii n multe domenii ale prelucrrii
automate a datelor, algoritmii pentru reprezentarea i prelucrarea grafurilor fiind
considerai fundamentali n acest domeniu.
n cadrul seciunii 3.1 sunt prezentate principalele caracteristici ale
grafurilor, precum i modalitile uzuale de reprezentare a structurii de graf. n
continuare sunt descrise tehnicile de parcurgere a grafurilor n lime i n adncime.
Verificarea conexitii i calculul drumurilor n grafuri sunt tratate n seciunea 3.3
3.1 Definiii, caracteristici i reprezentri ale grafurilor
Definiia 3.1.1. Un graf (sau un graf neorientat) este o structur G=(V,E),
unde V este o mulime nevid, iar E este o submulime (posibil vid) a mulimii
perechilor neordonate cu componente distincte din V.
Obiectele mulimii V se numesc vrfuri, iar obiectele mulimii E se numesc
muchii. Dac eE, uv v) (u, e = = , se spune c muchia e are ca extremiti u,v sau
c muchia e este determinat de vrfurile u i v. Dac e=uvE se spune c vrfurile
u, v sunt incidente cu muchia e.
Definiia 3.1.2. Fie G = (V,E) graf. Vrfurile u, v sunt adiacente n G dac
uvE.
Definiia 3.1.3. Graful G = (V,E) este finit, dac V este o mulime finit.
n cadrul acestui capitol vor fi considerate n exclusivitate grafurile finite,
chiar dac acest lucru nu va fi precizat n mod explicit.
Definiia 3.1.4. Fie G
i
=(V
i
,E
i
), i=1,2 grafuri. G
2
este un subgraf al grafului
G
1
dac
1 2
V V i
1 2
E E . Dac G
2
este un subgraf al lui G
1
, G
2
este un graf
parial al lui G
1
dac V
2
=V
1
.
GRAFURI. IMPLEMENTRI
N LIMBAJUL PASCAL
28
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Definiia 3.1.5. Un digraf este o structur D = (V,E), unde V este o mulime
nevid de obiecte numite convenional vrfuri, iar E este o mulime (posibil vid) de
perechi ordonate cu componente elemente distincte din V. Convenional, elementele
mulimii E sunt numite arce sau muchii ordonate.
Terminologia utilizat relativ la digrafuri este similar celei corespunztoare
grafurilor.
Definiia 3.1.6. Se numete graf ponderat o structur (V,E,W), unde G =
= (V,E) este graf, W funcie, ( ) , 0 E : W . Funcia W este numit pondere i ea
asociaz fiecrei muchii a grafului un cost/ctig al parcurgerii ei.
Definiia 3.1.7. Fie G=(V,E) un graf, u,vV.
Secvena de vrfuri : u
0
, u
1
,..,u
n
este un u-v drum dac u
0
=u, u
n
=v, u
i
u
i+1
E
pentru toi i, n i 0 .
Moduri de reprezentare a grafurilor
Cea mai simpl reprezentare a unui graf este cea intuitiv, grafic; fiecare
vrf este figurat printr-un punct, iar muchiile sunt reprezentate prin segmentele de
dreapt, orientate (n cazul digrafurilor) sau nu i etichetate (n cazul grafurilor
ponderate) sau nu, avnd ca extremiti punctele corespunztoare vrfurilor care le
determin.
Exemple:
3.1. Fie G = (V, E) graf, cu V = {1, 2, 3, 4, 5}, E = {(1,2),(1,3),(2,5),(3,5)}.
O posibil reprezentare grafic este:
1
2 4
3
5
29
Grafuri. Implementri n limbajul Pascal
3.2. Fie D = (V, E) digraf, cu V = {1, 2, 3, 4, 5}, E = {(1,2),(1,3),
(2,5),(3,5),(1,5)}. Digraful poate fi reprezentat grafic astfel:
3.3. Fie G = (V, E, W) graf ponderat, cu V = {1, 2, 3, 4}, E =
{(1,2),(1,3),(2,4),(3,4)}, W((1,2))=5, W((1,3))=1, W((2,4))=2, W((1,4))=7. O
posibil reprezentare grafic este:
Dei acest mod de reprezentare este foarte comod i sugestiv, n special n
cazul grafurilor cu numr mic de vrfuri, pentru prelucrri cu ajutorul calculatorului
sunt necesare reprezentri prin intermediul structurilor de date.
O modalitate de reprezentare este cea prin matrice de adiacen. Dac
G=(V,E) este graf sau digraf cu n V = , atunci matricea de adiacen AM
nxn
({0,1})
are componentele:
( )
=
altfel
j i
dac
ij
, 0
E v , v , 1
a ,
1
2 4
3
5
1
5 1
2 3
7
2
4
30
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
unde v
i
, v
j
reprezint cel de-al i-lea, respectiv cel de-al j-lea nod din V. Se observ c,
n cazul unui graf neorientat, matricea de adiacen este simetric -
ji ij
a a , n , 1 j , i = = (perechile de vrfuri ce caracterizeaz muchiile sunt
neordonate, deci dac uvE, atunci i vuE), n timp ce, n cazul unui digraf, este
posibil ca ( ) , E v , v
j i
( ) E v , v
j i
, deci a
ij
a
ji
.
Exemplu:
3.4. Graful din exemplul 3.1 i digraful din exemplul 3.2 sunt reprezentate
prin matricele de adiacen:
|
|
|
|
|
|
.
|
\
|
=
0 0 1 1 0
0 0 0 0 0
1 0 0 0 1
1 0 0 0 1
0 0 1 1 0
A pentru 3.1,
|
|
|
|
|
|
.
|
\
|
=
0 0 0 0 0
0 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 1 1 0
A pentru 3.2
n cazul grafurilor ponderate, reprezentarea matriceal este asemntoare
celei prezentate anterior. Matricea ponderilor unui graf ponderat G = (V, E, W),
n V = , W M
nxn
((0, )) are componentele:
( ) ( )
=
altfel ,
E v , v dac , ) v , v ( W
w
j i j i
j , i
,
unde v
i
, v
j
reprezint cel de-al i-lea, respectiv cel de-al j-lea nod din V, =0
dac ponderea are semnificaia de ctig, respectiv = n cazul n care se dorete
reprezentarea costurilor ca ponderi ale grafului.
Exemplu:
3.5. Presupunnd c ponderile reprezint costuri, matricea de reprezentare a
grafului din exemplul 3.3. este:
|
|
|
|
|
.
|
\
|
=
2 7
1
2 5
7 1 5
W .
Reinnd numai informaia util, i anume existena unei muchii ntre dou
vrfuri i eventual valoarea ponderii ei, se obine reprezentarea tabelar, mai
economic din punctul de vedere al spaiului de memorare. n cazul n care exist
vrfuri izolate n graf (ce nu sunt incidente cu nici o muchie), atunci este necesar
pstrarea acestora ntr-un vector suplimentar. Mulimea muchiilor se memoreaz
31
Grafuri. Implementri n limbajul Pascal
ntr-o matrice cu E linii i 2 coloane dac graful nu este ponderat, respectiv cu
3 coloane, dac graful este ponderat. n primele dou coloane se scriu perechile de
vrfuri ce determin muchiile, n cazul grafurilor ponderate cea de-a treia coloan
conine valoarea ponderii muchiei respective.
Exemple:
3.6. Graful din exemplul 3.1 poate fi reprezentat astfel: deoarece 4 este vrf
izolat, vectorul suplimentar este VS = (4), pentru reprezentarea muchiilor fiind
utilizat matricea
|
|
|
|
|
.
|
\
|
=
5 3
5 2
3 1
2 1
A
3.7. Digraful din exemplul 3.2 poate fi reprezentat astfel: deoarece 4 este
vrf izolat, vectorul suplimentar este VS = ( 4), arcele fiind reprezentate prin
|
|
|
|
|
|
.
|
\
|
=
5 3
5 2
5 1
3 1
2 1
A
O alt reprezentare este prin intermediul listelor. Reprezentarea permite
utilizarea economic a spaiului de memorare i, n anumite cazuri, implementri mai
eficiente pentru anumite clase de algoritmi. Vrfurile grafului se memoreaz ntr-o
list, fiecare celul a listei avnd o legtur ctre lista vecinilor acelui vrf (vrfurile
din graf adiacente cu vrful corespunztor acelei celule i indicat ca informaie util).
n situaia n care graful nu este ponderat, el se reprezint printr-o list de
liste, i anume: nodurile grafului se trec ntr-o list L_nod, fiecare celul avnd
structura
informaie legtur vecini legtur nod urmtor
unde:
cmpul informaie conine identificatorul nodului;
legtur vecini reprezint pointer ctre capul listei vecinilor;
legtur nod urmtor conine adresa urmtoarei celule din lista
L_nod.
Un graf ponderat poate fi reprezentat n mod similar, cu diferena c fiecare
celul din lista vecinilor conine i ponderea muchiei respective (muchia care are ca
extremiti vrful referit prin identificatorul de nod din lista vecinilor i respectiv
vrful indicat de informaia acelei celule din L_nod ce conine adresa primului
element al listei vecinilor).
32
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
3.2 Modaliti de parcurgere a grafurilor
Parcurgerea unui graf reprezint o modalitate de vizitare a tuturor vrfurilor
grafului, fiecare vrf fiind vizitat o singur dat. n acest paragraf sunt prezentate
dou modaliti de parcurgere a grafurilor neorientate.
Ambele metode de parcurgere presupun selectarea unui vrf iniial v
0
. Prin
aplicarea acestor metode sunt identificate numai vrfurile grafului cu proprietatea c
exist cel puin un drum de la vrful iniial ctre acel vrf. Grafurile cu proprietatea
c oricare dou vrfuri sunt conectate printr-un drum se numesc conexe i sunt
prezentate n 3.3. Dac graful este conex, atunci prin aplicarea metodelor de
parcurgere vor fi identificate toate vrfurile grafului.
3.2.1 Metoda de parcurgere BF (Breadth First)
Ideea traversrii BF este de parcurgere n lime a grafului, n sensul c
vrfurile grafului sunt prelucrate n ordinea cresctoare a distanelor la vrful
iniial. Prin distan se nelege numrul de muchii din drumul identificat la acel
moment de la vrful iniial ctre acel vrf. La momentul iniial, vrful curent este v
0
.
Deoarece vrful curent la fiecare moment trebuie s fie unul aflat la distan minim
de v
0
, se poate proceda n modul urmtor: iniial lui v
0
i se asociaz valoarea 0 i
fiecrui vrf diferit de v
0
i se asociaz valoarea 1. Dac valoarea asociat vrfului
curent este m, atunci fiecruia dintre vecinii acestuia de valoare 1 i se asociaz
valoarea m+1. Se observ c dac dup ce toate vrfurile de valoare m au fost
considerate i nici unui vrf nu i-a fost recalculat valoarea, atunci toate vrfurile
conectate cu v
0
au fost gsite, deci calculul se ncheie.
Exemple:
3.8 Fie graful:
i v
0
=1.
1
2 3
4 6
5 7
33
Grafuri. Implementri n limbajul Pascal
Valorile calculate prin aplicarea metodei prezentate sunt:
vrf
m
1 2 3 4 5 6 7
0 0 -1 -1 -1 -1 -1 -1
1 0 1 1 -1 1 -1 1
2 0 1 1 2 1 2 1
0 1 1 2 1 2 1
Ordinea de vizitare a vrfurilor: 1,2,3,5,7,4,6.
3.9. Fie graful:
i v
0
=1.
Se observ c vrfurile 8, 9 i 10 nu sunt conectate cu vrful iniial.
Valorile rezultate prin aplicarea metodei sunt:
vrf
m
1 2 3 4 5
6
7 8
9
10
0 0 -1 -1 -1 -1 -1 -1 -1 -1 -1
1 0 1 1 -1 1 -1 1 -1 -1 -1
2 0 1 1 2 1 2 1 -1 -1 -1
0 1 1 2 1 2 1 -1 -1 -1
Ordinea de vizitare a vrfurilor este 1,2,3,5,7,4,6.
Se observ c valorile lui m calculate n final reprezint numrul de muchii
corespunztor celui mai scurt drum care conecteaz vrful iniial cu vrful respectiv,
pentru vrfurile neconectate cu v
0
valoarea lui m rezultat la terminarea calculului
este 1.
O implementare diferit, dar urmnd aceeai idee, rezult prin utilizarea
urmtoarelor structuri de date:
A matricea de adiacen a grafului;
o structur de tip coad, C, n care sunt introduse vrfurile ce urmeaz a fi
vizitate i procesate (n sensul cercetrii vecinilor lor);
1 8
2 3
4 6 9 10
7
5
34
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Un vector c cu n componente, unde:
dac i a fost introdus n coad
=
, 0
, 1
c
i
altfel
i n este numrul vrfurilor grafului.
Componentele vectorului c vor fi iniializate cu valoarea 0.
Descrierea metodei este:
se iniializeaz coada C cu vrful v
0
;
ct timp coada este nevid, se extrage un vrf i din coad, se viziteaz, apoi
se introduc n coad numai vecinii acestuia care nu au fost deja introdui (adic toate
vrfurile k avnd proprietatea c c[k]=0 i a[i,k]=1). Vrfurile i ce au fost introduse
n coad sunt marcate: i introdus n coad, c[i]=1.
n continuare este prezentat un program Pascal pentru parcurgerea n lime a
unui graf. Vrfurile grafului sunt numerotate de la 1 pn la n, parcurgerea ncepnd
cu vrful numerotat cu 1. Graful este reprezentat prin matricea de adiacen.
Structura de coad este implementat ca o list simplu nlnuit, procedurile push i
pop realiznd introducerea, respectiv extragerea unui element din coad.
uses crt;
type
ptcoada=^coada;
coada=record
inf:byte;
leg:ptcoada;
end;
var
prim,ultim:ptcoada;
c:array[1..20] of byte;
a:array[1..20,1..20] of byte;
i,j,k,n:byte;
procedure push(var p,u:ptcoada;i:byte);
var a:ptcoada;
begin
new(a); a^.inf:=i; a^.leg:=nil;
if p=nil then
begin
p:=a; u:=a;
end
else begin
u^.leg:=a;u:=a;
end;
end;
procedure pop(var p,u:ptcoada;var i:byte);
var a:ptcoada;
begin
if p<>nil then
begin
i:=p^.inf; a:=p; p:=p^.leg;
dispose(a);
if p=nil then u:=nil;
end;
35
Grafuri. Implementri n limbajul Pascal
end;
begin {program principal}
clrscr;
write('Numarul de varfuri:');
readln(n);
writeln('Matricea de adiacenta');
for i:=1 to n do
for j:=1 to n do
begin
write('a[',i,',',j,']=');
readln(a[i,j]);
end;
for i:=2 to n do c[i]:=0;
readln;
clrscr;
writeln('Incepem parcurgerea de la nodul 1');
c[1]:=1;
prim:=nil;ultim:=nil;
push(prim,ultim,1);
while prim<>nil do
begin
pop(prim,ultim,i);
write(i,' ');
for k:=1 to n do
if (a[i,k]=1)and(c[k]=0) then
begin
c[k]:=1;
push(prim,ultim,k);
end;
end;
readln;
end.
3.2.2 Metoda de parcurgere DF (Depth First)
Ideea metodei DF revine la parcurgerea n adncime a grafurilor, n sensul
c, la fiecare moment, dac M este mulimea vrfurilor vizitate de procedur, pentru
vizitarea vecinilor este considerat unul din vrfurile din M cu proprietatea c
lungimea drumului calculat pn la vrful iniial v
0
este maxim.
Implementarea metodei poate fi realizat n mai multe moduri, pentru
meninerea mulimii vrfurilor grafului disponibilizate pn la momentul curent fiind
utilizat o structur de date de tip stiv, S.
La momentul iniial se introduce n stiv v
0
. La fiecare pas, se preia cu
tergere ca vrf curent vrful stivei S i se introduc n stiv vecinii nc nevizitai ai
vrfului curent. Un vrf se marcheaz ca vizitat n momentul introducerii lui n S.
Calculul continu pn cnd este efectuat un acces de preluare din stiv i se constat
c S este vid. Pentru gestiunea vrfurilor vizitate, se utilizeaz un vector c cu
n componente, unde n reprezint numrul vrfurilor grafului i, la fiecare moment,
componentele sunt:
36
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
=
altfel 0
vizitat fost a dac 1
,
i ,
c
i
Componentele vectorului c vor fi iniializate cu valoarea 0.
Exemple:
3.10. Pentru graful:
i v
0
= 1, ordinea n care sunt vizitate vrfurile este: 1, 2, 3, 4, 6, 7, 5.
3.11. Pentru graful
i v
0
= 1, ordinea n care sunt vizitate vrfurile este: 1, 2, 3, 4, 6, 7, 5. Vrfurile 8, 9 i
10 nu sunt vizitate de procedur, pentru c nu sunt conectate de vrful iniial selectat.
O variant de implementare a metodei DF rezult prin gestionarea stivei S
dup cum urmeaz. Iniial vrful v
0
este unicul component al lui S . La fiecare etap
se preia, fr tergere, ca vrf curent vrful stivei. Se introduce n stiv unul dintre
vecinii vrfului curent nc nevizitat. Vizitarea unui vrf revine la introducerea lui n
S. Dac vrful curent nu are vecini nc nevizitai, atunci este eliminat din stiv i
1
2 3
4 6
5 7
1 8
2 3
4 6 9 10
7
5
37
Grafuri. Implementri n limbajul Pascal
este efectuat un nou acces de preluare a noului vrf al stivei ca vrf curent. Calculul
se ncheie n momentul n care este efectuat un acces de preluare a vrfului stivei ca
vrf curent i se constat c S este vid. Evident, nici n cazul acestei variante nu vor
fi vizitate vrfurile care nu sunt conectate cu vrful ales iniial.
3.3 Drumuri n grafuri. Conexitate
3.3.1 Drumuri; definiii
Una dintre cele mai importante proprieti ale grafurilor o constituie
posibilitatea de accesare, prin intermediul unei secvene de muchii (arce), dintr-un
vrf dat a oricrui alt vrf al grafului, proprietate cunoscut sub numele de conexitate
sau conexiune. Aa dup cum a rezultat n 3.2., dac G=(V,E) este un graf conex,
atunci pentru orice vrf iniial v
0
considerat, metodele BF i DF permit vizitarea
tuturor vrfurilor din V.
Definiia 3.3.1. Fie G=(V,E) un graf, u,vV. Secvena de vrfuri
: u
0
, u
1
,..,u
n
este un u-v drum dac u
0
=u, u
n
=v, u
i
u
i+1
E pentru toi i, n i 0 .
Lungimea drumului, notat l(),este egal cu n. Convenional, se numete trivial, un
drum cu l()=0.
Definiia 3.3.2. Fie : u
0
, u
1
,..,u
n
un drum n graful G=(V,E). este un drum
nchis dac u
0
=u
n
; n caz contrar, este deschis. Drumul este elementar dac
oricare dou vrfuri din sunt distincte, cu excepia, eventual, a extremitilor.
Drumul este proces dac, pentru orice 1 n j i 0 , u
i
u
i+1
u
j
u
j+1
.
Evident, orice drum elementar este un proces.
Definiia 3.3.3. Fie : u
0
, u
1
,..,u
n
un drum n graful G = (V,E).
: v
0
, v
1
,..,v
m
este un subdrum al lui dac
=
=
+
+
n j , 0 i dac , u ... u u ... u u
0 j dac , u ... u u
0 i dac , u ... u u
:
n 1 j i 1 0
i 1 0
n 1 j j
'
este, de asemenea, un u
0
-u
n
drum. Aplicnd n continuare eliminarea duplicatelor
vrfurilor n modul descris, rezult n final un u
0
-u
n
drum elementar.
3.3.2 Matricea existenei drumurilor; algoritmul Roy-Warshall
Fie G=(V,E) un graf, n V = . Dac A este matricea de adiacen asociat
grafului, atunci, pentru orice p1,
) p (
ij
a este numrul v
i
-v
j
drumurilor distincte de
lungime p din graful G, unde ( )
) p (
ij
p
a A = .
Definiia 3.3.4. Fie M
n
({0,1)} mulimea matricelor de dimensiuni nxn,
componentele fiind elemente din mulimea {0,1}. Pe M
n
({0,1)}se definesc operaiile
binare, notate i , astfel: pentru orice A=(a
ij
), B=(b
ij
) din M
n
({0,1)},
AB=(c
ij
), AB=(d
ij
), unde
n j , i 1 ,
c
ij
=max{a
ij
, b
ij
}
d
ij
=max{min{a
ik
, b
kj
}, n k 1 }.
Dac A=(a
ij
) M
n
({0,1)}, se noteaz ( ) { } 1 k ; a A
) k (
ij
k
= secvena de
matrice definit prin:
( )
2 k , A A A , A A
) 1 k ( k 1
= =
.
Dac A este matricea de adiacen a unui graf G=(V,E), atunci pentru fiecare
k, 1 n k 1 ,
=
altfel , 0
k lungime de j la i la de drum exist dac , 1
a
) k (
ij
) 1 n ( ) 2 ( ) 1 (
A A A M
= se numete matricea existenei drumurilor
n graful G. Semnificaia componentelor matricei M este:
=
altfel , 1
G n drum v v exist nu dac , 0
m , n j , i 1
j i
ij
39
Grafuri. Implementri n limbajul Pascal
Exemplu:
3.12. Pentru graful:
|
|
|
|
|
.
|
\
|
=
|
|
|
|
|
.
|
\
|
=
|
|
|
|
|
.
|
\
|
=
|
|
|
|
|
.
|
\
|
=
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 0 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 0
1 1 0 1
0 1 0 1
1 0 0 1
0 0 0 1
1 1 1 0
3 2
M , A , A , A
Calculul matricei existenei drumurilor permite verificarea faptului c un
graf dat este conex: graful este conex dac i numai dac toate componentele
matricei M sunt egale cu 1.
Algoritmul Roy-Warshall calculeaz matricea existenei drumurilor ntr-un
graf G cu n vrfuri.
procedure Roy_Warshall (a,n,m);
i,j,k:integer;
do-for i=1,n,1
do-for j=1,n,1
m
ij
=a
ij
;
do-for j=1,n,1
do-for i=1,n,1
if m
ij
=1 then
do-for k=1,n,1
if m
ik
<m
kj
then
m
ik
=m
kj
;
endif;
enddo;
endif;
enddo;
enddo;
end;
2
1
3
4
40
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Datele de intrare sunt: n, numrul de noduri i A, matricea de adiacen
corespunztoare grafului. Matricea M calculat de algoritm constituie ieirea i este
matricea existenei drumurilor n graful G.
3.3.3 Componente conexe ale unui graf
Definiia 3.3.5. Fie G=(V,E) graf netrivial. Vrfurile u,v V sunt conectate
dac exist un u-v drum n G.
Definiia 3.3.6. Dac G este un graf, atunci o component conex a lui G este
un subgraf conex al lui G, maximal n raport cu proprietatea de conexitate.
Evident, un graf este conex dac i numai dac numrul componentelor sale
conexe este 1. Mulimile vrfurilor corespunztoare oricror dou componente
conexe distincte sunt disjuncte. Mulimile vrfurilor corespunztoare componentelor
conexe ale unui graf formeaz o partiie a mulimii vrfurilor grafului.
Multe aplicaii modelate n termeni de grafuri impun determinarea
componentelor conexe corespunztoare unui graf dat. Problema poate fi rezolvat n
modul urmtor: se selecteaz un vrf al grafului, se determin componenta conex
care-l conine; dac exist vrfuri care nu aparin componentei conexe determinate,
se alege unul dintre acele vrfuri cruia i se determin componenta conex care-l
conine; n continuare, se repet procedeul pn cnd au fost gsite toate
componentele conexe ale grafului.
Pentru G=(V,E), n V = , n 1 i v
0
V, paii algoritmului pentru
determinarea componentei conexe care conine un vrf v
0
dat sunt:
Pasul 1: V
0
={v
0
}; E
0
=; i=0;
Pasul 2: repet Pas 3 pn cnd V
i
=V
i-1
i E
i
=E
i-1
Pasul 3: i=i+1;
{ }
{ }; e cu incident u , V u , E e / e E E
; E uv , V u , V v / v V V
1 i 1 i i
1 i 1 i i
=
=
Ieirea este G
1
=(V
i
,E
i
), componenta conex din care face parte v
0
.
Exemplu:
3.13. Pentru graful
1 2 7 3
4 5 8 6
41
Grafuri. Implementri n limbajul Pascal
Aplicarea algoritmului descris, pentru v
0
=1, determin urmtoarea evoluie:
i V
i
E
i
i=0 {1}
i=1 {1,2,4} {(1,2),(1,4)}
i=2 {1,2,4,7,5} {(1,2),(1,4),(2,7),(4,5),(4,7)}
i=3 {1,2,4,7,5,8} {(1,2),(1,4),(2,7),(4,5),(4,7),(5,8),(7,8)}
i=4 {1,2,4,7,5,8} {(1,2),(1,4),(2,7),(4,5),(4,7),(5,8),(7,8)}
3.3.4 Drumuri de cost minim
Definiia 3.3.7. Fie G=(V, E, w) un graf ponderat. Costul drumului
: u
1
, u
2
,..,u
n
, notat L(), este definit prin:
( ) ( )
=
+
=
1 n
1 i
1 i i
u , u w L .
Pentru orice u i v vrfuri conectate n G, u v, w-distana ntre u i v, notat
D(u,v), este definit prin:
( ) ( ) { }
uv
D , L min v , u D = , unde D
uv
desemneaz mulimea tuturor u-v
drumurilor elementare din G. Dac
uv
D este astfel nct D(u,v)=L(), drumul
se numete de cost minim.
Cu toate c este utilizat termenul de w-distan, n general D nu este o
distan n sensul matematic al cuvntului.
n particular, dac funcia pondere asociaz valoarea 1 fiecrei muchii a
grafului, atunci, pentru fiecare pereche de vrfuri distincte ale grafului, costul D(u,v)
este lungimea celui mai scurt drum ntre cele dou vrfuri. n acest caz, D este o
distan pe mulimea vrfurilor.
Dat fiind interesul pentru determinarea w-distanelor i a drumurilor de cost
minim n cadrul aplicaiilor modelate pe grafuri, n continuare vor fi prezentai
algoritmi pentru rezolvarea acestor probleme.
Algoritmul Dijkstra
Algoritmul a fost propus de E. W. Dijkstra pentru determinarea w-distanelor
D(u
0
,v) i a cte unui u
0
-v drum de cost minim pentru fiecare vrf vu
0
ntr-un graf
ponderat, unde u
0
este prestabilit.
Fie (V,E,w) graf conex ponderat, u
0
V, SV, u
0
S. Se noteaz S \ V S = i
( ) ( ) { } S x ; x , u D min S , u D
0 0
= . Fie vS astfel nct D(u
0
,v)=D(u
0
, S ), : u
0
,
u
1
,,u
p
v este un u
0
-v drum de cost minim. Evident, 0ip u
i
S i
: u
0
, u
1
,,u
p
,
un u
0
- u
p
drum de cost minim. De asemenea,
( ) ( ) { } E uv , S v , S u ); uv ( w u , u D min S , u D
0 0
+ = .
42
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Dac xS, yS astfel nct ( ) ( ) ) xy ( w x , u D S , u D
0 0
+ = , rezult
( ) ( ) ) xy ( w x , u D y , u D
0 0
+ = . Pentru determinarea unui drum u
0
-v, cel mai ieftin,
algoritmul consider o etichetare dinamic a vrfurilor grafului. Eticheta vrfului v
este (L(v),u), unde L(v) este lungimea celui mai ieftin drum u
0
-v determinat pn la
momentul respectiv i u este predecesorul lui v pe un astfel de drum.
Pentru (V,E,w) graf conex ponderat, n V = i u
0
V, calculul implicat de
algoritmul Dijkstra poate fi descris astfel:
Pasul 1: i=0; S
0
={u
0
}; L(u
0
)=0, L(v)=pentru toi vV, vu
0
. Dac n=1
atunci stop
Pasul 2: Pentru toi v
i
S , dac L(v)>L(u
i
)+w(u
i
v), atunci L(v)=L(u
i
)+w(u
i
v)
i eticheteaz v cu (L(v),u
i
).
Pasul 3: Se determin d=min{L(v), v
i
S } i se alege u
i+1
i
S astfel nct
L(u
i+1
)=d.
Pasul 4: S
i+1
=S
i
{u
i+1
}
Pasul 5: i=i+1. Dac i=n-1, atunci stop. Altfel, reia Pasul 2.
Evident, dac (V,E,w) este graf ponderat neconex, atunci, pentru u
0
V,
algoritmul lui Dijkstra permite determinarea w-distanelor D(u
0
,v) i a cte unui u
0
-v
drum de cost minim pentru toate vrfurile v din componenta conex creia i aparine
u
0
.
Exemplu:
3.14. Fie graful ponderat
1
5 1
9
2 3
2 16
5
5
4
43
Grafuri. Implementri n limbajul Pascal
Considernd u
0
=1, etapele n aplicarea algoritmului Dijkstra sunt:
P1: i=0; S
0
={1}; L(1)=0, L(i)=pentru toi 5 , 2 i = .
P2:
0
S ={2,3,4,5}, u
0
=1
L(2)= >L(1)+5=5 L(2)=5, eticheteaz 2 cu 1
L(3)= >L(1)+1=1 L(3)=1, eticheteaz 3 cu 1
L(4)= >L(1)+9=9 L(4)=9, eticheteaz 4 cu 1
L(5)= , w(1,5)= , deci L(5) nu se modific
P3: selecteaz u
1
=3, L(3)=1, cea mai mic dintre w-distanele calculate la P2
P4: S
1
={1,3}
P5: i=i+1=1 4, reia P2
P2:
1
S ={2,4,5}, u
1
=3
Nu se modific nici o etichet i nici o w-distan (w(3,i)=, pentru
toi i din
1
S )
P3: selecteaz u
2
=2, L(2)=5, cea mai mic dintre w-distanele calculate la P2
P4: S
2
={1,3,2}
P5: i=i+1=2 4, reia P2
P2:
2
S ={4,5}, u
2
=2
L(4)= 9>L(2)+2=7 L(4)=7, eticheteaz 4 cu 2
L(5)= >L(2)+16=21, eticheteaz 5 cu 2
P3: selecteaz u
3
=4, L(4)=7, cea mai mic dintre w-distanele calculate la P2
P4: S
3
={1,3,2,4}
P5: i=i+1=3 4, reia P2
P2:
3
S ={5}, u
3
=4
L(5)= 21>L(4)+5=12, eticheteaz 5 cu 4
P3: selecteaz u
4
=5, L(5)=12, cea mai mic dintre w-distanele calculate la
P2
P4: S
3
={1,3,2,4,5}
P5: i=i+1=4, stop.
Algoritmul calculeaz urmtoarele rezultate:
Vrful v pn la care se
calculeaz w-distana
1 2 3 4 5
D(1,v), eticheta lui v 0, 1 5, 1 1, 1 7, 2 12, 4
Drumurile de cost minim de la vrful 1 la fiecare dintre vrfurile grafului se
stabilesc pe baza sistemului de etichete astfel: drumul de la 1 la un vrf v este dat de:
v
1
, eticheta lui v, v
2
eticheta lui v
1
.a.m.d., pn se ajunge la eticheta 1.
44
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Astfel, v
0
-drumurile de cost minim sunt:
pn la 2: 2,1;
pn la 3: 3,1;
pn la 4: 4,2,1;
pn la 5: 5,4,2,1.
Programul Pascal pentru algoritmul Dijkstra, graful ponderat fiind
reprezentat sub form tabelar, este prezentat n continuare.
Variabilele folosite n program au urmtoarele semnificaii:
- v: numrul de vrfuri ale grafului;
- m: numrul de muchii din graf;
- s: mulimea S
i
la momentul curent;
- t: mulimea
i
S la momentul curent;
- l: vectorul componentelor L din etichetele ataate vrfurilor;
- dr: vectorul componentelor de tip vrf din etichetele ataate vrfurilor.
uses crt;
var a:array[1..200,1..3] of integer;
s,dr,t,l:array[1..20] of integer;
i,j,k,p,v1,u,c,d:integer;
m,v:integer;
begin
clrscr;
readln(v);
readln(m);
for i:=1 to m do
for j:=1 to 3 do
begin
write('a[',i,',',j,']=');
readln(a[i,j]);
end;
i:=1;s[1]:=1;v1:=1;
for j:=2 to v do
begin
t[j-1]:=j; l[j]:=maxint;
end;
l[1]:=0;
for k:=1 to v-1 do
begin
for j:=1 to v-i do
begin
u:=1;
while((t[j]<>a[u,1])or(v1<>a[u,2]))and
((t[j]<>a[u,2])or(v1<>a[u,1]))and(u<=m)
do inc(u);
if(u<=m) and (l[t[j]]>l[v1]+a[u,3]) then
begin
l[t[j]]:=l[v1]+a[u,3];
dr[t[j]]:=v1;
end;
end;
d:=l[t[1]];v1:=t[1];
for j:=2 to v-i do
if l[t[j]]<d then begin
d:=l[t[j]];
45
Grafuri. Implementri n limbajul Pascal
v1:=t[j];
end;
inc(i);
s[i]:=v1;
u:=1;
while(u<=v-i+1)and(t[u]<>v1) do inc(u);
for j:=u to v-i do t[j]:=t[j+1];
end;
clrscr;
for i:=1 to v do
writeln(i,'--->',l[i]);
writeln('Drumurile minime de la fiecare varf la 1:');
for j:=2 to v do
begin
k:=j;write(k,' ');
while k<>1 do
begin
write(dr[k],' '); k:=dr[k];
end;
writeln;
end;
readln;
end.
n anumite cazuri se dorete determinarea numai a w-distanelor D(v
0
,v),
pentru toi vV. n acest caz, algoritmul Roy-Floyd permite o rezolvare a acestei
probleme mai simplu de implementat dect algoritmul Dijkstra.
Algoritmul Roy-Floyd
Pentru (V,E,w) graf ponderat, n V = i W matricea ponderilor, sistemul de
w-distane D(v
0
,v), vV, poate fi calculat pe baza urmtoarei proceduri (similar
algoritmului Roy-Warshall):
procedure Roy_Floyd (w,n,d);
i,j,k:integer;
do-for i=1,n,1
do-for j=1,n,1
d
ij
=w
ij
;
do-for j=1,n,1
do-for i=1,n,1
if d
ij
then
do-for k=1,n,1
if d
ik
>d
ij
+ d
jk
then
d
ik
=d
ij
+ d
jk
;
endif;
enddo;
endif;
enddo;
enddo;
46
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
end;
Matricea D calculat de algoritm este a w-distanelor D(u,v) n graful
ponderat conex (V,E,w); pentru orice n j , i 1
=
altfel ,
conectate sunt v , v ), v , v ( D
d
j i j i
ij
ntr-adevr, procedura calculeaz dinamic w-distana ntre oricare dou
vrfuri i i k, astfel: dac exist un i-k drum ce trece prin j ( n j 1 ), cu costul
corespunztor (d
ij
+ d
jk
)
inferior costului curent (d
ik
), atunci noul drum de la i la k via
j este de cost mai mic dect cel al drumului vechi, deci w-distana ntre i i k trebuie
reactualizat la d
ij
+ d
jk
.
Algoritmul Yen
Pentru calculul tuturor w-distanelor ntr-un graf ponderat, algoritmul propus
de Yen rezolv problema ntr-o manier mai eficient dect algoritmul Roy-Floyd,
din punctul de vedere al volumului operaiilor. Fie (V,E,w) un graf ponderat, W
matricea ponderilor. Pentru determinarea w-distanelor de la vrful v
k
fixat la
celelalte vrfuri ale grafului, algoritmul Yen iniiaz urmtoarele operaii:
Pasul 1: D = W
Pasul 2: i = 1; (k) = 0, b(k) = 0; (j)=0, pentru toi n j 1 , j k
Pasul 3: Calculeaz min{d
kj
; n j 1 , (j)=1}; determin j
0
astfel nct
(j
0
) = 1 i
0
kj
d = min{d
kj
; n j 1 , (j) = 1}
B(j
0
) =
0
kj
d , (j
0
) = 0
d[k,j] = min{d[k,j],d[k,j0]+d[j0,j]}, pentru toi j, n j 1
i=i+1
Pasul 4: Dac i<n, reia Pasul 3, altfel stop.
La terminarea algoritmului, componentele vectorului B sunt egale cu
w-distana de la vrful v
k
la orice alt vrf al grafului: B(j)=D(v
k
,v
j
), n j 1 .
ntr-adevr, componentele egale cu 1 ale vectorului indic, la fiecare reluare a
pasului 3, vrfurile grafului pentru care nu s-a calculat nc w-distana la vrful v
k
.
Dup fiecare efectuare a etapei 3, dac j
0
a fost selectat, atunci B(j
0
)=D(v
k
,
0
j
v ).
47
n clasa grafurilor conexe, structurile cele mai simple, dar care apar cel mai
frecvent n aplicaii, sunt cele arborescente (arbori). n acest capitol sunt prezentate
principalele caracteristici ale arborilor, algoritmi pentru calculul arborelui parial de
cost minim, arbori direcionai, arbori cu rdcin i arbori binari. Pe lng operaiile
primitive asupra arborilor cutarea unei informaii, inserarea unui nod, extragerea
unui nod i metode de parcurgere, sunt prezentate dou clase importante de arbori
binari, i anume arbori de sortare i arbori de structur.
4.1 Grafuri de tip arbore
4.1.1 Definiii i caracterizri ale grafurilor de tip arbore
Definiia 4.1.1. Graful G este arbore dac G este aciclic i conex.
Definiia 4.1.2. Fie G=(V,E) graf arbore. Subgraful H=(V1,E1) al lui G este
un subarbore al lui G dac H este graf arbore.
Exemple:
4.1. Graful
este arbore, deoarece pentru orice pereche de vrfuri i,j, 1i,j 6, ij, exist un i-j
drum i graful nu conine cicluri.
1 3
4 2
5
STRUCTURI ARBORESCENTE
48
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
4.2. Graful
nu este arbore deoarece este conex, dar drumul :1,4,3,2,1 este un ciclu.
4.3. Graful
nu este arbore deoarece are dou componente conexe {1,2,3,4,5,6}, {7,8}.
Proprietatea unui graf de a fi arbore poate fi verificat prin algoritmi care
testeaz calitile de conexitate i aciclicitate. Verificarea proprietii unui graf de a fi
arbore poate fi realizat i pe baza urmtoarelor proprieti:
Proprietatea 1.: Un graf G=(V,E), cu m E , n V = = este de tip arbore dac
i numai dac G este aciclic i n=m+1. Cu alte cuvinte, problema revine la
verificarea aciclicitii grafului i a relaiei existente ntre numrul vrfurilor i
numrul muchiilor grafului.
Proprietatea 2: Un graf G=(V,E), cu m E , n V = = este de tip arbore dac
i numai dac G este conex i n=m+1.
Fie G=(V,E) un graf. Urmtoarele afirmaii sunt echivalente:
1. G este graf arbore;
2. G este graf conex minimal (oriare ar fi eE, prin eliminarea muchiei
e graful rezultat nu este conex);
1 3
4 2
5
6
1 3 7
4 2
5
6 8
49
Structuri arborescente
3. G este graf aciclic maximal (prin adugarea unei noi muchii n graf
rezult cel puin un ciclu).
Definiia 4.1.3. Un graf orientat D=(V,E), cu proprietatea c pentru
, E v , u E v , u , atunci vuE se numete graf asimetric. Digraful D este
simetric dac , E v , u uvE, dac i numai dac vuE.
Definiia 4.1.4. Fie D=(V,E) digraf netrivial. Graful G=(V,E), unde
E={uv/ uvE sau vuE} se numete suport al digrafului D.
Definiia 4.1.5. Un arbore direcionat este un graf orientat asimetric cu
proprietatea c graful suport corespunztor lui este graf arbore. Arborele direcionat
T=(V,E) este cu rdcin dac exist rV astfel nct, pentru orice uV, u r, exist
r-u drum n T. Vrful r se numete rdcina arborelui direcionat T.
Definiia 4.1.6. Dac T=(V,E) este arbore direcionat, atunci T1=(V1,E1)
este subarbore al lui T dac V1V, E1E i T1 este arbore direcionat.
Deoarece graful suport al unui arbore direcionat este aciclic, rezult c
pentru orice uV, u r, r-u drumul n T este unic. De asemenea, un arbore
direcionat are cel mult o rdcin. n consecin, pentru orice uV, u r, distana de
la rdcin la vrful u este egal cu numrul de muchii ale r-u drumului n T.
Exemple:
4.4. Arborele direcionat
este cu rdcin (vrful r este rdcina arborelui).
u
w x
t r y
v z
50
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
4.5. Arborele direcionat
nu are rdcin.
4.6. Arborele
este un subarbore cu rdcin x al arborelui din exemplul 4.5
4.1.2 Arbori orientai; reprezentri i parcurgeri
Definiia 4.1.7. Un arbore orientat este un arbore direcionat cu rdcin.
Deoarece un arbore orientat este un caz particular de digraf, pentru
reprezentarea unui arbore orientat poate fi utilizat oricare din modalitile prezentate
n 3.1. n plus, exist i posibilitatea obinerii unor reprezentri mai eficiente pentru
acest tip de graf.
Una dintre modaliti este reprezentarea FIU-FRATE, care const n
numerotarea convenional a vrfurilor grafului i reinerea, pentru fiecare vrf i al
arborelui, a urmtoarelor informaii:
- FIU(i), care reprezint numrul ataat primului descendent al vrfului i;
- FRATE(i), care reprezint numrul ataat vrfului descendent al tatlui
vrfului i i care urmeaz imediat lui i;
- INF(i), care reprezint informaia ataat vrfului i (de obicei valoarea i).
Pentru reprezentarea arborelui se rein rdcina i numrul nodurilor.
Absena fiului, respectiv a fratelui unui vrf, este marcat printr-o valoare
diferit de numerele ataate vrfurilor (de obicei valoarea 0).
u v
x
y
z w
y w
x
v
51
Structuri arborescente
Exemplu:
4.7. Arborele orientat
este reprezentat astfel:
N=15 (numrul nodurilor arborelui)
R=1 (rdcina), FIU=(2,5,7,9,0,10,0,0,13,0,0,0,0,0,0)
fiul lui 1 este 2 vrful 9 are fiul 13
FRATE=(0,3,4,0,6,0,8,0,0,11,12,0,14,15,0)
vrful 1 nu are frate vrful 14 are fratele 15
Utiliznd structurile de date dinamice pentru arbori orientai, se obine o
reprezentare descris n continuare. Presupunnd c fiecare vrf al arborelui are cel
mult n descendeni, fiecrui vrf i este ataat structura:
vector de legturi ctre descendenii vrfului identificatorul vrfului
legtur ctre fiul 1
legtur ctre fiul n
Dac un vrf are p<n descendeni, atunci primele p legturi sunt ctre
descendeni, iar ultimile n-p legturi sunt nil. Pentru n10, descrierea structurii de
date n limbajul Pascal este:
type ptnod=^nod;
nod=record
inf:integer;
leg:array[1..10] of ptnod;
end;
1
2 3 4
5 6 7 8 9
10 11 12 13 14 15
52
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
O parcurgere revine la aplicarea sistematic a unei reguli de vizitare a
vrfurilor grafului. Cele mai uzuale reguli de parcurgere a arborilor orientai sunt
prezentate n continuare.
A. Parcurgerea n A-preordine
Iniial vrful curent este rdcina arborelui. Se viziteaz vrful curent i sunt
identificai descendenii lui. Se aplic aceeai regul de vizitare pentru arborii care au
ca rdcini descendenii vrfului curent, arborii fiind vizitai n ordinea dat de
numerele ataate vrfurilor rdcin corespunztoare.
Exemplu:
4.8. Pentru arborele orientat din exemplul 4.7, prin aplicarea parcurgerii n
A-preordine, rezult: 1,2,5,6,10,11,12,3,7,8,4,9,13,14,15.
Pentru un arbore reprezentat FIU-FRATE, implementarea parcurgerii n
A-preordine se bazeaz pe urmtoarea procedur recursiv, avnd ca parametru de
intrare rdcina arborelui curent (vrful curent n momentul apelului).
procedure A_preordine (R);
if R0 then
vizit (R);
A_preordine(FIU[R]);
A_preordine(FRATE[R]);
endif;
end;
B. Parcurgerea A-postordine
Regula de vizitare a vrfurilor n parcurgerea n A-postordine difer de cea n
A-preordine numai prin faptul c rdcina fiecrui arbore este vizitat dup ce au fost
vizitate toate celelalte vrfuri ale arborelui.
Exemplu:
4.9. Pentru arborele orientat din exemplul 4.7, ordinea de vizitare a vrfurilor
este: 5,10,11,12,6,2,7,8,3,13,14,15,9,4,1.
Pentru arbori reprezentai prin structuri de date arborescente, implementarea
parcurgerii n A-postordine poate fi obinut pe baza urmtoarei proceduri recursive.
Unicul parametru (de intrare) reprezint rdcina arborelui curent n momentul
apelului.
procedure A_postordine (R);
if Rnil then
do-for i=1,n,1
A_postordine(R^.leg[i]);
53
Structuri arborescente
enddo;
vizit (R);
endif;
end;
Procedurile A-preordine i A-postordine sunt variante de parcurgeri n
adncime, fiind prioritare vrfurile aflate la distan maxim fa de rdcina
arborelui iniial.
C. Parcurgerea pe niveluri
Definiia 4.1.8. Un vrf v al unui arbore orientat cu rdcin r se afl pe
nivelul i al arborelui, dac distana de la vrf la rdcin (lungimea r-v drumului) este
egal cu i. Rdcina arborelui este de nivel 0.
Parcurgerea unui arbore orientat pe niveluri const n vizitarea vrfurilor sale
n ordinea cresctoare a distanelor fa de rdcin.
Exemplu:
4.10. Pentru arborele din exemplul 4.7, prin aplicarea parcurgerii pe niveluri,
rezult: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15.
Implementarea parcurgerii pe niveluri se bazeaz pe utilizarea unei structuri
de coad C. La momentul iniial, rdcina arborelui este unicul element din C. Atta
timp ct coada este nevid, se extrage (cu tergere) un vrf din C, este vizitat i sunt
introdui n coad descendenii si. Calculul se ncheie n momentul n care, la
tentativa de extragere a unui vrf din C, se constat C=.
Parcurgerea pe niveluri este realizat de urmtoarea procedur care are ca
parametri de intrare reprezentarea FIU-FRATE a grafului. Procedurile push i pop
realizeaz operaiile de acces introducere-extragere n C.
procedure parcurgere_pe_niveluri(R,FIU,FRATE,n)
C:ptcoada;
C=nil;push(C,R);
while Cnil do
pop(C,v);
VIZIT(v);
v=FIU[v];
while v0 do
push(C,v);
v=FRATE[v];
endwhile;
endwhile;
end;
54
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Exemplu
4.11. Pentru arborele de la exemplul 4.7, evoluia algoritmului este:
C
t
t=1 1
t=2 2 3 4
t=3 3 4 5 6
t=4 4 5 6 7 8
t=5 5 6 7 8 9
t=6 6 7 8 9
t=7 7 8 9 10 11 12
t=8 8 9 10 11 12
t=9 9 10 11 12
t=10 10 11 12 13 14 15
t=11 11 12 13 14 15
t=12 12 13 14 15
t=13 13 14 15
t=14 14 15
t=15 15
t=16
deci vrfurile sunt vizitate n ordinea: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15.
Metoda BF pentru parcurgerea grafurilor este o generalizare a tehnicii de
parcurgere pe niveluri a arborilor orientai. O alternativ de implementare a
parcurgerii pe niveluri poate fi descris prin intermediul procedurilor recursive frai
i parc. Coada C este o variabil global i este iniializat cu rdcina arborelui.
Parcurgerea este obinut prin apelul parc(C).
procedure frai(v);
if v0 then
push(C,v);frai(FRATE[v];
endif;
end;
procedure parc;
if Cnil then
pop(C,v);VIZIT(v);
frai(FIU[v]); parc;
endif;
end;
55
Structuri arborescente
4.1.3 Arbori pariali; algoritmul Kruskal
Definiia 4.1.9. Fie G graf. Subgraful parial H este un arbore parial al lui G
dac H este graf arbore.
Definiia 4.1.10. Fie (V,E,w) un graf ponderat conex. Dac T=(V,E
0
) este un
arbore parial al grafului G=(V,E), ponderea arborelui T este definit prin:
W(T)=
0
E e
) e ( w .
Definiia 4.1.11. Fie T(G) mulimea arborilor pariali corespunztori grafului
G. T
0
T(G) este arbore parial minim pentru G dac W(T
0
)=min{W(T); TT(G)}.
Dac G este graf finit, atunci T(G) este mulime finit, deci orice graf finit
ponderat i conex are cel puin un arbore parial minim.
Pentru calculul unui arbore parial minim sunt cunoscui mai muli algoritmi.
n continuare este prezentat algoritmul Kruskal pentru determinarea unui arbore
parial minim al unui graf ponderat conex G=(V,E,w).
Pasul 1: i=1; E
0
=
Pasul 2: Determin mulimea
R={e/eE \ E
i-1
astfel nct graful (V,E
i-1
{e}) este aciclic}
Dac R=, atunci stop;
altfel, selecteaz e
i
R cu w(e
i
)=min{w(e), eR};
E
i
=E
i-1
{e
i
}
Pasul 3: i=i+1 i reia pasul 2.
Structura (V,E
i-1
) calculat de procedur este arbore parial minim al grafului
conex ponderat G.
Ideea algoritmului Kruskal revine la alegerea i includerea n mulimea de
muchii curente a unei muchii de cost minim nc neselectate i astfel nct s nu
formeze un ciclu cu muchiile selectate la etapele precedente. Algoritmul se ncheie
atunci cnd nici o alegere nu mai este posibil. Aplicarea metodei la grafuri neconexe
calculeaz o mulime de arbori pariali minimi, cte un arbore pentru fiecare
component conex.
Pentru implementarea algoritmului Kruskal, graful conex ponderat este
reprezentat sub form tabelar, muchiile fiind ordonate cresctor dup ponderi.
Muchiile selectate de algoritm pot fi meninute, de asemenea, ntr-o structur
tabelar, sau doar marcate ca fiind incluse n mulimea muchiilor arborelui parial
minim a crui construcie este dorit. n varianta prezentat n continuare muchiile
selectate sunt afiate.
Pentru verificarea condiiei ca muchia selectat s nu formeze nici un ciclu
cu muchiile selectate la etapele precedente, este utilizat un vector, TATA. Pentru
fiecare vrf i (vrfurile grafului fiind numerotate de la 1 la n, unde n este numrul
nodurilor grafului), componenta TATA [i] este predecesorul su n arborele care
conine vrful i construit pn la momentul curent, dac i nu este rdcina acelui
56
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
arbore, respectiv TATA[i] este egal cu numrul de vrfuri ale arborelui de
rdcin i, n caz contrar. Componentele vectorului TATA sunt iniializate cu
valoarea -1. Calculul care realizeaz adugarea unei noi muchii poate fi descris
astfel:
- este determinat o muchie de cost minim, e=v1v2, care nu a fost selectat
anterior;
- se verific proprietatea de aciclicitate a grafului care rezult prin eventuala
adugare a muchiei selectate astfel: dac vrfurile v1 i v2 nu aparin
aceluiai arbore, atunci proprietatea de aciclicitate este ndeplinit i
muchia e este adugat la structura curent. Determinarea valorii k
reprezentnd rdcina arborelui care conine vrful dat v rezult prin
parcurgerea vectorului TATA:
k=v;
while TATA[k] >0 do k=TATA[k]
endwhile;
- adugarea muchiei e selectate este realizat prin reunirea arborilor cu
rdcini r1 i r2, din care fac parte v1 i respectiv v2, astfel: dac
TATA[r1]<TATA[r2] (arborele de rdcin r1 conine mai multe vrfuri
dect arborele de rdcin r2), atunci arborele rezultat prin reunirea celor
doi arbori are ca rdcin vrful r1, iar vrful r2 devine fiu al lui r1
(TATA[r2]=r1 i TATA[r1] =TATA[r2]+TATA[r1] (numrul muchiilor
arborelui cu rdcin r1 este crescut cu numrul muchiilor arborelui cu
rdcin r2). n caz contrar se procedeaz analog, rdcina arborelui
rezultat prin reunire fiind r2, iar r1 devenind fiu al rdcinii.
Calculul se ncheie dup ce a fost adugat cea de-a (n-1)-a muchie.
4.2 Arbori binari
4.2.1 Reprezentare; parcurgeri
Definiia 4.2.1. Un arbore binar este un arbore orientat cu proprietatea c
pentru orice vrf v, od(v)2. n cazul od(v)=2, cei doi descendeni sunt desemnai ca
descendent stng (fiu stnga) respectiv descendent drept (fiu dreapta). Pentru
vrfurile cu od(v)=1, unicul descendent este specificat fie ca fiu stnga, fie ca fiu
dreapta.
Definiia 4.2.2. Se numete nod terminal orice vrf v al arborelui cu od(v)=0.
Nodul v este neterminal dac od(v)>0.
Reprezentarea unui arbore binar este realizat prin reinerea, pentru fiecare
nod, a legturilor ctre descendenii lui. Absena unui descendent este reprezentat
prin nil.
57
Structuri arborescente
identificator
nod
legtur fiu
stnga
legtur fiu
dreapta
Structura de date Pascal este:
type arb=^nod;
nod=record;
inf:integer;
fius,fiud:arb;
end;
Definiia 4.2.3. Fie T=(V,E) un arbore binar cu rdcina R. Subarborele
stng al lui T este ST=(V\{R},E\{RS}), unde S este fiul stnga al rdcinii.
Subarborele drept al lui T este DT=(V\{R},E\{RD}), unde D este fiul dreapta al
rdcinii.
n plus fa de metodele deja prezentate pentru parcurgerea arborilor generali
i care sunt aplicabile i n acest caz particular, parcurgerile n preordine(RSD),
inordine(SRD) i respectiv postordine(SDR) sunt special considerate pentru arbori
binari i au multiple aplicaii. Regula de vizitare revine la parcurgerea subarborelui
stng, a subarborelui drept corespunztori vrfului curent. La momentul iniial, vrful
curent este rdcina arborelui. Diferena ntre cele trei tipuri de parcurgere este dat
de momentul n care este vizitat fiecare vrf al arborelui. n parcurgerea RSD
(rdcin-subarbore stng-subarbore drept), fiecare vrf al arborelui este vizitat n
momentul n care devine vrf curent; n parcurgerea SRD (subarbore stng-rdcin-
subarbore drept), vizitarea vrfului este efectuat dup ce a fost parcurs subarborele
stng; n parcurgerea SDR (subarbore stng-subarbore drept-rdcin) vizitarea
fiecrui vrf este efectuat dup ce au fost parcuri subarborii afereni lui.
Procedura preordine realizeaz parcurgerea n preordine, metodele SRD i
SDR fiind propuse cititorului ca exerciii. Procedura preordine este recursiv i are
ca parametru de intrare vrful curent n momentul apelului.
procedure preordine(r:arb);
begin
if r<>nil then
begin
write(r^.inf);
preordine(r^.fius);
preordine(r^.fiud);
end;
end;
58
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
4.2.2 Arbori binari de sortare
Definiia 4.2.4. Un arbore de sortare este un arbore binar cu proprietile:
fiecrui nod i al arborelui i este ataat o informaie INF(i) dintr-o
mulime ordonat de valori;
pentru fiecare nod i, INF(i) este mai mare dect INF(j), pentru toate
nodurile j din subarborele stng al arborelui cu rdcin i;
pentru fiecare nod i, INF(i) este mai mic dect INF(j), pentru toate
nodurile j din subarborele drept al arborelui cu rdcin i;
pentru orice vrfuri i,j, dac ij, atunci INF(i)INF(j).
Exemplu:
4.12. Arborele binar
este de sortare.
Operaiile uzuale efectuate asupra arborilor de sortare sunt inserarea unui
nod, tergerea unui nod i parcurgerea arborelui (n preordine, inordine sau
postordine). Inserarea i tergerea nodurilor ntr-un arbore de sortare trebuie realizate
astfel nct arborele rezultat s fie, de asemenea, arbore de sortare.
Parcurgerea n inordine a unui arbore de sortare determin secvena
vrfurilor arborelui n ordinea cresctoare a informaiilor ataate.
Exemplu:
4.13. Pentru arborele de sortare descris n exemplul 4.12, parcurgerea n
inordine determin secvena de valori: 20,30,40,50,60,70,80,90, adic exact vectorul
de informaii asociate nodurilor ordonat cresctor.
30
70
20
40
60
90
80
50
59
Structuri arborescente
Inserarea unui nod ntr-un arbore de sortare
Algoritmul de inserare a unei informaii nr n arborele de sortare de rdcin
rad este recursiv i const n efectuarea operaiilor. Vrful curent v la momentul
iniial este rdcina arborelui.
- 1. dac arborele de rdcin v este vid (v=nil), este generat arborele cu un
singur nod, avnd nr ca informaie ataat;
- 2. altfel
- a) dac informaia ataat nodului v este mai mare dect nr,
atunci vrful curent devine fiul stnga al lui v;
- b) dac informaia ataat nodului v este egal cu nr, atunci stop
(se previne duplicarea informaiilor ataate vrfurilor arborelui);
- c) dac informaia ataat nodului v este mai mic dect nr,
atunci vrful curent devine fiul dreapta al lui v.
Exemplu:
4.14. Aplicarea algoritmul descris pentru inserarea informaiei 55 n arborele
de sortare din exemplul 4.12 determin urmtoarele operaii:
INF(v)=50<55: se decide inserarea n subarborele drept cu rdcina avnd
informaia ataat 70 (cazul 2.c);
INF(v)=70>55: se decide inserarea n subarborele stng cu rdcina avnd
informaia ataat 60 (cazul 2.a);
INF(v)=60>55: se decide inserarea n subarborele stng cu rdcina nil
(situaia de la 1). Se decide crearea nodului cu informaie 55, fiu stng al nodului de
informaie 60.
Arborele rezultat este:
30
70
20
40
60
90
80
50
55
60
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
tergerea unei informaii dintr-un arbore de sortare
Algoritmul pentru tergerea unei informaii nr din arborele de sortare de
rdcin rad este recursiv este descris n continuare. Vrful curent v la momentul
iniial este rdcina arborelui.
- 1. dac arborele este vid (v=nil) atunci stop (nr nu se afl n mulimea
informaiilor ataate nodurilor arborelui);
- 2. altfel
- a) dac informaia ataat nodului v este mai mare dect nr,
atunci vrful curent devine fiul stnga al lui v ;
- b) dac informaia ataat nodului v este mai mic dect nr,
vrful curent devine fiul dreapta al lui v ;
- c) dac INF(v)=nr atunci:
- c1) dac subarborele stng este vid (v^.fius=nil), atunci
adresa vrfului v este memorat ntr-o celul suplimentar
aux, v devine fiul dreapta al lui v, iar celula aux este
eliberat din memorie (este disponibilizat celula
corespunztoare vrfului din arbore de informaie nr);
- c2) dac subarborele stng este nevid, atunci se determin
cel mai mare element din subarborele stng (este parcurs
subarborele stng pe legturile din dreapta, ct timp acest
lucru este posibil, cu pstrarea i a adresei nodului printe
corespunztor fiecrui vrf atins) :
p:=v^.fius;
while p^.fiud<> nil do
begin
p1:=p;
p:=p^.fiud;
end;
c2.1) dac fiul stnga al lui v nu are subarbore drept
(v^.fius^.fiud=nil), atunci informaia ataat fiului stnga se
transfer n vrful curent, iar fiul stnga (v^.fius) este
nlocuit cu fiul su stnga (v^.fius^.fius) i este eliberat
memoria corespunztoare celulei v^.fius.
c2.2) altfel, se transfer n rdcin informaia ataat
ultimului nod p determinat la c2), nodul p este nlocuit cu
fiul su stng i celula corespunztoare lui p este eliberat
din memorie.
Exemple:
4.15. tergerea informaiei 70 n arborele de sortare din exemplul 4.12 este
realizat astfel:
70>50, decide tergerea din subarborele drept (cu rdcin 70) - situaia 2.b;
70=70, decide tergerea din arborele curent: rdcina etichetat cu 70 -
situaia 2.c;
61
Structuri arborescente
Exist subarbore stng (rdcina lui p este etichetat cu 60) iar acesta nu are
subarbore drept - situaia 2.c.1.: nodul cu informaie 70 este etichetat cu 60, iar p este
nlocuit cu subarborele su stng (vid)
Arborele de sortare rezultat este:
4.16. tergerea informaiei 30 din arborele de sortare:
este realizat astfel:
30>50, decide tergerea din subarborele stng (cu rdcin 30) - situaia 2.a;
30=30, decide tergerea din arborele curent: rdcina etichetat cu 70
situaia 2.c;
30
60
20
40
90
80
50
30
70
20
40
60
90
25
50
10
24
62
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Exist subarbore stng (rdcina este etichetat cu 20), iar acesta are
subarbore drept - situaia 2.c.2: nodul cu informaie 30 este etichetat cu 25
(informaia ultimului nod p detectat la c2)), iar p este nlocuit cu subarborele su
stng (cu rdcin 24).
Arborele rezultat este:
Punctul c) de la pasul 2 poate fi nlocuit cu:
c) dac INF(v)=nr atunci:
- c1) dac subarborele drept este vid (v^.fiud=nil), atunci adresa
vrfului v este memorat ntr-o celul suplimentar aux, v devine fiul stnga al lui v,
iar celula aux este eliberat din memorie (este eliberat vrful de informaie nr);
- c2) dac subarborele drept este nevid, atunci se determin cel mai
mic element din subarborele drept (este parcurs subarborele drept pe legturile din
stnga, ct timp acest lucru este posibil, cu pstrarea i a adresei nodului printe
corespunztor fiecrui vrf atins) :
p:=v^.fiud;
while p^.fius<> nil do
begin
p1:=p;p:=p^.fius;
end;
c2.1.) dac fiul dreapta al lui v nu are subarbore stng
(v^.fiud^.fius=nil), atunci informaia ataat fiului dreapta se
transfer n vrful curent, iar fiul dreapta este nlocuit cu fiul
su dreapta (v^.fiud^.fiud) i este eliberat memoria
corespunztoare celulei v^.fiud.
c2.2) altfel, se transfer n rdcin informaia ataat
ultimului nod p determinat la c2), nodul p este nlocuit cu
fiul su dreapta i celula corespunztoare lui p este eliberat
din memorie.
25
70
20
40
60
90
10
50
24
63
Structuri arborescente
4.2.3 Arbori de structur
Expresiile aritmetice n care intervin numai operatori binari pot fi
reprezentate prin intermediul arborilor strict binari (fiecare nod neterminal are doi
fii). Un arbore de structur are vrfurile etichetate astfel:
- fiecare nod neterminal este etichetat cu un simbol corespunztor unuia
dintre operatori;
- fiecare nod terminal este etichetat cu un operand (variabil sau constant);
Construcia arborelui de structur corespunztor unei expresii aritmetice date
se realizeaz pe baza parantezrii existente n expresie i a prioritilor
convenional asociate operatorilor (ordinea operaiilor) astfel nct rdcina fiecrui
subarbore este etichetat cu operatorul care se execut ultimul n evaluarea
subexpresiei corespunztoare acelui subarbore.
Exemplu:
4.17. Pentru expresia matematic (a+b)*(c-d)+e/g, arborele de structur este:
Construcia arborelui de structur pentru o expresie s se face n dou etape, i
anume:
1. Ataarea prioritilor operatorilor i operanzilor (toi operanzii
au aceeai prioritate, egal cu prioritatea maxim). Prioritile ataate
permit eliminarea parantezelor fr ca semnificaia expresiei s se
modifice;
2. Construcia propriu-zis.
/
+
e
g
b
+
a
c d
64
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Prima etap este realizat astfel:
- prioritatea iniial a operatorilor +,- este 1 (dac expresia nu conine
paranteze, atunci n construcie operatorii vor fi primii luai n considerare,
n ordinea de la dreapta la stnga);
- prioritatea iniial a operatorilor /,* este 10 (dac expresia nu conine
paranteze, acetia sunt considerai dup operatorii de prioritate 1 n
ordinea de la dreapta la stnga);
- prioritatea fiecrui operator este incrementat cu valoarea 10 pentru
fiecare pereche de paranteze n interiorul crora se afl;
- prioritatea ataat fiecrui operand este maxint.
Dup stabilirea sistemului de prioriti, se elimin parantezele din expresie
(ordinea de efectuare a operaiilor n cadrul expresiei este indicat de vectorul de
prioriti ataat).
Exemplu:
4.18. Etapele calculului sistemului de prioriti pentru expresia de la
exemplul 4.17 sunt:
i j dim vectorul prioritate
1 10 0
2 10 1 (maxint)
3 10 2 (maxint,11)
4 10 3 (maxint,11,maxint)
5 0 3 (maxint,11,maxint)
6 0 4 (maxint,11,maxint,10)
7 10 4 (maxint,11,maxint,10)
8 10 5 (maxint,11,maxint,10,maxint)
9 10 6 (maxint,11,maxint,10,maxint,11)
10 10 7 (maxint,11,maxint,10,maxint,11,maxint)
11 0 7 (maxint,11,maxint,10,maxint,11,maxint)
12 0 8 (maxint,11,maxint,10,maxint,11,maxint,1)
13 0 9 (maxint,11,maxint,10,maxint,11,maxint,1,maxint)
14 0 10 (maxint,11,maxint,10,maxint,11,maxint,1,maxint,10)
15 0 11 (maxint,11,maxint,10,maxint,11,maxint,1,maxint,10,maxint)
Dup eliminarea parantezelor, expresia rezultat este s=a+b*c-d+e/g, avnd
ca vector de prioriti (maxint,11,maxint,10,maxint,11,maxint,1,maxint,10,maxint).
Construcia arborelui de structur pe baza expresiei s, din care au fost
eliminate parantezele i a vectorului de prioriti, poate fi realizeaz recursiv n
modul descris n continuare. La momentul iniial expresia curent este cea dat.
65
Structuri arborescente
- Pentru expresia curent se determin operatorul/operandul de prioritate
minim care se ataeaz ca etichet a rdcinii r a subarborelui de
structur corespunztor ei; fie i poziia acestuia n cadrul expresiei;
- Dac expresia are un singur simbol (operand) atunci r^.fius=r^.fiud=nil;
- Altfel, se consider subexpresiile s1 i s2, constnd din simbolurile de pe
poziiile 1 pn la i-1 i respectiv i+1 pn la length(s). Arborii de
structur corespunztori subexpresiilor s1 i s2 se ataeaz ca subarbore
stng, respectiv subarbore drept vrfului r.
Exemplu:
4.19. Pentru expresia de la exemplul 4.17, dup determinarea vectorului de
prioriti i a expresiei neparantezate corespunztoare, procedura cr_der realizeaz
urmtoarea construcie:
s=a+b*c-d+e/g,
prioritate=(maxint,11,maxint,10,maxint,11,maxint,1,maxint,10,maxint)
p=1,u=11 min=1, i=8, arborele:
p=1,u=7 min=10, i=4, arborele:
+
n construcie n construcie
+
* n construcie
n construcie n construcie
66
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
p=1,u=3 min=11, i=2, arborele:
p=u=1 min=maxint, i=1, arborele:
+
+
n construcie
n construcie
n construcie a
+
+
n construcie
n construcie
n construcie n construcie
67
Structuri arborescente
p=3,u=3 min=maxint, i=3, arborele:
p=5,u=7 min=11, i=6, arborele:
+
+
n construcie
n construcie
a
b
+
+
n construcie
n construcie
a
b
n construcie
68
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
p=5,u=5 min=maxint, i=5, arborele:
p=7,u=7 min=maxint, i=7, arborele:
+
+
n construcie
n construcie
a
b
c
+
+
n construcie
a
b
c
d
69
Structuri arborescente
p=9,u=11 min=10,i=10, arborele:
p=9,u=9 min=maxint,i=9, arborele:
+
+
n construcie
a
b
c
d
/
n construcie
+
+
a
b
c
d
/
n construcie
e
70
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
p=11,u=11 min=maxint,i=11, arborele:
i construcia se termin.
Construcia arborelui de structur se face n ipoteza n care expresia este
corect. Procedura cr_der se apeleaz cu:nil,1,length(s),s,prioritate, unde s i
prioritate sunt cei rezultai dup apelarea procedurii prioriti.
Definiia 4.2.5. Se numete forma polonez direct a unei expresii, expresia
rezultat n urma parcurgerii RSD a arborelui de structur. . Se numete forma
polonez invers a unei expresii, expresia rezultat n urma parcurgerii SDR a
arborelui de structur.
Exemplu:
4.20. Pentru expresia considerat la exemplul 4.17, forma polonez direct
este +*+ab-cd/eg. Forma polonez invers a expresiei date este ab+cd-*eg/+.
Parcurgerea arborelui n inordine determin secvena de simboluri rezultat
prin eliminarea parantezelor din expresia dat. Restaurarea unei forme parantezate
poate fi realizat printr-o parcurgere SRD n modul urmtor. La momentul iniial,
vrful curent este rdcina arborelui de structur. Dac vrful curent v nu este vrf
terminal, atunci se genereaz (s1) eticheta(v) (s2), unde eticheta(v) este operatorul
etichet a vrfului, s1 este secvena rezultat prin traversarea SRD a subarborelui
stng, s2 este secvena rezultat prin traversarea SRD a subarborelui drept. Dac v
este vrf terminal, atunci este generat secvena eticheta(v).
+
+
a
b
c
d
/
e
g
71
Structuri arborescente
Exemplu:
4.21. Prin aplicarea traversrii SRD a arborelui de structur al expresiei din
4.2.6, rezult:
s=(((a)+(b))*((c)-(d)))+((e)/(g)).
Se observ c, prin aplicarea traversrii SRD i a parantezrii descrise,
expresia rezultat are aceeai semnificaie cu expresia iniial, dar apar multe
paranteze inutile. Propunem ca exerciiu scrierea unei proceduri Pascal pentru
eliminarea parantezelor inutile.
Evaluarea expresiilor aritmetice pe baza arborilor de structur
Traversarea SRD a arborelui de structur ataat unei expresii aritmetice
permite evaluarea expresiei pentru valorile curente corespunztoare variabilelor.
Evaluarea poate fi efectuat n mod recursiv. La momentul iniial, vrful curent este
rdcina arborelui. Dac v este vrf curent, atunci noua informaie asociat lui v este:
- val(eticheta(v)), dac v este vrf terminal;
- val(s1)eticheta(v)val(s2), dac v este neterminal,
unde val(s1), val(s2) sunt valorile rezultate prin evalurile subarborilor stng
i respectiv drept ai lui v; val(eticheta(v)) este valoarea curent a variabilei, dac
eticheta lui v este variabil, respectiv valoarea constantei, dac eticheta lui v este o
constant.
Dac v este vrf neterminal, atunci noua informaie asociat lui v este
val(s1)eticheta(v)val(s2), ce reprezint rezultatul operaiei eticheta(v) aplicat
valorilor val(s1), val(s2).
Exemplu:
4.22. Prin aplicarea metodei de evaluare descrise, se obine:
15
5
18
3
2
3
5
2
3
6
2
72
Recursivitatea este o tehnic de programare bazat pe apelarea unui
subprogram de ctre el nsui. n cadrul capitolului sunt prezentate calculul recursiv,
metoda divide et impera i metoda backtracking implementat recursiv.
5.1 Calcul recursiv
Calculul valorii n! pentru n dat poate fi efectuat pe baza formulei n!=n(n-1)!,
pentru n 1 i 0!=1. Dac Fact(n) este funcia Pascal care calculeaz n!, atunci, dac
n 1 evaluarea lui Fact(n) rezult prin multiplicarea cu n a valorii calculate de apelul
Fact(n-1), cu Fact(0)=1. Cu alte cuvinte, apelul funciei Fact(n) realizeaz calculul
imediat dac n=0, altfel presupune un nou apel al aceleiai funcii pentru valoarea
argumentului egal cu n-1. Cazurile n care este posibil evaluarea imediat se
numesc condiii terminale.
n Pascal, funcia Fact, este:
function Fact(n:byte):word;
begin
if n=0 then Fact:=1
else Fact:=n*Fact(n-1);
end;
Utilizarea formulei
)! k n ( ! k
! n
C
k
n
> +
+
=
+
< +
=
1 x , 5 x 3
1 x , 2 x 3 x
) x ( g ,
3 x , 2 x
3 x , 1 x 2
) x ( f
2
2
funcia Pascal h(x) este:
76
Algoritmi recursivi. Metodele divide et impera i backtracking
Fig. 5.1 Evoluia n stiv pn la condiia terminal Fact(0):=1
2
Fact=2*Fact(1)
Adresa de revenire
3
Fact=3*Fact(2)
Adresa de revenire
2
Fact=2*Fact(1)
Adresa de revenire
3
Fact=3*Fact(2)
Adresa de revenire
1
Fact=1*Fact(0)
Adresa de revenire
2
Fact=2*Fact(1)
Adresa de revenire
1
Fact=1*Fact(0)
Adresa de revenire
0
Fact=1
Adresa de revenire
(o)
(o)
(o)
(o)
3
Fact=3*Fact(2)
Adresa de revenire
3
Fact=3*Fact(2)
Adresa de revenire
77
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
()
()
()
Stiva vid
Fig. 5.2 Eliberarea stivei dup execuia determinat de condiia terminal
function f(x:real):real;
begin
if x<3 then f:=2*x+1
else f:=x*x+2
end;
function g(x:real):real;
begin
if x<=1 then g:=x*x-3*x+2
else g:=3*x+5
end;
function h(x:real):real;
begin
h:=f(g(f(x)));
end;
2
Fact=2*Fact(1)
Adresa de revenire
3
Fact=3*Fact(2)
Adresa de revenire
1
Fact=1
Adresa de revenire
2
Fact=2
Adresa de revenire
3
Fact=3*Fact(2)
Adresa de revenire
3
Fact=6
Adresa de revenire
78
Algoritmi recursivi. Metodele divide et impera i backtracking
5.2 Metoda divide et impera
Metoda divide et impera presupune descompunerea problemei de rezolvat
n dou sau mai multe subprobleme (probleme mai simple), determinarea soluiilor
acestora care, apoi, compuse dup reguli simple, furnizeaz soluia problemei
iniiale.
De exemplu, se presupune c se dorete aflarea valorii maxime dintr-o
secven } a ,..., a {
n 1
de n numere. Pentru rezolvarea problemei se poate proceda n
mai multe moduri: se determin valoarea cea mai mare din prima jumtate, fie
aceasta x
1
, apoi se determin valoarea cea mai mare din a doua jumtate a secvenei,
fie aceasta x
2
. Soluia problemei este max(x
1
, x
2
). Problema iniial a fost
descompus n dou subprobleme de acelai tip, dar mai simple deoarece lungimea
fiecrei secvene este jumtate din lungimea secvenei iniiale. Problema poate fi
rezolvat pe baza unei metode care o reduce succesiv la o problem mai simpl,
determinndu-se valoarea maxim din primele n-1 componente ale secvenei (fie
aceasta x
1
), valoarea maxim fiind max(x
1
,a
n
). Ambele soluii sunt recursive i sunt
reprezentate prin funciile Pascal max1 i max2.
function max1(var a:vector; s,d:byte):real;
var x1, x2:real;
begin
if s=d then max1=a[s]
else
begin
x1:=max1(a,s,(s+d)div 2);
x2:=max1(a,(s+d)div 2+1,d);
if x1>x2 then max1:=x1
else max1:=x2;
end;
end;
function max2(var a:vector; n:byte):real;
var x1:real;
begin
if n=1 then max2=a[1]
else
begin
x1:=max1(a,n-1);
if x1>a[n] then max1:=x1
else max1:=a[n];
end;
end;
Un alt exemplu n care, pentru rezolvarea problemei, se poate efectua un
raionament similar este urmtorul. Se presupune c ecuaia f(x)=0 are o singur
soluie x
0
n intervalul (a,b). Se dorete obinerea unei valori aproximative x
astfel
nct < x
x
0
, pentru 0 > dat. Deoarece ecuaia f(x)=0 are o singur soluie x
0
n intervalul [a,b], rezult c f(a)f(b)<0 i, de asemenea, dac pentru a<<<b
f()f()<0, atunci ) , ( x
0
. Pe baza aceastei proprieti, dac c este mijlocul
79
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
intervalului (a,b), atunci este ndeplinit una i numai una dintre relaiile f(a)f(c)<0,
f(c)=0, f(b)f(c)<0. Dac f(c)=0, atunci x
0
=c. Dac f(a)f(c)<0 atunci ) c , a ( x
0
,
altfel ) b , c ( x
0
. Se presupune c f(a)f(c)<0. Se poate aplica acelai procedeu
intervalului (a,c) i se continu pn cnd sau este obinut soluia exact sau
intervalul care conine soluia este de lungime inferioar lui . n cazul n care
terminarea calculului se realizeaz prin identificarea unui interval de lungime
inferioar lui , x
N
2
a b
, adic 1
a b
log N
2
+
(
|
.
|
\
|
=
.
Se presupune c funcia f este calculat prin apelul funciei Pascal
f(a:real):real. O variant recursiv a metodei descrise este:
uses crt;
{$F+}
type
fct=function(x:real):real;
var
eps,a,b,x:real;
functie:fct;
function f(x:real):real;
begin
f:=x*x*x-8;
end;
procedure bisectie(a,b,eps:real;var f:fct;var x:real);
var xx:real;
begin
if f(a)=0 then x:=a
else if f(b)=0 then x:=b
else if b-a<eps then x:=(a+b)/2
else
begin
xx:=(a+b)/2;
if f(xx)*f(a)<0 then bisectie(a,xx,eps,f,x)
else bisectie(xx,b,eps,f,x)
end;
end;
begin
clrscr;
write('Introduceti a ');
readln(a);
write('Introduceti b ');
readln(b);
eps:=exp(-20);
functie:=f;
bisectie(a,b,eps,functie,x);
writeln('Solutia este:',x:5:2);
readln;
end.
80
Algoritmi recursivi. Metodele divide et impera i backtracking
De asemenea, rezolvarea problemei turnurilor din Hanoi a fost realizat tot
pe baza unei metode de reducere i anume: problema deplasrii a n discuri P(n) a fost
redus succesiv la rezolvarea problemelor mai simple P(n-1), P(n-2),,P(1).
Unul dintre cei mai eficieni algoritmi pentru sortarea cresctoare a unei
secvene de numere reale este cunoscut sub numele de algoritmul de quicksort
(sortare rapid) i reprezint, de asemenea, un exemplu de aplicare a metodei divide
et impera. Fie secvena (v
p
, v
p+1
, ,v
u
), unde iniial p=1, u=n (n=dimensiunea
vectorului).
Dac p = u, secvena este sortat.
Altfel, se poziioneaz v
p
n aceast secven astfel nct toate elementele ce
ajung n faa lui s fie mai mici dect el i toate cele care i urmeaz s fie mai mari
dect el; fie poz poziia lui corect n secvena (v
p
, v
p+1
, , v
poz
, v
poz+1
, ,v
n
).
Procedeul se reia pentru secvenele (v
p
, v
p+1
, ,v
poz-1
) i (v
poz+1
, v
poz+2
, ,v
n
), deci
p poz-1 i poz+1 u.
Poziionarea elementului v
p
se face astfel: se utilizeaz doi indicatori, i i j;
iniial i = p i j = u. Se compar v
i
cu v
j
, dac nu este necesar interschimbarea, se
micoreaz j cu 1, repetndu-se procesul; dac apare o interschimbare, se mrete i
cu 1 i se continu compararea, mrind i pn la apariia unei noi interschimbri.
Apoi se micoreaz din nou j, continundu-se n acelai mod pn cnd i = j.
Exemplu:
5.1. Aplicarea algoritmului de sortare rapid pentru
v = (10, 12, 19, 15, 3, 17, 4, 18)
1 2 3 4 5 6 7 8
p = 1, u = n = 8
a) poziionarea lui v
p
= v
1
= 10
i=1, j=8
Sensul de parcurgere:
i=1, j=8 10<18 j=j-1
i=1,j=7 10>4 se efectueaz interschimbarea i se atribuie i=i+1=2
v=(4, 12, 19, 15, 3, 17, 10, 18)
i=2, j=7
Sensul de parcurgere:
i=2, j=7 12>10 se efectueaz interschimbarea i se atribuie j=j-1=6
v=(4, 10, 19, 15, 3, 17, 12, 18)
i=2, j=6
Sensul de parcurgere:
i=2, j=6 10<17 j=j-1
i=2, j=5 10>3 se efectueaz interschimbarea i se atribuie i=i+1=3
v = (4, 3, 19, 15, 10, 17, 12, 18)
i=3, j=5
Sensul de parcurgere:
i=3, j=5 19>10 se efectueaz interschimbarea i se atribuie j=j-1=4
81
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
v=(4, 3, 10, 15, 19, 17, 12, 18)
i=3, j=4
Sensul de parcurgere:
i=3, j=4 10<15 j=j-1
i=3, j=3 i=j, poziionare realizat
b) Se obine vectorul:
v=(4, 3, 10, 15, 19, 17, 12, 18)
1 2 3 4 5 6 7 8
poz=3, se lucreaz cu secvenele
(4, 3) i (15, 19, 17, 12, 18)
Primul nivel de recursie:
Pentru Sv1=(4, 3) p=1, u=2
a1) poziionarea lui 4:
i=1, j=2
Sensul de parcurgere:
i=1,j=2 4>3 se efectueaz interschimbarea i se atribuie i=i+1=2
sv1 (3, 4) , poz=2
i=j=2, stop
b1) se ajunge la scevenele (3) i ; acestea sunt sortate
Pentru sv2 = (15, 19, 17, 12, 18)
4 5 6 7 8
a1) poziionarea lui 15
i=4, j=8
Sensul de parcurgere:
i=4, j=8 15<18 j=j-1=7
i=4, j=7 15>12 se efectueaz interschimbarea i se atribuie i=i+1=5
sv2=(12, 19, 17, 15, 18)
4 5 6 7 8
i=5, j=7
Sensul de parcurgere:
i=5, j=7
19>15 se efectueaz interschimbarea i se atribuie j=j-1=6
sv2=(12, 15, 17, 19, 18)
4 5 6 7 8
i=5, j=6
Sensul de parcurgere:
i=5, j=6 15<17 j=j-1
i=5, j=5 i=j poziionare realizat
sv2=(12, 15, 17, 19, 18)
4 5 6 7 8 poz = 5
b1)Se obine secvena sv2=(12, 15, 17, 19, 18)
4 5 6 7 8
poz=5; se lucreaz mai departe cu secvenele
82
Algoritmi recursivi. Metodele divide et impera i backtracking
sv3=(12) sortat
sv4=(17, 19, 18)
6 7 8
n acest moment, v=(3, 4, 10, 12, 15, 17, 19, 18)
Al doilea nivel de recursie - avem numai secvena
sv4=(17, 19, 18)
6 7 8
a2) poziionarea lui 17
i=6, j=8
Sensul de parcurgere:
i=6, j=8 17<18 j=j-1=7
i=6, j=7 19<19 j=j-1=6
i=j=6 - poziionare realizat
b2) Se obine sv4=(17, 19, 18), poz=6,
6 7 8
se lucreau mai departe cu secvenele
sv5= sortat
sv6=(19, 18)
7 8
n acest moment v=(3, 4, 10, 12, 15, 17, 19, 18)
Al treilea nivel de recursie - avem numai secvena
sv6=(19, 18)
7 8
a3) poziionarea lui 19
i=7, j=8
Sensul de parcurgere:
i=7, j=8 19>18 se interschimb i i=i+1=8
sv6=(18,19)
i=j=8, poziionare realizat
b3) S-a obinut secvena sv6=(18, 19), poz=8
Urmtoarele secvene sunt sv7=(18), sv8= , ambele sortate
Calculul se ncheie, v=(3, 4, 10, 12, 15, 17, 18, 19) este sortat cresctor.
program quick_sort;
uses crt;
var
x:array[1..100] of integer;
n,i:byte;
procedure poz(p,u:byte; var k:byte);
var
i,j:byte;
l,di,dj:shortint;
{di, dj: pasii de incrementare pentru i si j;
ei indica sensul parcurgerii}
v:integer;
83
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
begin
i:=p;j:=u;di:=0;dj:=-1;
while i<j do
if x[i]>x[j] then
begin
v:=x[i];
x[i]:=x[j];
x[j]:=v;
l:=di;di:=-dj;dj:=-l;
i:=i+di;j:=j+dj;
end
else begin
i:=i+di;j:=j+dj;
end;
k:=i;
end;
procedure quick(p,u:byte);
var
i:byte;
begin
if p>=u then
else begin
poz(p,u,i);
quick(p,i-1);
quick(i+1,u);
end;
end;
begin{ program principal}
clrscr;
write('Dimensiunea vectorului:');
readln(n);
for i:=1 to n do
read(x[i]);
quick(1,n);
for i:=1 to n do
write(x[i],' ');
end.
n programul quick_sort, pentru simularea sensurilor de parcurgere, s-a
lucrat cu incremeni pentru i i j, desemnai prin di, respectiv dj. Pentru sensul de
parcurgere (de la sfritul secvenei spre nceputul ei) i rmne constant (di=0)
i j este decrementat cu o unitate (dj=-1). Pentru cellalt sens, j rmne constant
(dj=0) i este incrementat i (di=1). Trecerea de la un sens la cellalt, efectuat n
momentul unei interschimbri, determin secvena de operaii:
l=dj;
di=dj;
dj=-l;
adic di este interschimbat cu dj. Vectorul de sortat x este variabil global
procedurii quick.
Soluiile recursive propuse n exemplele precedente se bazeaz fie pe o metod
de tip reducere, fie pe o metod de descompunere. n toate cazurile a fost posibil
sinteza unei soluii a problemei date din soluiile subproblemelor la care problema
84
Algoritmi recursivi. Metodele divide et impera i backtracking
s-a redus, respectiv n care s-a descompus. De asemenea, pentru fiecare dintre
problemele considerate au fost definite subproblemele primitive (condiiilor
terminale) a cror soluie este cunoscut sau dat. Metoda de rezolvare se numete
divide et impera (dezbin i stpnete) i semnific ideea prin care este realizat
construcia soluiei.
5.3 Metoda backtracking
Pentru rezolvarea anumitor probleme este necesar desfurarea unui proces
de cutare a soluiei aflate ntr-o anumit mulime, numit spaiul strilor. Pentru
fiecare element din spaiul strilor este definit o mulime de aciuni sau alternative.
Momentul iniial n rezolvarea problemei corespunde unei stri, numit iniial, iar
soluiile corespund drumurilor n spaiul strilor, de la cea iniial pn la una final.
Procesul de rezolvare a problemei poate fi imaginat ca o secven de aciuni care
asigur deplasarea (prin intermediul unei secvene de stri) n spaiul strilor din
starea iniial la cea final. n cazul anumitor probleme se dorete obinerea unei
singure soluii, altele solicit determinarea tuturor soluiilor sau determinarea unei
soluii optime, dintr-un anumit punct de vedere (soluie optimal).
Se presupune c problema const n a ajunge n vrful unui munte pornind de
la baza lui. n general, exist mai multe puncte din care se desprind mai multe poteci,
dar nu neaprat toate conduc spre vrful muntelui. n acest caz, starea iniial este
baza muntelui, exist o singur stare final i anume vrful muntelui, spaiul strilor
incluznd i toate punctele de ramificare a drumului. O soluie poate fi apreciat ca
optimal din mai multe puncte de vedere: un drum care solicit cel mai mic efort din
partea celui care-l urmeaz; un cel mai scurt drum; un drum care trece printr-un
punct preferat etc.
Un alt exemplu este un labirint avnd una sau mai multe ieiri. Starea iniial
poate fi considerat orice camer a labirintului, problema revenind la gsirea unui
drum din camera respectiv ctre una dintre ieiri. Desfurarea procesului de cutare
a unei stri finale presupune, la fiecare etap, alegerea opiunii pentru o alternativ
posibil a strii curente i detectarea acelor stri capcan din care nu mai este
posibil continuarea procesului, sau deja se cunoate excluderea atingerii unei stri
finale. Detectarea strii capcan trebuie s determine revenirea la starea din care
s-a ajuns la ea i selectarea unei noi opiuni de continuare. n cazul n care nu mai
exist alternative care s nu fi fost selectate anterior, o astfel de stare devine la rndul
ei capcan i pentru ea se aplic acelai tratament.
Prin soluie a problemei se nelege o secven de aciuni care determin
tranziia din starea iniial ntr-o stare final, fiecare component a unui drum soluie
reprezentnd o alternativ din mulimea de variante posibile. Cu alte cuvinte, x
1
este
alternativa aleas pentru starea iniial, x
2
este alternativa selectat pentru starea n
85
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
care s-a ajuns pe baza opiunii x
1
.a.m.d. Dup efectuarea aciunii corespunztoare
alegerii alternativei x
n
rezult o stare final.
Forma standard a metodei corespunde unei probleme n care trebuie gsit un
drum soluie x=(x
1
, x
2
, ..., x
n
) cu x
i
S
i
, unde fiecare mulime S
i
este finit i conine
s
i
elemente. n plus, se presupune c fiecare S
i
este ordonat i reprezint mulimea
alternativelor existente la momentul i al cutrii.
n anumite cazuri intereseaz obinerea unei singure soluii, n altele sunt
cutate toate soluiile problemei sau cele care ndeplinesc un criteriu dat (de
exemplu, se maximizeaz sau minimizeaz o funcie f definit pe mulimea
drumurilor soluie din spaiul strilor).
Procesul de cutare a unui drum soluie revine la tentativa de extindere a
poriunii de drum construit, alegnd prima alternativ disponibil pentru starea
curent atins. Continuarea drumului poate fi realizat pn la atingerea unei stri
finale sau pn la ntlnirea unei stri capcan (mulimea vid de alternative). Dac
este atins o stare capcan, atunci este necesar revenirea la starea anterioar i
selectarea urmtoarei alternative disponibile acestei stri. Dac nu mai exist
alternative disponibile, atunci se iniiaz o nou revenire .a.m.d. n cazul n care
exist cel puin nc o alternativ disponibil, atunci se reia procesul de extindere a
drumului rezultat. n condiiile n care revenirea poate conduce la atingerea strii
iniiale i pentru ea nu mai exist alternative disponibile, se consider c problema nu
are soluie.
Pentru implementarea cutrii este necesar reinerea alternativei selectate
pentru fiecare stare atins pn la cea curent, astfel nct, n cazul unei reveniri s
fie posibil alegerea alternativei urmtoare. Cu alte cuvinte, procesul de cutare
revine la tentativa de extindere a drumului curent (pasul de continuare), cu eventuala
revenire n cazul atingerii unei stri capcan (pasul de revenire - back), memornd
alternativele selectate pentru fiecare stare intermediar atins (track). De aici i are
geneza numele metodei backtracking.
Pentru determinarea unei singure soluii, descrierea pe pai a metodei este:
starea iniial a problemei este prima alternativ posibil pentru starea
curent ; fie aceasta x
1
S
1
;
dac starea curent rezultat prin alternativa x
1
este final, atunci x=(x
1
)
este soluie; stop;
altfel, este selectat prima alternativ din mulimea de aciuni posibile
pentru starea curent; fie aceasta x
2
S
2
;
dac secvena de alternative care a condus la starea curent este
x=(x
1
, x
2
,..., x
k
), atunci:
dac starea curent este final, soluia este x=(x
1
, x
2
,..., x
k
); stop;
altfel
B1: dac pentru starea curent exist alternative disponibile,
atunci se alege prima dintre ele i se continu;
86
Algoritmi recursivi. Metodele divide et impera i backtracking
B2: altfel, se revine la starea anterioar celei curente, soluia
parial construit devine x=(x
1
, x
2
,..., x
k-1
) i se efectueaz B1.
dac, n urma unui pas de revenire, s-a ajuns la starea iniial i nu
mai sunt alternative disponibile, atunci problema nu are soluie; stop.
n cazul n care trebuie determinate toate soluiile problemei, cutarea
continu dup determinarea fiecrei soluii prin efectuarea de reveniri succesive.
Terminarea cutrii este decis n momentul n care s-a revenit la starea iniial i nu
mai exist alternative disponibile.
Dac se dorete obinerea numai a soluiilor care optimizeaz o funcie
criteriu f, atunci metoda se aplic pentru determinarea tuturor soluiilor problemei,
fiecare nou soluie rezultat fiind comparat cu cea mai bun soluie determinat
anterior. Pentru aceasta este necesar reinerea celei mai bune soluii calculate la
fiecare moment.
Forma general a metodei backtracking este implementat de procedura
back.
procedure back(k:byte);
begin
if k=n+1 then final
else
begin
x[k]:=init(k);
while succ(k) do
if continuare(k) then back(k+1);
end;
end;
n care:
final este o procedur care descrie prelucrarea dorit pentru o soluie
determinat (se afieaz rezultatul, se testeaz o funcie criteriu pentru soluia
obinut samd);
init(k) efectueaz iniializarea lui x
k
cu o valoare prin care se indic faptul
c, pn la acel moment, nu a fost selectat nici o alternativ pentru poziia k;
succ(k) este o funcie boolean care calculeaz true, dac i numai dac
exist succesor pentru x
k
n S
k
;
continuare(k) este o funcie boolean pentru testarea condiiilor de
continuare; calculeaz true dac i numai dac este posibil extinderea drumului
curent.
n continuare sunt prezentate cteva probleme rezolvate prin metoda
backtracking.
1. S se genereze toate permutrile mulimii {1, 2,..., n}.
n acest caz, S
1
= S
2
= ... = S
n
= {1, 2,..., n}. Alternativele posibile pentru
starea iniial corespund alegerilor pentru prima poziie dintr-un vector soluie.
Pentru fiecare k, 1 n k 1 , dac x=(x
1
, x
2
,..., x
k
) este drumul calculat pn la
87
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
momentul k, atunci k j i 1 , x x
j i
i alternativele posibile pentru starea
curent sunt elementele x
k+1
din mulimea {1, 2,..., n}care ndeplinesc cerina
k i 1 , x x
1 k i
+
.
De exemplu, pentru n=3, soluiile problemei sunt:
x1=(1,2,3), x2=(1,3,2), x3=(2,1,3), x4=(2,3,1), x5=(3,1,2), x6=(3,2,1).
Funcia init(k) realizeaz iniializarea elementului x[k] cu valoarea 0, pentru
a marca faptul c, pn la momentul curent, nu a fost selectat nici o alternativ
pentru x[k]. Funcia succ(k) calculeaz true dac elementul x[k] are succesor n
mulimea {1, 2,..., n}, caz n care acesta este determinat prin incrementare. Altfel,
funcia calculeaz false. Funcia continuare(k) returneaz true dac i numai dac
secvena (x
1
, x
2
,..., x
k
) calculat pn la momentul curent este corect, conform
regulilor descrise anterior.
Conform schemei generale, programul Pascal este:
program permutare;
uses crt;
type tip_elem=0..7;
var x:array[1..7] of tip_elem;
n:byte;
function init:byte;
begin
init:=0;
end;
function succ(k:byte):boolean;
begin
succ:=x[k]<n; {atribuire de valoare logica}
inc(x[k]);
end;
function continuare(k:byte):boolean;
var i:byte;
begin
i:=1;
while(i<k)and(x[i]<>x[k]) do inc(i);
continuare:=i=k; {atribuire de valoare logica}
end;
procedure final;
var i:byte;
begin
for i:=1 to n do write(x[i],' ');
readln;
end;
procedure back(k:byte);
begin
if k=n+1 then final
else
begin
x[k]:=init;
while succ(k) do
if continuare(k) then back(k+1);
88
Algoritmi recursivi. Metodele divide et impera i backtracking
end;
end;
begin
clrscr;
write('Numarul de elemente ale permutarii: ');
readln(n);
back(1);
end.
n cazul acestei probleme este posibil operarea unor simplificri n scrierea
codului, pe baza observaiilor:
- funcia init(k) nu depinde de valoarea lui k i returneaz ntotdeauna
valoarea 0;
- funcia succ(k) nu depinde de valoarea parametrului k i realizeaz
ntotdeauna o incrementare (S
1
= S
2
= ... =S
n
= {1, 2,..., n}).
Procedura back(k) poate fi descris fr a utiliza funciile init i succ, astfel:
procedure back(k:byte);
var i:byte;
begin
if k=n+1 then final
else
for i:=1 to n do
begin
x[k]:=i;
if continuare(k) then back(k+1);
end;
end;
nlocuirea n procedura back a structurii repetitive while cu ciclul for este
posibil datorit faptului c funcia succ realiza incrementarea valorii elementului
x[k].
Varianta de program Pascal rezultat n urma acestor simplificri este:
program permutare_1;
uses crt;
type tip_elem=0..7;
var x:array[1..7] of tip_elem;
n:byte;
procedure final;
var i:byte;
begin
for i:=1 to n do write(x[i],' ');
readln;
end;
function continuare(k:byte):boolean;
var i:byte;
begin
i:=1;
while(i<k)and(x[i]<>x[k]) do inc(i);
continuare:=i=k;
end;
procedure back(k:byte);
89
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
var i:byte;
begin
if k=n+1 then final
else
for i:=1 to n do
begin
x[k]:=i;
if continuare(k) then back(k+1);
end;
end;
begin
clrscr;
write('Numarul de elemente ale permutarii: ');
readln(n);
back(1);
end.
2. Se presupune c se dispune de n tipuri de bancnote, n20, cu valori
diferite; din fiecare tip se dispune de un numr cunoscut de bancnote. Considern-
du-se dat o sum de bani s, s se determine o modalitatea de plat a sa utilizndu-se
un numr minim de bancnote.
Valorile i numrul de bancnote disponibile din fiecare tip sunt memorate
ntr-o tabel y cu 2 linii i n coloane, astfel: pentru fiecare 1 n i , y[1,i] reprezint
valoarea unei bancnote de tipul i i y[2,i] este numrul de bancnote disponibile din
tipul i. Vectorul xb memoreaz modalitatea optim de plat a sumei s, adic xb[i]
reprezint numrul de bancnote alese din tipul i ntr-o descompunere optim;
vectorul x memoreaz descompunerea curent. Numrul minim de bancnote utilizate
n plata sumei s este nrb.
Metoda utilizat n rezolvarea problemei este backtracking, urmrindu-se
minimizarea funciei
=
=
n
1 i
] i [ x ) x ( f , n condiiile n care s ] i , 1 [ y ] i [ x
n
1 i
=
=
i
n ,..., 1 i ], i , 2 [ y ] i [ x 0 = . Sunt generate toate descompunerile posibile ale sumei
s funcie de bancnotele disponibile i, la fiecare moment n care este determinat o
astfel de descompunere, aceasta este comparat cu precedenta. n vectorul xb este
memorat o cea mai bun descompunere pe baza criteriului f, dup fiecare astfel de
comparaie.
program bancnote;
uses crt;
var x,xb:array[1..100] of longint;
y:array[1..2,1..20]of longint;
n,i,nrb:word;
s:longint;
function init(k:word):longint;
begin
init:=-1;
end;
function urm(k:word):boolean;
begin
90
Algoritmi recursivi. Metodele divide et impera i backtracking
urm:=x[k]<y[2,k];inc(x[k]);
end;
function continuare(k:word):boolean;
var
sc,i:longint;
begin
sc:=0;
for i:=1 to k do sc:=sc+x[i]*y[1,i];
if k<n then continuare:=sc<=s
else continuare:=sc=s;
end;
procedure final(k:word);
var i:byte;
nr:longint;
begin
nr:=0;
for i:=1 to n do
begin
nr:=nr+x[i];
end;
if nr<nrb then
begin
for i:=1 to n do xb[i]:=x[i];
nrb:=nr;
end;
end;
procedure back(k:byte);
begin
if k=n+1 then final(k)
else
begin
x[k]:=init(k);
while urm(k) do
if continuare(k) then back(k+1)
end;
end;
begin
clrscr;
write('Dati numarul de bancnote');
readln(n);
writeln('Valorile si numarul de exemplare:');
for i:=1 to n do
begin
write('Valoarea:');readln(y[1,i]);
write('Numar de bancnote:');readln(y[2,i]);
end;
write('Suma schimbata:');
readln(s);
nrb:=maxint;
back(1);
writeln('Numarul minim de bancnote:',nrb);
writeln;
writeln('Numarul de bancnote alese din fiecare tip:');
for i:=1 to n do
writeln('Tip ',i,' numar de bancnote alese:',xb[i]);
end.
91
Forma i formatul afirii datelor pe monitor (ca ecou al introducerii de la
tastatur sau ca rezultat al scrierii) precum i modul n care se desfoar conversaia
n timpul acestui proces constituie interfaa programului cu utilizatorul. Realizarea
unei interfee eficiente i atractive trebuie s constituie pentru programator un
obiectiv la fel de important ca i cel al atingerii performanelor ridicate de eficien a
programului nsui.
6.1 Resursele i modurile de lucru video
ale unui microcalculator
n procesul afirii video a datelor sunt implicate componente hardware i
software, care interacioneaz pentru crearea imaginii pe ecranul monitorului
(figura 6.1).
Fig. 6.1 Componente implicate n afiarea video a datelor
Interfaa video
(Logic de comand)
Memoria ecran
Software
Monitor
Placa grafic
Memoria ecran, de tipul RAM, are rolul de a stoca, sub form binar,
imaginea care se afieaz pe ecran. Ea poate avea diferite capaciti - uzual, pn la 1
REPREZENTAREA VIZUAL
A DATELOR
92
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
MB i este mprit n pagini de o anumit mrime, n care se pot memora
concomitent una sau mai multe imagini de ecran. n plus, se pot memora definiiile
binare ale unor seturi de caractere pentru afiarea textelor cu modele de caractere
(fonturi) ale utilizatorului, altele dect cele definite de generatorul de caractere al
interfeei video.
Interfaa video (adaptorul video) are rolul de a comanda i controla
monitorul pentru crearea imaginii pe tub catodic. Ea comunic cu UC a
microcalculatorului i cu memoria ecran prin magistrale de date i de adrese. UC i
interfaa pot utiliza simultan memoria ecran (prin porturi diferite), astfel nct
microprocesorul poate nscrie date n memoria ecran n timp ce interfaa citete
memoria pentru a realiza afiarea (figura 6.2).
Fig. 6.2 Modul de interaciune a interfeei video
Microproceso
r
Memoria
ecran
Magistrala de date
Magistrala de adrese
Controler
video
Monitor
Generator
de semnale
Registru de
deplasare
Generator
de caractere
Sincronizare
Interfa video
Semnale de comand
Controlerul video (logica de comand) al interfeei citete periodic, cu o
anumit frecven, memoria de ecran i formeaz semnalele de comand pentru
monitor n vederea crerii i meninerii imaginii video. Dac frecvena de refacere a
imaginii pe ecran (frecvena de remprosptare) este de peste 50 Hz (de obicei
50-70 Hz), atunci, datorit ineriei ochiului, imaginea apare ca fiind continu i fr
plpiri.
Generatorul de caractere este dispozitivul interfeei care produce imaginile
(matricele) punctiforme ale caracterelor ASCII de afiat. Prin comanda dat de
controler i utiliznd caracterele ASCII citite din memoria ecran, generatorul de
caractere produce, la ieire, matricele discrete care definesc caracterele. Pe baza lor i
a atributelor de afiare asociate, aduse de controler din memoria de ecran, generatorul
de semnale produce semnalele seriale care comand monitorul. Serializarea n
producerea semnalelor este asigurat prin intermediul unui registru de deplasare care
furnizeaz, pe rnd, cte un element de imagine.
93
Reprezentarea vizual a datelor
Monitorul utilizeaz un tub catodic monocrom sau color i creeaz
imaginea pe ecran, de sus n jos. Fascicolul de electroni aprinde, pe rnduri sau
linii, puncte elementare din suprafaa fluorescent a tubului catodic, n conformitate
cu semnalele discrete de comand trimise de sistemul de baleere a ecranului.
Punctele elementare de imagine sunt denumite pixeli (picture elements) i
apar pe monitor organizate matriceal, definind spaiul fizic sau spaiul ecran
(figura 6.3). n acest spaiu, pixelii pot fi adresai printr-o pereche de numere naturale
(x, y), unde x este numrul coloanei i y este numrul liniei. De remarcat faptul c, n
acest spaiu, abscisa crete normal, de la stnga spre dreapta, dar ordonata crete de
sus n jos.
Fig. 6.3 Spaiul ecran
x
y
(0,0)
(x,y)
(x
max
,y
max
)
Numrul total de pixeli care pot fi tratai independent constituie o
caracteristic a monitorului, denumit rezoluia ecranului. Rezoluia poate fi joas
(cca.320 x 200 pixeli), medie (cca.640 x 200 pixeli) i nalt (peste 640 x 350 pixeli).
Interfeele video sunt proiectate astfel nct pot lucra cu monitoare de diferite
rezoluii, pentru un monitor simulnd toate rezoluiile inferioare celei date. Imaginea
este cu att mai clar cu ct rezoluia utilizat n realizarea ei este mai mare. De
regul, n construcia microcal culatoarelor, interfaa video i memoria de ecran sunt
realizate pe o plac unic, numit plac grafic. Puterea plcii grafice este cea care
d, n principal, puterea de afiare a datelor pe ecran. n prezent, microcalculatoarele
sunt echipate cu plci grafice de mare putere, de tipul SVGA (Super Video Graphic
Array), realizate dup standardul firmei IBM pentru utilizatori profesionali. Ele sunt
compatibile cu plci realizate anterior (MDA, CGA i EGA), al cror mod de lucru l
pot realiza, oferind n plus o rezoluie nalt i o palet bogat de culori i nuane de
gri (pentru monitoare monocrome).
Partea de software implicat n afiarea video are rolul de a comanda
interfaa video n realizarea diferitelor operaii necesare afirii: alegerea modului de
afiare - text sau grafic - definirea poziiei spaiului ecran pentru afiare, definirea
atributelor de afiare etc. Ea este constituit din rutine BIOS multifuncionale (cu mai
multe servicii) care se apeleaz prin intermediul tehnicii ntreruperilor software.
Tipic este INT 10h, care ofer o serie de servicii video standard. n program, nainte
de cererea ntreruperii, codul serviciului dorit trebuie ncrcat ntr-un registru special
94
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
(AH), iar ali parametri, dac sunt necesari, se ncarc n alte registre (AL, BH, BL,
DH, DL).
6.2 Moduri video
Din punctul de vedere al constituirii imaginii, interfaa video poate lucra n
dou moduri: text i grafic.
n modul text, ecranul este vzut ca o matrice de linii i coloane de text.
Locul de afiare a unui caracter n spaiul ecran este dat de o pereche (x,y) de numere
naturale, cu x=numrul coloanei i y=numrul liniei (figura 6.4.a).
Fig. 6.4 Ecranul n modul text
x
(nr. coloan)
y
(nr. linie)
caracter
0 1 2
0
1
l
max
c
max
ecran 25*80
l
max
=24
l
max
=24
c
max
=79
c
max
=39
ecran 25*40
a) Spaiul
######
######
#####
#####
#####
####
#####
####
#####
#####
#####
######
######
########
b) Matricea de caractere
8
14
Deoarece spaiul text rezult prin gruparea corespunztoare a liniilor i
coloanelor de pixeli, afiarea caracterelor se face, n mod natural, prin matrice de
caractere (figura 6.4.b). O astfel de matrice, de regul 8x14 sau 8x8, definete forma
caracterului prin pixelii aprini, iar fondul prin pixelii stini. n fondul caracterului se
cuprind pixeli de separare a caracterelor pe coloane i linii. Caracterele realizate
astfel se numesc caractere matriceale sau rastru. De regul, n memoria ROM a
calculatorului se definesc patru seturi de caractere, avnd forme (fonturi) tipice
(scriere standard, caractere italice etc). La pornirea calculatorului sau la cererea
95
Reprezentarea vizual a datelor
programatorului, ele sunt ncrcate n memoria de ecran pentru a fi accesibile
generatorului de caractere. Un anumit set, implicit sau cerut de utilizator (via INT
10h), va deveni set curent pentru generator. Exist posibilitatea ca programatorul
s-i defineasc n memoria calculatorului propriile seturi de caractere (cel mult patru
odat), pe care s le ncarce n memoria ecran i din care, apoi, s defineasc setul
curent (ambele sunt servicii INT 10h).
Datorit adresabilitii spaiului text, exist posibilitatea de a comanda (INT
10h) poziia de afiare a unui caracter. n acest scop, interfaa pstreaz n registre
speciale coordonatele locului de afiare, iar pe ecran acesta este marcat prin afiarea
unui caracter special, denumit cursor (de regul, un dreptunghi umplut sau luminos).
Atunci cnd se afieaz un caracter n poziia de la cursor (poziia curent), acesta se
suprascrie peste cursor, iar cursorul este mutat automat cu o poziie spre dreapta i n
jos, la nceputul noului rnd, dac este cazul. Prin servicii ale rutinei INT 10h se
poate defini o form proprie a cursorului n modul text i se poate afla locul acestuia
pe ecran.
Fiecrui caracter de afiat i se asociaz un caracater de atribute (figura
6.5.a).
Fig. 6.5 Definirea atributelor de afiare
a) caracter de atribute b) registru de palet
7 6 5 4 3 2 1 0
Culoare de
fond
Culoare de
caracter
Intensitatea
culorii
(1=da, 0=nu)
Clipire
(1=da, 0=nu)
byte 0 1 2 ... 15
culoare negru albastru ... alb
cod 0 1 ... 53
Caracterul de atribute, prin valorile biilor si, definete culoarea de fond a
caracterului (background color), culoarea de caracter (foreground color) i faptul c
imaginea caracterului se va stinge intermitent (clipire - blinking). Se observ c se
pot defini cel mult 8 culori pentru fond i 16 culori de caracter, dac se consider c
afiarea normal i intens definesc dou culori diferite. Dac ecranul este
monocrom, atunci se pot combina culorile alb i negru.
Pentru variabilitate n exprimarea culorilor i pentru asigurarea
independenei fa de conveniile de notare a lor la diverse plci grafice, s-a adoptat
ideea specificrii indirecte a culorilor. Interfaa posed un registru, de regul de
16 octei, denumit registru de palet, prin care se specific culorile care pot fi
utilizate la un moment dat (figura 6.5.b). Fiecare poziie din registrul de palet
definete, prin cod, o culoare i, n ansamblu, constituie paleta curent de culori.
96
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Astfel, n caracterele de atribute se specific numrul intrrii din paleta curent
(index), de unde trebuie extras codul culorii dorite. Pe baza acestei idei, n orice
moment, poate fi modificat coninutul registrului de palet (serviciu INT 10h), ceea
ce conduce, n mod automat, la modificarea culorilor pentru ntregul text afiat pe
ecran. La pornirea calculatorului, registrul de palet este ncrcat cu o palet iniial
(implicit), definit n memoria ROM. Programatorul poate schimba, total sau
parial, culorile n registrul de palet, depinznd de tipul plcii grafice i aceasta este
unica operaie pentru care trebuie cunoscute codurile culorilor la placa respectiv.
Trebuie remarcat c unele monitoare nu pot afia toate culorile, dei interfaa cu care
sunt cuplate accept specificarea oricrui atribut.
Definirea caracterului de atribute se face prin serviciul INT 10h, care
realizeaz scrierea caracterului text ca parametru ntr-un registru (registrul BL).
Scrierea unui caracter poate fi nsoit de operaia SAU EXCLUSIV (suma
modulo-2, notat ) ntre culoarea caracterului afiat ntr-o anumit poziie i
culoarea noului caracter, destinat a fi afiat n aceeai poziie. Operaia poate fi
utilizat pentru scrierea i tergerea caracterelor (tergerea selectiv). De exemplu,
pentru tergere, dac culoarea este 0101 i se aplic o suprascriere cu aceeai culoare,
atunci, cum 01010101=0000, se obine un cod care desemneaz culoarea fondului
curent, adic, de fapt, dispariia caracterului de pe ecran.
Avnd n vedere c necesarul de memorie ecran este n jur de 4KB 25*80,
depinznd de rezoluia n modulul text, n memoria video se pot focaliza una sau mai
multe pagini video (ecrane). Se creeaz posibilitatea constituirii textului ntr-o
anumit pagin, denumit pagin video, selectat din mulimea paginilor acceptate
de interfaa respectiv prin serviciul INT 10h. Orice poziie i deplasare a cursorului
pe ecran i are echivalentul ntr-o poziie i o deplasare corespunztoare n pagina
video selectat. Din mulimea paginilor definite, programatorul poate selecta una, ca
pagin de afiare pe ecran, denumit pagin activ. Astfel crete viteza de lucru prin
suprapunerea operaiei de afiare cu operaia de pregtire a imaginii, ntr-o nou
pagin video. Interogarea, prin INT 10h, n legtur cu atributele unui anumit
caracter al imaginii este, de fapt, o citire din pagina video a memoriei ecran, eventual
pagina activ.
Modul text permite definirea, n pagina activ, a ferestrelor de text. O
fereastr text este o zon de afiare, format din una sau mai multe linii i coloane
consecutive. Ferestrele text se definesc i se selecteaz prin INT 10h. Definirea se
realizeaz prin precizarea coordonatelor din spaiul text ale colului stnga sus i
respectiv ale colului dreapta jos. n fereastr se poate realiza o operaie de defilare n
sus (jos) care deplaseaz textul rndurilor cu un numr de poziii n sus (jos) i umple
rndurile eliberate, la partea de jos (sus), cu caracterul blank (tergere). Se pot scrie
rnduri noi de text n rndurile eliberate, eventual n toat fereastra activ. Rndurile
de text care ies din fereastr, prin defilare, se pierd. La limit i n mod implicit,
fereastra text este ntreaga pagin activ.
n modul grafic, imaginea se constituie prin aprinderea mulimilor de pixeli
(desen prin puncte - pixel mode). Imaginea se creeaz n memoria ecran, n pagini,
dac placa grafic permite mai multe pagini i se afieaz pe ecran, pagin cu pagin.
97
Reprezentarea vizual a datelor
O pagin video utilizeaz un bit pentru a defini starea fiecrui pixel al ecranului
(1=aprins, 0=stins) i un numr de bii suplimentari pentru a defini culoarea
acestora. Deoarece culorile se definesc pe baza registului de palet, dac se
utilizeaz concomitent 16 culori, sunt necesari 4 bii suplimentari. Rezult c o
pagin video trebuie s aib cel puin 4rezoluie bii. De exemplu, pentru o plac
EGA, cu rezoluie nalt, sunt necesari 4640350=896000 bii110 Kb i deci,
ntr-o memorie ecran de 256 Kb, pot fi create dou pagini video.
Modul grafic utilizeaz posibilitatea de adresare a pixelilor ntr-o pagin
video i un cursor grafic invizibil. Cursorul grafic are coordonatele ultimului pixel
adresat n pagina video selectat i poate fi deplasat n orice punct al acestui spaiu.
Se menin, de asemenea, facilitile de interogare asupra poziiei cursorului i asupra
culorii pixelului curent.
Ca i la modul text, la definirea unui pixel exist posibilitatea realizrii
operaiei SAU EXCLUSIV ntre biii de culoare ai unui pixel dintr-o pagin i
valorile noi ale acestora. n acest fel, pixelii pot fi scrii sau teri.
Toate aceste operaii se realizeaz ca servicii ale rutinei INT 10h. n modul
grafic, se selecteaz un anumit submod acceptat de placa grafic, submodurile
diferind prin rezoluie, numr de culori i numr de pagini de ecran pe care le
accept.
6.3 Faciliti de scriere a textelor prin unitatea CRT
n Pascal, operaiile de afiare pe monitor, n modul text, au fost
implementate n dou uniti de program: SYSTEM i CRT. Unitul SYSTEM
definete operaia de afiare pe monitor n mod standard, adic cu atribute de scriere
implicite i ncepnd din poziia curent a cursorului. Unitul CRT (anexa 3) definete
variabile, funcii i proceduri prin care programatorul poate defini i controla
contextul de scriere (ferestre, culori, poziie de scriere etc.)
Alegerea modului text. Programatorul are posibilitatea de a alege un
anumit mod de scriere, caracterizat, n principal, prin rezoluia de afiare i tipul de
monitor: monocrom sau color. Sunt acceptate modurile prezentate n anexa 3. Pentru
alegerea modului se apeleaz procedura:
TextMode (Mode);
n care parametrul Mode, de tip Word, definete modul dorit, prin numrul asociat.
Procedura salveaz vechiul mod n variabila predefinit LastMode, de unde, prin
aceeai procedur, poate fi restaurat. Procedura seteaz culoarea de fond zero
(culoarea neagr). Dac nu se apeleaz TextMode, atunci, implicit, se consider
modul de mare rezoluie al plcii grafice.
98
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Exemplu:
6.1.
. . .
User CRT;
. . .
TextMode(C080);
. . .
TextMode(LastMode);
. . .
TextMode(BW40)
Stabilirea culorii de fond i de scriere se face prin referire la paleta
implicit. Intrrile n palet, desemnate prin constante ntregi sau constante
simbolice, sunt asociate cu diferitele culori (anexa 3). Definirea culorii fondului se
face prin apelul procedurii:
TextBackGround(culoare);
n care parametrul culoare este de tipul Byte i poate avea valorile 0-7. Procedura
trateaz biii 4-6 ai unei variabile predefinite TextAtrr de tip Byte, prin care se
modific corespunztor octetul de atribute din memoria video.
Culoarea de scriere se definete prin apelul procedurii:
TextColor (culoare);
n care parametrul culoare poate s aib o valoare ntre 0 i 15 (anexa 2), eventual
mrit cu 128. Procedura modific biii 0-3 i 7 ai variabilei TextAtrr, scriind n
bitul 7, pentru definirea clipirii, 1 sau 0, dup cum a fost adunat sau nu constanta
128 (constanta simbolic corespunztoare este Blink).
Exemplu:
6.2.
. . .
TextColor (Red+128);
. . .
TextColor(Green+Blink);
. . .
Culoare:=6
. . .
TextColor(Culoare);
Programatorul poate controla intensitatea culorii, prin modificarea bitului 3
din variabila TextAtrr (ters de ctre TextColor) prin procedurile fr parametri:
HighVideo - intensitate mrit (bitul 3 are valoare 1);
LowVideo - intensitate mic (bitul 3 are valoare 0);
NormVideo - intensitate implicit.
Execuia procedurilor pentru stabilirea culorii de fond i de scriere afecteaz
numai fereastra curent. Atributele rmn valabile pn la o nou definire sau pn la
terminarea execuiei programului.
Definirea unei ferestre de scriere. Scrierea textului pe ecran se poate
realiza ntr-o anumit zon a acestuia, denumit fereastr curent de scriere (text
99
Reprezentarea vizual a datelor
window). O fereastr se definete ca un dreptunghi, prin coordonatele colurilor
stnga-sus, dreapta-jos. Ecranul ntreg este o fereastr de coordonate (1, 1, 80, 25)
sau (1, 1, 40, 25) etc., depinznd de modul text. Declararea ferestrei se face prin
procedura:
Window(x1, y1, x2, y2);
n care parametrii (de tipul Byte) definesc, n ordine, cele dou coluri: (x1, y1) -
colul stnga-sus, (x2, y2) - colul dreapta-jos (n exprimare matriceal, abscisele
x1,x2 reprezint numerele coloanelor, iar ordonatele y1, y2 sunt numerele de linii).
Exemplu:
6.3. Window (10, 5, 70, 20); definete o fereastr care se ntinde ntre liniile
5-20 i coloanele 10-70.
Unitatea CRT definete variabilele WindMin, WindMax, de tipul Word,
care conin coordonatele colurilor ferestrei curente. Octetul cel mai semnificativ
conine numrul liniei (y), iar cel mai puin semnificativ conine numrul coloanei
(x). Coordonatele ferestrei curente pot fi scrise ca:
(Lo(WindMin), Hi(WindMin)) - colul stnga-sus
(Lo(WindMax), Hi(WindMax)) - colul dreapta-jos
Dac nu se apeleaz procedura Window, fereastra implicit este ntregul
ecran, variabilele WindMin i WindMax fiind iniializate corespunztor modului
text selectat sau implicit. Fereastra selectat rmne activ pn la un nou apel al
procedurii Window, care poate defini o nou fereastr curent, eventual una utilizat
anterior.
Poziionarea cursorului. n fereastra curent, programatorul poate s
gestioneze poziia cursorului dup necesitile programului, impunnd locul pe ecran
ncepnd cu care se va realiza scrierea urmtorului text. Poziia curent a cursorului
poate fi aflat prin apelul funciilor, fr parametri, cu rezultat de tipul Byte:
WhereX (pentru abscis) i WhereY (pentru ordonat). Mutarea cursorului ntr-o
anumit poziie a fereastrei curente poate fi comandat prin apelul procedurii:
GotoXY(X, Y);
Exemplu:
6.4.
. . .
Window(20, 3, 100, 15); TextBackGround(Red); TextColor(Blue);
ClrScr; {sterge fereastra}
Writeln (Text 1); {Se scrie pe linia 1, coloana 1 a
ferestrei (coordonatele absolute: linia 3, coloana 20)}
GotoXY(5, 6); Write (Text 2);
{Se scrie pe linia 6, coloana 5 a ferestrei (coordonatele
absolute: linia 9, coloana 25)}
X:=WhereX;
Y:=WhereY;
Write;
Writeln (X=, X, Y=, Y); {Se scrie X=11, Y=6}
Dac programatorul nu gestioneaz poziia cursorului, atunci acesta se
deplaseaz, implicit, de sus n jos i de la stnga la dreapta, pe msur ce se scrie
100
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
textul n fereastr. Cnd cursorul este la sfritul ultimului rnd al ferestrei, se
produce defilarea textului n fereastra curent.
tergerea i inserarea n fereastra curent se pot realiza utiliznd
urmtoarele proceduri fr parametri:
ClrScr - terge ferestra curent i poziioneaz cursorul pe prima linie i
coloan a acesteia;
ClrEol - terge linia curent, de la cursor pn la sfritul ei, fr a muta
cursorul;
DelLine - terge rndul pe care se afl cursorul i mut, n sus cu un rnd,
textul de sub linia tears; nu este afectat poziia cursorului;
InsLine - deplaseaz n jos, cu un rnd, textul, ncepnd cu cel pe care este
cursorul i insereaz o linie goal, n linia din fereastr pe care este cursorul. Se
pierde ultimul rnd din fereastr.
Citirea caracterelor fr ecou. Prin intermediul a dou funcii, fr
parametri, programatorul poate citi fr ecou caracterul produs de ultima tast
apsat sau poate verifica dac a fost apsat o tast. Se utilizeaz funciile:
ReadKey - funcie de tipul CHAR care rentoarce caracterul existent n
buffer-ul tastaturii; dac nu exist un astfel de caracter, atunci ateapt pn la
tastarea unui caracter;
KeyPressed - funcie de tipul BOOLEAN care rentoarce valoarea True dac
a fost apsat o tast i False altminteri.
Funcia ReadKey ntoarce codul caracterului rezultat prin apsarea tastei,
dac aceasta produce un singur cod sau primul cod (valoare zero binar), dac tasta
apsat produce dou coduri. n acest ultim caz, se obine caracterul complet dac se
fac dou apeluri succesive ale funciei Readkey.
n general, tastele F1-F12, tastele de deplasare cursor (sgei), Home, Ins,
Del, PgUp, PgDwn cnd sunt apsate singure sau simultan cu CTRL, Shift ori
ALT, produc dou coduri. Pot, de asemenea, produce dou coduri tastele de litere
sau cifre, atunci cnd sunt apsate simultan cu tasta ALT.
n legtur cu funcia KeyPressed, trebuie menionat c rspunsul este
furnizat potrivit strii buffer-ului tastaturii de la acel moment (funcia nu ateapt
apsarea pe o tast). Dac KeyPressed este TRUE, atunci ReadKey returneaz
imediat caracterul.
101
Reprezentarea vizual a datelor
Pornirea i oprirea difuzorului. Programul poate provoca producerea
sunetelor de o anumit frecven pe o durat controlabil. n acest scop sunt
prevzute procedurile:
Sound(Hz) - pornirea difuzorului care emite un sunet continuu de frecven
dat de parametrul Hz, n Hertz;
NoSound - oprirea difuzorului;
Delay(Ms) - realizarea unei ntrzieri de Ms milisecunde pn la execuia
urmtoarei instruciuni.
Controlnd corespunztor frecvena Hz i intervalul de emisie Ms al
difuzorului se poate realiza o anumit linie melodic.
Pentru cei care doresc s se iniieze n tehnica compunerii muzicii cu ajutorul
calculatorului, sunt prezentate n continuare cteva elemente de baz.
n tabelul 6.1 sunt prezentate frecvenele notelor, n patru octave consecutive
(n total sunt 7 octave numerotate 06). Se poate constata c frecvena unei note
ntr-o octav se poate estima prin dublarea frecvenei acesteia din octava imediat
inferioar. Similar, se poate deduce frecvena notelor dintr-o octav inferioar prin
njumtirea frecvenelor notelor din octava imediat superioar.
Tonul unei note poate fi alterat (mrit sau micorat) cu o jumtate de ton n
octava respectiv (note cu diez i bemol). Aceasta nseamn c frecvena unei note
oarecare i cu diez se calculeaz cu relaia: nota
i
:=0.5(nota
i+1
+nota
i
); nota
i
=1,2,4,5,6.
Notele pot avea diferite durate: ntreag, doime, ptrime, optime etc. Dac se
stabilete durata notei ntregi ca durat iniial, atunci duratele celorlalte note se
calculeaz ca o fracie corespunztoare din aceasta (1/2, 1/4, 1/8 etc.).
Tabelul 6.1 - Frecvenele notelor muzicale n diverse octave
Octava 1 Octava 2 Octava 3
(mijlocie)
Octava 4
Nota Frecvena Nota Frecvena Nota Frecvena Nota Frecvena
Do 130.81 Do 261.63 Do 523.25 Do 1046.5
Re 146.83 Re 293.66 Re 587.33 Re 1174.7
Mi 164.81 Mi 329.63 Mi 659.26 Mi 1318.5
Fa 174.61 Fa 349.23 Fa 698.46 Fa 1396.9
Sol 186.00 Sol 392.00 Sol 783.99 Sol 1568.0
La 220.00 La 440.00 La 880.00 La 1760.0
Si 246.94 Si 493.88 Si 987.77 Si 1976.5
102
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Se tie c durata unitar este determinat de tempo-ul n care trebuie
cntate notele. n tabelul 6.2, sunt redate cteva tempo-uri, exprimate n
ptrimi/minut. Din tabel rezult duratele diferitelor note, n minute, pentru un tempo,
T, dat:
D
1
=4/T; D
8
=1/2T;
D
2
=2/T; D
16
=1/4T;
D
4
=1/T; D
32
=1/8T etc.
Durata unei note poate fi modificat prin punct. Astfel, durata real este 3/2
din durata notei fr punct. Pentru a obine stilul legato i stacatto, durata pe care se
cnt o not se modific astfel:
normal: 7/8 din durat; 1/8 pauz;
legato: 1/1 din durat;
stacatto: 3/4 din durat; 1/4 pauz.
Trebuie observat c, datorit dependenei duratei notelor de ceasul intern,
pentru unele tempo-uri nu se obin rezultate satisfctoare. De aceea, este necesar ca
durata notelor i tempo-urile s se stabileasc prin experimentri.
Tabelul 6.2 Duratele notelor n diverse tempo-uri
Tempo Denumire Ptrimi/minut
foarte ncet
Largo
Larghetto
Adagio
40-60
60-66
66-76
ncet Andante 76-108
mediu Moderato 108-120
repede Alegro
Presto
120-168
168-208
6.4 Implementarea modului grafic n Pascal
Subprogramele care implementeaz modul grafic se bazeaz pe
caracteristicile plcilor existente i se mpart n: primitive grafice i subprograme
ajuttoare. Ele sunt declarate n unitatea Graph i sunt memorate n urmtoarele
fiiere:
GRAPH.TPU - care conine codul obiect al subprogramelor definite n
unitatea Graph;
*.BGI - cte un fiier pentru fiecare tip de plac grafic, care
conine codul obiect al rutinelor de tratare a
ntreruperii pentru operaii grafice (driver de plac), ca
soft specific pentru comanda interfeelor grafice;
103
Reprezentarea vizual a datelor
*.CHR - fiiere care conin seturi de caractere suplimentare cu
diferite stiluri (fonturi).
Unitatea Graph definete, de asemenea, o serie de constante, variabile i
structuri de date care s-i uureze programatorului apelul acestor subprograme
(anexa 4). Pentru utilizarea subprogramelor de grafic, programatorul trebuie s
procedeze astfel:
a) S declare faptul c utilizeaz unitatea: uses Graph;
b) S selecteze modul (submodul) grafic dorit, prin utilizarea procedurii:
InitGraph (GraphDriver, GraphMode, PathToDriver)
Primii doi parametri sunt variabile de tipul INTEGER, iar ultimul este o
constant sau variabil de tipul STRING. Parametrii au urmtoarea semnificaie:
GraphDriver precizeaz tipul plcii grafice considerate. Variabila poate lua una
din valorile ntregi 0-10 sau constantele predefinite echivalente. Constanta Detect
(valoare 0) cere subprogramului s identifice tipul de plac a calculatorului.
GraphMode selecteaz unul din submodurile acceptate de placa grafic. Valoarea
parametrului nu este luat n considerare dac GraphDriver a fost Detect, caz n
care se selecteaz automat submodul cu cea mai mare rezoluie.
PathToDriver definete calea spre directorul de reziden a driver-ului de plac
(fiier de tip BGI), dac acesta nu este n director curent. irul vid definete o
cutare n directorul curent.
Exemple:
6.5.
GraphDriver:=EGA;
GraphMode:=EGALo;
InitGraph ('GraphDriver, GraphMode,');
6.6.
GraphDriver:=Detect;
GraphMode:=0;
InitGraph (GraphDriver, GraphMode,'C:\TP\BIN');
c) S verifice dac iniializarea modului grafic dorit, din pasul anterior, s-a desfurat
cu succes. n acest sens, se utilizeaz funcia special GraphResult, de tipul
INTEGER i fr parametri, care returneaz valoarea zero (GrOK) pentru succes.
Funcia poate fi utilizat dup execuia oricrei operaii grafice.
d) S apeleze subrutinele grafice necesare, dac iniializarea s-a derulat cu succes.
e) S revin n modul text, la terminarea operaiilor grafice, prin utilizarea procedurii
fr parametri, CloseGraph. Iniializarea sistemului grafic aloc memoria dinamic
necesar, iar nchiderea o elibereaz.
104
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
6.4.1 Fereastr i vizor
n grafica computerizat se consider c nregistrarea pe ecran este o
transpunere, micorat sau mrit, a desenelor din spaiul real (spaiul utilizator).
Partea imaginii reale care se deseneaz este cuprins ntr-un dreptunghi, numit
fereastr (window), cu laturile paralele cu axele de coordonate ale acestui spaiu.
Fereastra se proiecteaz pe spaiul ecran ntr-un dreptunghi, asemenea cu fereastra,
denumit vizor (viewport). Astfel, pe ecran, pot coexista mai multe imagini
independente. La limit, vizorul poate fi ntregul ecran.
Relaia ntre fereastr i vizor este evideniat n figura 6.6. De aici se deduce
o transformare de coordonate, care proiecteaz orice punct (x
r
,y
r
) din spaiul real, n
punctul (x
e
,y
e
) al spaiului ecran. Dac fereastra i vizorul se definesc prin
coordonatele colurilor stnga-sus i dreapta-jos, iar centrele celor dou dreptunghiuri
sunt notate ) y , x (
r
0
r
0
, ) y , x (
e
0
e
0
, din asemnarea imaginii din cele dou spaii se pot
scrie relaiile:
(1)
w w
v v
y y
y y
w w
v v
x x
x x
4 3
3 4
r
0
r
0
e e
1 2
1 2
0
r r
0
e e
Fig. 6.6 Relaia fereastr-vizor
(x
r
,y
r
)
(x
e
,y
e
)
(w
1
,w
3
)
(w
2
,w
4
)
(v
2
,v
4
)
(v
1
,v
3
)
(x y
r r
0 0
, )
(x y
e e
0 0
, )
x
x
y
y
fereastr
vizor
105
Reprezentarea vizual a datelor
Din (1) se expliciteaz coordonatele (x
e
,y
e
) i se obin relaiile:
(2)
y
w w
v v
y
w w
v v
y y
x
w w
v v
x
w w
v v
x x
0
r
4 3
3 4
r
4 3
3 4 0
e e
0
r
4 2
1 2
r
1 2
1 2 0
e e
+ =
din care, prin nlocuirea coordonatelor centrelor ferestrelor i vizorului, n funcie de
coordonatele colurilor acestora, se obin relaiile:
(3)
2
w w
w w
v v
y
w w
v v
2
v v
y
2
w w
w w
v v
x
w w
v v
2
v v
x
4 3
4 3
3 4
r
4 3
3 4 4 3
e
2 1
1 2
1 2
r
1 2
1 2 2 1
e
+
=
+
+
+
=
Realiznd calculul din (3) se obin relaiile:
(4)
w w
w v w v
y
w w
v v
y
w w
w v w v
x
w w
v v
x
4 3
4 3 3 4
r
4 3
3 4
e
1 2
1 2 2 1
r
1 2
1 2
e
=
Notnd:
(5)
w w
w v w v
b >
w w
w v w v
b
w w
v v
a >
w w
v v
a
4 3
4 3 3 4
2
1 2
1 2 2 1
1
4 3
3 4
2
1 2
1 2
1
=
se obin relaiile de transformare:
x = Round(a x + b )
y = Round(a y + b )
e 1 r 1
e 2 r 2
(6)
Relaiile (6) dau coordonatele absolute, n spaiul ecran, pentru orice punct
(x
r
,y
r
). Este, de multe ori, preferabil s se exprime punctele n spaiul ecran relativ la
vizor, adic ntr-un subspaiu cu originea n colul stnga-sus al acestuia. Dac se
noteaz (dx
e
,dy
e
) coordonatele absolute (x
e
, y
e
), se obin relaiile:
(7)
dy v y
dx v x
e 3 e
e 1 e
+ =
+ =
106
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Utiliznd relaiile (4), din (6) se obin relaiile:
) 8 (
) w y (
w w
v v
dy
) w x (
w w
v v
dx
3 r
4 3
3 4
e
1 r
1 2
1 2
e
=
Dac se noteaz:
k
v v
w w
k
v v
w w
1
2 1
2 1
2
4 3
3 4
=
atunci se pot considera coordonatele relative sub forma:
) 9 (
)) (
)) (
=
=
3 r 2 e
1 r 1 e
w y round(k dy
w x round(k dx
Utilizarea ferestrei i/sau vizorului n tehnica realizrii imaginilor grafice
ofer, n plus, posibilitatea de verificare a apartenenei punctelor la desenul curent.
Se pot implementa msuri de eliminare a punctelor strine (tehnica clipping-ului sau
tierii), pentru a asigura protecia imaginilor vecine mpotriva distrugerilor
accidentale, desenndu-se numai imaginea din fereastr.
n sistemul grafic Pascal, ideile tehnicii fereastr-vizor sunt implementate
parial, aa dup cum rezult din cele ce urmeaz.
Exist posibilitatea definirii vizorului ca spaiu curent pentru un anumit
desen (vizor curent). Declararea lui se face prin apelul procedurii SetViewport, n
forma:
SetViewport(v1,v3,v2,v4,Clip);
n care (v1,v3) i (v2,v4) sunt constante sau variabile de tipul INTEGER care dau
coordonatele colurilor vizorului, iar Clip este un parametru boolean care activeaz
sau inhib aplicarea clipping-ului.
Unitatea Graph definete funciile de tipul INTEGER fr parametri:
GetMaxX i GetMaxY care returneaz dimensiunile maxime ale spaiului ecran
pentru placa grafic cu care este echipat calculatorul. Pentru a crea independen
programului fa de calculator, se recomand utilizarea lor n definirea vizorului. De
asemenea, unitatea Graph definete constantele simbolice ClipOn (True) i ClipOff
(False) care pot fi folosite pentru parametrul Clip.
107
Reprezentarea vizual a datelor
Exemplu:
6.7.
SetViewport(10,25,GetMaxX-150,GetMaxY-50,ClipOn);
Vizorul implicit, stabilit la iniializarea modului grafic, este ntregul ecran, echivalent
cu un apel de forma:
SetViewport (0,0,GetMaxX,GetMaxY,ClipOn) ;
Vizorul curent poate fi ters, la culoarea de font curent, prin apelul
procedurii ClearViewport, care este fr parametri. Pentru a fi pus n eviden fa
de zonele vecine, vizorul poate fi ters cu o culoare de fond adecvat, stabilit n
prealabil (vezi 6.4.2.) i poate fi ncadrat ntr-un dreptunghi.
Exemplu:
6.8. Pentru un ecran monocrom (dar nu numai) se poate utiliza o secven de
forma:
Rectangle(9,24,GetMaxX-149,GetMaxY-49);
SetViewport(10,25,GetMaxX-150,GetMaxY-50,ClipOn)
ClearViewport;
n care procedura Rectangle deseneaz un dreptunghi cu liniile n culoarea curent de
desen (alb), iar SetViewport l terge, la culoarea fondului.
Procedura ClearDevice terge ntregul ecran i determin revenirea la
parametrii de lucru implicii, stabilii la iniializare.
Declararea vizorului determin rutinele sistemului grafic s lucreze n
coordonate relative. Aceasta nseamn c orice procedur sau funcie care primete
ca parametru de intrare coordonatele (dx
e
,dy
e
) nelege s le utilizeze pentru a
calcula coordonatele absolute (x
e
,y
e
), prin relaii de forma (6), iar cele care au aceste
coordonate ca parametru de ieire le determin prin relaiile:
dx x v
dy y v
e e 1
e e 3
=
=
Sistemul nu prevede posibilitatea declarrii ferestrelor n spaiul utilizator
i, de aici, lipsa facilitii de exprimare a coordonatelor, pentru rutinele de grafic,
direct n acest spaiu i transformarea lor automat n coordonatele ecran.
Programatorul trebuie s-i construiasc proceduri proprii care s-i transforme
coordonatele din spaiul utilizator n spaiul ecran, relative la vizorul curent. Dei pot
fi aplicate procedee diverse, dup natura desenului, pentru generalitate i
uniformitate n realizarea programelor de grafic se aplic tehnica fereastr-vizor
descris anterior.
108
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
6.4.2 Grafic n culori
Sistemul grafic Pascal implementeaz culorile pe principiul paletei. Sistemul
posed o serie de proceduri, funcii i date prin care se pot accesa facilitile de
culoare ale plcii grafice i modului grafic selectat.
Determinarea paletei. Deoarece caracteristicile de culoare depind de placa
grafic i modul grafic selectat, se poate obine un program relativ portabil, dac
acesta se scrie astfel nct s-i determine singur facilitile pe care le poate utiliza.
Pentru aceasta pot fi utilizate rutinele:
- GetMaxColor - funcie fr parametri care ntoarce o valoare de tipul WORD,
reprezentnd indexul maxim al paletei;
- GetPaletteSize - funcie fr parametri care ntoarce o valoare de tipul
INTEGER reprezentnd numrul maxim de culori care pot fi
utilizate simultan;
- GetDefaultPalette(paleta) - procedur care returneaz, n parametrul paleta,
numrul i culorile paletei implicate;
- GetPalette(paleta) - procedur care returneaz aceleai date ca procedura
anterioar, dar pentru paleta curent.
Parametrul paleta trebuie s fie declarat ca o variabil de tipul PaletteType, definit n
unitatea Graph ca un articol cu cmpurile: Size (Byte) i Colors (Shortint).
Modificarea paletei curente. Programatorul poate modifica una sau toate
intrrile paletei curente, dar pantru aceasta trebuie s cunoasc codurile de culoare.
Procedurile care se utilizeaz sunt:
- SetPalette(Index,Color) - care permite modificarea intrrii date de parametrul
Index (WORD), cu o culoare de cod Color (INTEGER). Att
pentru Index, ct i pentru Color pot fi utilizate constantele
simbolice predefinite n unitatea Graph.
- SetAllPalette(Palette) - nlocuiete paleta curent cu cea dat de parametrul
Palette. Parametrul este de tipul PaletteType i trebuie s fi
fost ncrcat corect cu codurile de culori.
n ambele situaii, procedurile modific automat culorilor desenului de pe
ecran, n concordan cu noua configuraie a paletei curente. Procedurile pot fi
utilizate i cu scopul de a produce efecte de culoare deosebite sau pentru a releva
treptat, prin modificri repetate, un desen ascuns.
Determinarea i modificarea culorilor de fond i de desen. Funciile i
procedurile din aceast categorie sunt cel mai frecvent utilizate deoarece definesc
fondul i culoarea de desen pe baza paletei curente.
-SetBkColor(Color) - procedur pentru selecia culorii de fond. Color este
parametrul de tip WORD care precizeaz indexul culorii
dorite. Implicit, se utilizeaz indexul zero care corespunde, n
general, culorii negre;
- GetBkColor - funcie fr parametri, de tipul WORD, care returneaz inde-
xul culorii curente pentru fond;
109
Reprezentarea vizual a datelor
- SetColor(Color) - procedur pentru selecia culorii de desen. Color are
aceeai semnificaie ca la procedura anterioar. Implicit, se
utilizeaz ultimul Index care, n general, corespunde culorii
alb;
- GetColor - funcie similar cu GetBkColor pentru a obine culoarea curent
de desen.
Modificarea culorii de fond atrage dup sine modificarea culorii pe ecran.
Culorile selectate, denumite culori curente, rmn active pn la o nou selecie sau
pn la ieirea din program.
Exemplu:
6.9. Presupunnd o plac EGA, secvena care urmeaz stabilete un vizor cu
fond albastru n care deseneaz un dreptunghi umplut. Dup 2000 ms se refac
culorile anterioare.
Uses Graph,Crt;
VAR
ColorBk,ColorFg:Word;
..
ColorBk:=GetBkColor;
ColorFg:=GetColor;
SetViewport(20,50,250,150,ClipOn);
SetColor(EGARed);
SetBkColor(EGABlue);
ClearViewport;
Bar(20,10,60,50);
Delay(2000);
SetBkColor(ColorBk);
SetColor(ColorFg);
. . . . . . . . . . . . . .
6.4.3 Desen prin puncte i vectori
Desenul prin puncte este modul natural de realizare a imaginii video.
Biblioteca de subprograme grafice Pascal conine pentru acest mod de lucru
procedura PutPixel(x,y,Color) i funcia de tipul WORD GetPixel(x, y).
Procedura PutPixel stabilete culoarea Color de aprindere a pixelului de
coordonate (x,y) din vizorul curent, iar funcia GetPixel ntoarce indexul culorii cu
care este aprins un astfel de pixel. Pe baza subprogramelor, se pot construi desene
complexe, dar cu dificultile pe care le implic gestionarea mulimii de pixeli care
compun imaginea video. Pentru a facilita realizarea desenelor, sistemul grafic
PASCAL implementeaz i alte moduri de lucru, cum este desenul prin vectori. n
acest mod, pot fi trasate segmente de dreapt, independente sau legate (linii frnte),
utiliznd pentru forma liniilor stilurile i culorile curente (setate). Culoarea de desen
i culoarea fondului sunt curente, setate prin SetBkColor i SetColor. Stilul de linie
este cel definit de procedura SetLineStyle,care se apeleaz astfel:
SetLineStyle(TipStil,Model,Grosime);
110
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Stilul definit rmne valabil pn la o nou setare. Stilul implicit este linia
continu normal. Parametrii, de tipul WORD, constante sau variabile, definesc
atributele liniei (stilul liniei):
- TipStil - definete tipul de linie din punctul de vedere al continuitii.
Parametrul poate avea valorile 0-4 sau constanta simbolic
corespunztoare;
- Grosime - precizeaz grosimea, n numr de pixeli i poate avea valorile:
1 (linie normal - NormWidth) i 2 (linie groas - ThickWidth);
- Model - definete un stil de utilizator printr-un fragment de 16 pixeli. Un pixel
este aprins, dac bitul corespunztor, din numrul dat de acest
parametru, este unu. De exemplu, dac Model=$F053 (n binar 1111
0000 0101 0011) atunci se definete modelul xxxx xx xx, n care
este pixel aprins.
Desenarea unui segment de dreapt se face prin procedura
Line(x1,y1,x2,y2). Prin parametrii x1, y1, x2, y2, de tip INTEGER, se precizeaz
coordonatele capetelor segmentului de dreapt. Coordonatele sunt relative la vizorul
curent i se pot exprima ca variabile sau constante. Se desemneaz numai poriunea
de segment care se afl n interiorul vizorului.
Exemplu:
6.10. Secvena care urmeaz:
SetViewport(20,20,150,100,ClipOn);
Line(10,10,150,150);
deseneaz un segment cu originea absolut n (30,30) i extremitatea final n
(170,120) din care se vede numai poriunea de coordonate absolute (30,30),
(138,100) - figura 6.7.
Desenarea segmentelor de dreapt cu procedura Line este incomod, cnd
trebuie desenate linii frnte, datorit redundanei de informaii, avnd n vedere
coincidena punctului final al unui segment cu originea segmentului urmtor.
Desenarea liniilor frnte este facilitat de introducerea n sistemul grafic a
noiunii de punct curent i de existena unor rutine care deseneaz linii relativ la
acesta. Punctul curent, definit prin coordonatele sale n spaiul ecran, este neles de
rutinele sistemului ca origine a urmtorului segment de dreapt posibil de desenat.
Sistemul prevede rutine pentru aflarea i modificarea poziiei punctului curent,
precum i reguli de comportare a rutinelor de trasare de linii, cu privire la
actualizarea acestuia. Locul punctului curent poate fi aflat cu ajutorul funciilor, fr
parametri, GetX i GetY, care returneaz abscisa i ordonata absolut, ca numere
ntregi.
111
Reprezentarea vizual a datelor
(20,20)
(30,30)
(138,100
(170,120)
(150,100)
(0,0)
Fig. 6.7. Desenarea liniilor relativ la vizor
x
y
Punctul curent poate fi mutat ntr-un alt loc din spaiul fizic, prin procedurile
MoveTo i MoveRel care se apeleaz sub forma: MoveTo(x,y); MoveRel(x,y).
Procedura MoveTo consider valorile (x,y) drept coordonate relative la vizorul curent
i calculeaz coordonatele absolute (x
e
,y
e
) ale punctului curent prin relaiile: x
e
=v
1
+x;
y
e
=v
3
+y, unde (v1,v3) sunt coordonatele originii vizorului. Procedura MoveRel
deplaseaz punctul curent relativ la poziia sa anterioar, adic x
e
=GetX+x;
y
e
=GetY+y, n care x,y apar ca deplasri. La intrarea n regim grafic, la definirea
i/sau tergerea vizoarelor, precum i la schimbarea modului grafic, punctul grafic
curent este nedefinit. Este sarcina programului s iniializeze punctul curent prin
procedura MoveTo. Toate procedurile de desenare de linii i scriere de text
deplaseaz poziia punctului curent n ultimul punct utilizat.
Desenarea liniilor care i au originea n punctul curent se realizeaz cu
ajutorul procedurilor LineTo(x,y); LineRel(x,y). Pentru LineTo, coordonatele
extremitii liniei sunt relative la vizorul curent i deci x
e
=v
1
+x, y
e
=v
3
+y, unde (x
e
,y
e
)
sunt coordonatele absolute ale extremitii liniei relativ la punctul curent x
e
=GetX+x;
y
e
=GetY+y. Dup trasare, punctul curent este deplasat n punctul x
c
=x
e
, y
c
=y
e
. Dac
la trasare a fost necesar operaia de clipping, punctul final al segmentului vizibil este
recalculat ca
(x
e
~
e
~
, ) y
, ns punctul curent este mutat tot n (x
e
,y
e
). Se evit astfel
deformarea desenelor.
Exemplu:
6.11. Dac se consider linia frnt P
1
, P
2
, P
3
, P
4
din figura 6.8, atunci
secvenele de instruciuni de trasare, avnd n vedere coordonate relative la vizor i
relative la punctul curent, pot fi scrise astfel:
Relativ la vizor Relativ la punctul curent
MoveTo(50,60) MoveTo(50,60)
LineTo(70,40) LineRel(20,-20)
LineTo(85,45) LineRel(15,5)
LineTo(140,30) LineRel(25,-15)
112
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
(0,0)
(85,45)
[15,5]
x
y
(20,10)
(50,60)
(70,40)
[20,-20]
(110,30)
[25,-15]
Fig. 6.8. Desenarea segmentelor relativ la vizor i la punctul curent
n plus, trebuie menionat faptul c desenarea unei linii simple sau frnte
poate fi fcut astfel nct s distrug sau s conserve, ntr-un anumit sens, culorile
pixelilor care se suprapun. Comportamentul pixelilor depinde de modul de scriere a
noii imagini n raport cu imaginea existent pe ecran (setarea modului Write);
6.4.4 Raportul de aspect
n realizarea desenelor prin segmente apare un fenomen de deformare care
poate s fie deranjant (un ptrat apare ca dreptunghi, un cerc ca o elips etc).
Fenomenul se datoreaz formei pixelilor care, cu excepia unor plci de foarte mare
rezoluie, nu sunt de form ptratic, ci dreptunghiular. Aceasta face s se aplice,
implicit, uniti diferite de msur pe cele dou axe. Deformarea poate fi atenuat sau
chiar eliminat, dac n realizarea desenului se aplic un anumit raport ntre
lungimile segmentelor de pe orizontal i ale celor de pe vertical.
Dac se noteaz cu Lpx lungimea unui pixel, n sensul axei ox i cu Ipy
nlimea sa, n sensul axei oy, atunci raportul Ra=Ipy/Lpx este denumit raport de
aspect. El poate fi utilizat pentru a determina, n mod adecvat, lungimile segmentelor
(n pixeli) care se deseneaz. Pentru a obine dimensiunile pixelului plcii grafice se
utilizeaz procedura:
GetAspectRatio(Lpx, Ipy);
n care cei doi parametri sunt variabile de tipul WORD.
Dac se noteaz cu AB un segment vertical de lungime n pixeli i cu CD un
segment orizontal, de lungime m pixeli, atunci, pentru ca raportul AB/CD s fie k,
trebuie ca m, dac se cunoate n (respectiv n, dac se cunoate m), s se determine
cu relaiile:
k * Round(m n
n * Round(Ra = m
= ) Ra
) k
113
Reprezentarea vizual a datelor
Exemplu:
6.12. Desenarea unui ptrat, cu latura orizontal CD de m=50 pixeli i vrful
stnga sus n (30,60), pe un vizor egal cu ntregul ecran. Deoarece k=1, se poate
utiliza secvena:
GetAspectRatio(Lpx,Ipy);
Ra:=Ipy/Lpx;
n=Round(50/Ra);
MoveTo(30,60);
LineTo(80,60);
LineTo(80,60+n);
LineTo(30,60+n);
LineTo(30,60);
Exist, de asemenea, rutina SetAspectRatio care permite definirea software a
raportului de aspect pentru a fi utilizat de rutinele sistemului grafic. Programatorul
care utilizeaz rutinele sistemului pentru desenare de figuri poate s reduc
fenomenul de deformare, modificnd repetat, eventual interactiv, raportul de aspect.
Apelul acestei proceduri este similar procedurii GetAspectRatio.
6.4.5 Scrierea textelor n modul grafic
n mod uzual, imaginile de pe ecran sunt nsoite de texte explicative. Avnd
n vedere c, de multe ori, lucrul n modul text nu satisface cerinele de mrime,
form, culoare i direcie de scriere, n unit-ul Graph au fost introduse primitive
specifice prelucrrii textelor. Unitatea conine dou grupe de rutine: pentru definirea
atributelor textelor i pentru scrierea propriu-zis.
Rutinele de declarare a atributelor textelor trebuie apelate ori de cte ori
este necesar s se defineasc alte caracteristici de scriere dect cele curente.
Atributele astfel definite (setate) rmn active pn la o nou setare sau pn la
sfritul programului. Rutinele de declarare sunt proiectate pentru a putea trata
urmtoarele atribute de scriere:
a) Stilul de caractere, adic forma caracterelor imprimabile. Sistemul
recunoate cinci stiluri (fonturi), codificate 0-4, crora li s-au asociat constante
simbolice;
b) Culoarea: caracterele se afieaz pe fondul i culoarea de desen curent;
c) Mrimea se refer la limea i nlimea caracterelor, caracteristici care se
definesc pentru toate fonturile, cu excepia stilului DefaultFont, la care mrimea nu
poate fi modificat. Fonturile cu mrime de caracter modificabil definesc
caracterele prin vectori (caractere vectoriale). Mrimea se poate referi la spaiul
dreptunghiular pentru un caracter, n sensul micorrii sau creterii proporionale a
acestuia pentru ambele dimensiuni sau pentru fiecare dimensiune n parte
(dimensiuni de utilizator).
114
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
d) Direcia de scriere poate fi: orizontal sau vertical. Pentru direcia orizontal
(constanta simbolic HorizDir) scrierea se face de la stnga spre dreapta, iar pentru
direcia vertical (VertDir), de jos n sus;
e) Alinierea: precizeaz, pentru fiecare din cele dou direcii, modul de
amplasare a textului n raport cu punctul de scriere (punct de referin).
Pentru definirea atributelor se pot utiliza procedurile:
SetTextStyle (Font, Directie, Marime);
SetTextJustify (FtHorizDir, FtVertDir);
SetUserCharSize (MultX, DivX, MultY, DivY);
Parametrul de mrime, la procedura SetTextStyle, poate lua valori naturale
mai mari sau egale cu zero i precizeaz de cte ori s fie mrite, proporional,
caracterele fontului ales fa de dimensiunea normal a acestora. Pentru definirea
dimensiunilor de utilizator (independente pe cele dou direcii), valoare zero a
parametrului Marime declar intenia programatorului de a apela procedura
SetUserCharSize. La aceast procedur, se utilizeaz ideea c dimensiunea se
modific prin nmulire cu un raport. Raportul MultX/DivX va fi utilizat pentru a
modifica limea caracterelor, iar MultY/DivY pentru modificarea nlimii. Atunci
cnd raportul este unu, dimensiunea pe direcia respectiv va rmne nemodificat.
La procedura de definire a alinierii se cere s se precizeze modul de aliniere
a textului pe ambele direcii, chiar dac scrierea utilizeaz numai una din ele.
Exemple:
6.13. Se definete fontul SmallFont, cu mrire proporional, de 3 ori i cu
afiare centrat pe orizontal:
SetTextJustify(CenterText,CenterText);
SetTextStyle(SmallFont,HorizDir,3);
6.14. Se stabilete o cretere a dimensiunii caracterelor fontului
SansSerifFont numai n nlime, de 1,5 ori; scrierea se face pe direcia vertical, cu
aliniere la partea de jos:
SetTextStyle(SansSerifFont,VerDir,0);
SetUserCharSize(1,1,3,2);
SetTextJustify(LeftText,BottomText);
Dac atributele de scriere au fost deja definite, adic au devenit atribute
curente, programatorul poate utiliza funciile ntregi (de tipul WORD):
TextHeight(Text), TextWidth(Text), pentru a afla nlimea, respectiv limea, n
numr de pixeli, necesare pentru a afia ntregul text dat de parametrul Text. Pe baza
acestor informaii, se poate alege punctul de referin astfel nct scrierea textului s
fie posibil (totul s nceap n vizorul de scriere) sau acesta s fie mai bine amplasat,
pe direcia curent.
115
Reprezentarea vizual a datelor
Pentru scrierea efectiv a textelor se utilizeaz una din urmtoarele dou
proceduri:
OutText(Text);
OutTextXY(x,y,Text);
Textul de scris (parametrul Text) se poate prezenta ca o constant, variabil
sau expresie de tipul STRING. Scrierea se face n raport cu punctul de referin cu
coordonate (x,y) sau la cursor, dac nu se definete explicit un astfel de punct.
Dup scriere, cursorul se gsete pe poziia urmtoare celei utilizate pentru scrierea
ultimului caracter al textului, dac scrierea s-a fcut prin procedura OutText sau
rmne nemodificat, atunci cnd s-a utilizat procedura OutTextXY.
Dac exist definit vizor curent, cu acceptarea clipping-ului, textul este
decupat la limitele vizorului. Nu se aplic procedeul de clipping dac fontul este
DefaultFont i comportarea rutinei de scriere este nedefinit cnd survine o depire
a vizorului. n plus, trebuie menionat c primitivele de afiare in cont de setarea
modului de scriere.
Exemplu:
6.15. Se scrie orizontal textul "TURBO PASCAL", de 4 ori, cu cele patru
fonturi vectoriale. Fiecare rnd, centrat pe linia vertical a centrului ecranului, se
scrie cu o alt culoare.
Clear Device;
SetTextJustify(CenterText,CenterText);
y:=20;
For i:=1 to 4 do
Begin
SetColor (i);
SetTextStyle(i,HorizDir,2+i);
Y:=y+TextHeight('TURBO PASCAL')+8;
OutTextXY(GetMaxX Div 2,Y,'TURBO PASCAL');
End;
6.4.6 Primitive pentru figuri
Pentru a facilita realizarea imaginilor, sistemul grafic cuprinde cteva
primitive pentru desenarea unor figuri, majoritatea n plan. Unele din aceste
proceduri umplu figura desenat cu un anumit model de culoare i haur. Toate
rutinele au fost concepute s lucreze n condiiile existenei unei vizor curent, adic
n coordonate relative la vizor i s aplice clipping-ul, dac acesta a fost acceptat.
Cteva din ele in seama de modul de scriere selectat. Ca i rutinele prezentate
anterior, primitivele pentru figuri utilizeaz, pentru contur i linii, culorile i
atributele curente. Dac o primitiv umple figura, atunci ea folosete un model de
haurare i o anumit culoare. Modelul de haurare poate fi ales dintr-o mulime
predefinit sau poate fi definit de utilizator.
116
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Pentru a preciza stilul i culoarea de umplere se apeleaz procedura:
SetFillStyle(TipStil,Culoare);
n care parametrul Culoare este un index n paleta curent, iar TipStil o constant
ntre 0-12. Dac TipStil este 12 (UserFill), atunci el trebuie s fie definit ca un model
binar pe 8 byte (un vector) care este interpretat de rutinele respective ca o matrice de
8x8 bii. Matricea este traversat circular pe linii i pixelul curent este aprins, la
culoarea definit prin parametrul culoare, dac bitul din model este unu. n plus, tipul
definit rmne ca model curent.
Exemplu:
6.16.
CONST
MyPattern:Array[1..8]of Byte=($01,$01,$FF,$01,$01,$FF,$01,$01);
. . . . . . . . . .
SetFillStyle(MyPattern,3);
n figura 6.9 se prezint toate tipurile de hauri considernd numai culorile
alb i negru.
Fig. 6.9 Tipuri de hauri