2.

Arbori asociaþi expresiilor aritmetice
Rolul oricãrui compilator este de a transforma programele scrise într-un limbaj de programare oarecare într-un cod echivalent, scris în limbaj de asamblare sau în limbaj maºinã. În acest capitol ne punem problema translatãrii expresiilor aritmetice dintr-un limbaj de programare cum ar fi de exemplu limbajul Pascal în limbaj de asamblare. Pentru aceasta ne vom propune un model simplu de maºinã, care lucreazã cu regiºtri notaþi R1, R2,... ºi executã urmãtoarele douã operaþii: PUNE Rx variabilã/constantã: încarcã variabila sau constanta în registrul Rx; OPz Rx Ry: efectueazã operaþia OPz asupra conþinuturilor regiºtrilor de memorie Rx respectiv Ry, rezultatul fiind depus în registrul Rx. De exemplu, pentru expresia aritmeticã (a+b)*(c+2) se poate asocia codul: PUNE R1 a PUNE R2 b OP+ R1 R2 PUNE R2 c PUNE R3 2 OP+ R2 R3 OP* R1 R2 Primul pas în rezolvarea acestei probleme este de asocia expresiei aritmetice un arbore binar. Definiþie Numim expresie aritmeticã o construcþie definitã prin urmãtoarele diagrame de sintaxã:

56

Aceste restricþii nu sunt semnificative. care conþine drept informaþie operandul respectiv. -dacã expresia este de forma E = E 1 op E2. * Programul Expresie-Aritmetica de la sfârºitul capitolului construieºte arborele binar asociat unei expresii corecte din punct de vedere sintactic. Oricãrei expresii aritmetice i se poate asocia un arbore binar strict. arborele binar asociat expresiei E = (a+b)*(a*c+b*d) este: Fig. arborele binar asociat este constituit dintr-un singur nod. De exemplu. 1. iar subarborele drept arborele binar asociat expresiei E2. iar operatorii pot fi doar + ºi *. subarborele stâng fiind arborele binar asociat expresiei E1. 57 . unde op este un operator. afiºeazã forma polonezã a expresiei ºi genereazã codul optimal pentru expresia datã. arborele binar corespunzãtor conþine în rãdãcinã operatorul.Observaþie Am ales pentru simplitate expresii aritmetice pentru care operanzii sunt formaþi dintr-un singur caracter. iar E1 ºi E2 sunt expresii aritmetice. construit dupã urmãtoarele reguli:* -dacã expresia este formatã dintr-un singur operand. rãdãcina.

obþinem notaþia polonezã a expresiei (forma prefixatã).dr )). iar nodurile interioare conþin operatori. notaþia polonezã este *+ab+*ac*bd.dr) . Într-un arbore binar asociat unei expresii aritmetice nodurile terminale conþin operanzi.st)+ 1. De exemplu.st)= MR(x^ .dr). dacă MR(x^ . utilizând un numãr minim de regiºtri de memorie. Vom descrie o procedurã de generare a codului corespunzãtor unei expresii aritmetice reprezentate ca un arbore binar.st). R |1. Parcurgând în preordine arborele binar asociat expresiei aritmetice. | MR(x^ . pentru expresia aritmeticã E=(a+b)*(a*c+b*d).MR( x^ . dacă MR(x^ . Numãrul minim de regiºtri necesari pentru a evalua expresia corespunzãtoare subarborelui cu rãdãcina x este: Fig. Lemã Fie A arborele binar asociat unei expresii aritmetice ºi x un nod din A. Lucasiewicz ºi permite scrierea fãrã paranteze a unei expresii aritmetice. MR( x) = S max(MR( x^ . Operatorii utilizaþi în cadrul expresiei fiind binari. 2.st)≠MR(x^ . T Observaþii 58 dacă x este un nod terminal. Aceastã notaþie a fost introdusã de matematicianul polonez J. Pentru a genera codul asociat unei expresii aritmetice vom presupune pentru început cã operatorii + ºi * nu sunt comutativi ºi nici asociativi.Observaþii 1. arborele binar asociat expresiei aritmetice este strict. 2.

UR). rad^. fãrã a þine cont de proprietãþile de //comutativitate ºi asociativitate ale operatorilor //UR este o variabilã globalã care indicã numãrul ultimului registru //ocupat begin if rad^. Demonstraþia se poate face prin inducþie dupã înãlþimea subarborelui cu rãdãcina în x ºi o propunem ca exerciþiu. ’ ‘. end else begin //genereazã mai întâi codul asociat subarborelui stâng GenCod(rad^. Pentru orice nod x din arbore. ’ R’.inf. se poate calcula MR(x) parcurgând arborele în postordine.st). //genereazã codul asociat expresiei aritmetice reprezentate prin //arborele cu rãdãcina rad.inf. ’ R’.st) then begin //genereazã mai întâi codul asociat subarborelui drept GenCod(rad^. rad^. writeln(‘OP’. UR). dec(UR). procedure GenCod (rad: Arbore). dec(UR). GenCod(rad^. UR-1.inf). writeln(‘OP’.dr). writeln(‘PUNE R’. ’ R’. 2. end else if MR(rad^. rad^. GenCod(rad^.st).st = nil then //expresie formatã dintr-un singur operand begin inc(UR).1.dr) > MR(rad^. UR. ’ R’. end 59 . UR-1.dr).

sã se aducã expresia în formã canonicã. e) Datã o expresie aritmeticã în notaþie polonezã. 60 . numãrul de regiºtri de memorie utilizaþi. a) a*b*c+2*d*(a+1+2*b*c) b) 2*a*c*(a*b+c+3*d+a*b*c*d) c) Evaluaþi complexitatea procedurii de generare a codului corespunzãtor unei expresii aritmetice. scrieþi un program care sã evalueze expresia. eventual. aplicând ori de câte ori este nevoie distributivitatea înmulþirii faþã de adunare (a*(b+c)=a*b+a*c. a*a=a). În acest caz. 3. diferã în funcþie de forma arborelui asociat expresiei.end. În caz afirmativ. Dacã sunt luate în considerare ºi proprietãþile de comutativitate ºi asociativitate ale operatorilor. d) Scrieþi un program care sã citeascã un ºir de caractere ºi sã verifice dacã reprezintã o expresie aritmeticã validã (în sensul definiþiei de mai sus). cât ºi timpul de evaluare a expresiei. Exerciþii: 1. idempotenþa (a+a=a. Fig. (b+c)*a=b*a+b*c) ºi. De exemplu. Construiþi un arbore binar pentru fiecare din expresiile urmãtoare ºi determinaþi notaþia polonezã. atunci aceeaºi expresie poate fi reprezentatã echivalent prin arbori binari diferiþi.

timpul necesar pentru evaluarea expresiei E1 op E2 fiind egal cu timpul necesar pentru efectuarea operaþiei op plus maximul dintre timpii necesari evaluãrii subexpresiilor E1 ºi E2. rad: Arbore. dr: Arbore. var e: string[LgMax]. Indicaþie Transformaþi arborele binar asociat expresiei aritmetice într-un arbore binar echilibrat dupã înãlþime. notãm p timpul necesar pentru efectuarea unei adunãri ºi q timpul necesar pentru efectuarea unei înmulþiri.pentru valori date ale operanzilor. st. Anexã program Expresie_Aritmetica. const LgMax = 30. Indicaþie: Se vor aduce cele douã expresii în formã canonicã. type Indice = 1. (a+b)+c=a+(b+c). Arbore = ^NodArbore. þinând cont de proprietãþile de comutativitate ºi asociativitate ale operatorilor ºi aplicând ori de câte ori este necesar regulile de distributivitate ºi idempotenþã. scrieþi un program care sã verifice dacã cele douã expresii sunt echivalente. f) Date douã expresii aritmetice sintactic valide. 6. Florian Boian la Olimpiada Internaþionalã de Informaticã Cluj. UR: byte. 61 . Transformãrile permise sunt: a*b=b*a. fout: text. aplicând rotaþii simple sau duble. lg: Indice. Timpul de evaluare a unui operand este considerat nul. (Propusã de conf. -Sã se determine o expresie echivalentã cu timp de evaluare minim ºi valoarea acestui timp. echivalente cu aplicarea proprietãþilor de comutativitate ºi asociativitate. 1994) Datã fiind o expresie aritmeticã. Scrieþi un program care citeºte date dintr-un fiºier ce conþine valorile lui p ºi q ºi expresii. Pentru fiecare expresie se cere: -Sã se determine timpul necesar evaluãrii ei. end. fiecare expresie pe o linie separatã. dr.. a+b=b+a (a*b)*c=a*(b*c).LgMax. i. NodArbore = record inf: char.

{construieste arborele binar asociat unui factor} var p: Arbore. inc(i).dr := Termen(i). 62 .inf := e[i]. end end. r^. readln(e). end. begin r1 := Factor(i). end. Termen := p. if (i > lg) or (e[i] <> '*') then Termen := r1 else begin new(p). p^. end else begin new(p).st := nil. end. preordine(r^. p^. lg := length(e). Factor := p. begin if e[i] = '(' then begin inc(i). {parcurge arborele binar asociat expresiei aritmetice in preordine} begin if r <> nil then begin write(fout.dr := nil. {construieste arborele binar asociat unui termen} var p. p^. end. end. p^. begin write('Introduceti expresia '). Factor := CreareArbore(i).st). inc(i). function CreareArbore(var i: Indice): Arbore. function Factor(var i: Indice): Arbore. p^. preordine(r^. procedure preordine(r: Arbore). inc(i).dr).st := r1.inf). forward.inf := e[i].procedure Citire. function Termen(var i: Indice): Arbore. r1: Arbore. p^.

GenCod(rad^.dr). {genereaza codul asociat expresiei aritmetice reprezentate prin arborele cu radacina rad} {UR este o variabila globala care indica numarul ultimului registru ocupat} begin if rad^.dr := CreareArbore(i).st := r1. begin if i > lg then CreareArbore := nil else begin r1 := Termen(i).dr). 63 . if (i > lg) or (e[i] = ')') then CreareArbore := r1 else begin new(p). r1: Arbore.st) then begin {genereaza mai intai codul asociat subarborelui drept } GenCod(rad^. procedure GenCod(rad: Arbore). p^. m2: byte. if m1 = m2 then MR := m1+1 else if m1 > m2 then MR := m1 else MR := m2. begin if rad^. p^. end. rad^. 'PUNE R'. end. inc(i). end end.st).st = nil then {operand} MR := 1 else begin m1 := MR(rad^. UR. {construieste arborele binar asociat unei expresii aritmetice} var p.st).inf := e[i]. CreareArbore := p. m2 := MR(rad^. ' '.inf). function MR(rad: Arbore): byte. end else if MR(rad^. var m1. p^. end. writeln(fout.dr) > MR(rad^.st = nil then begin {expresie formata dintr-un singur operand} inc(UR).function CreareArbore(var i: Indice): Arbore.

UR).st).writeln(fout.UR-1. end end. writeln(fout. end else begin {genereaza mai intai codul asociat subarborelui stang} GenCod(rad^. MR(rad). 64 .' R'. end. GenCod(rad^.' R'.rad^.'OP'. preordine(rad). UR := 0. dec(UR).'OP'.out').rad^.UR). begin {program principal} Citire. GenCod(rad).' R'. assign(fout.inf. i := 1. De exemplu. writeln(fout.'expr. dec(UR). pentru expresia aritmeticã E=(a+b)*(1+c)+2*a*b. writeln(fout). conþinutul fiºierului de ieºire va fi: +*+ab+1c*2*ab PUNE R1 a PUNE R2 b OP+ R1 R2 PUNE R2 1 PUNE R3 c OP+ R2 R3 OP* R1 R2 PUNE R2 a PUNE R3 b OP* R2 R3 PUNE R3 2 OP* R2 R3 OP+ R1 R2 Pentru evaluarea expresiei au fost necesari 3 registri. rad := CreareArbore(i). close(fout).dr).UR-1. 'Pentru evaluarea expresiei au fost necesari '. rewrite(fout).inf.' registri').' R'.

65 .

Sign up to vote on this title
UsefulNot useful