Sunteți pe pagina 1din 3

1

7. Forma polonez a expresiilor aritmetice


Se mai numete notaia fr paranteze a expresiilor aritmetice i de studiul acestei probleme s-a ocupat matematicianul polonez J. Lukasiewicz. Deoarece ntr-o expresie aritmetic, un operator se aplic unui operand sau unei perechi de operanzi, s-a ajuns la ideea de a asocia unei expresii aritmetice un arbore binar. Presupunem c se noteaz cu E1 respectiv cu E2 dou expresii aritmetice crora li se aplic operatorul notat op. Operatorii pe care i vom accepta sunt doar operatorii binari, i anume: adunarea (+), scderea (-), nmulirea (*), mprirea (/) i ridicarea la putere (^). Pentru a asocia unei expresii aritmetice fr paranteze un arbore binar se folosesc urmtoarele reguli: - unei expresii aritmetice format dintr-un singur operand i se asociaz un arbore binar format doar din nodul rdcin n care se pune operandul respectiv - dac expresia aritmetic E este de forma E1 op E2, atunci arborele binar complt asociat are ca rdcin operatorul op, ca subarbore stng are arborele binar asociat expresiei aritmetice E1, iar ca subarbore drept are arborele binar asociat expresiei aritmetice E2 Exemplu: Fie expresiile cele mai simple care se pot forma cu operatorii binari cunoscui: a+b, a-b, a*b, a/b i a . Considernd op unul dintre operatorii binari +,-,*,/,, arborele binar asociat este cel din figura urmtoare:
b

Exemplu: Fie expresia E=a*b+c/d-e. Ne propunem s determinm arborele binar asociat. Se observ c, deoarece nu este stabilit modul de asociere a termenilor, se pot obine doi arbori binari, dup cum se consider E1=a*b+c/d i E2=e, sau E1=a*b i E2=c/d-e. Se obin corespunztor arborii din figura de mai jos.

Aceti arbori binari se pot parcurge folosind oricare din cele trei metode. Se obine astfel: RSD: -+*ab/cde respectiv RSD: +*ab-/cde SRD: a*b+c/d-e respectiv SRD: a*b-c/d-e SDR: ab*cd/+erespectiv SDR: ab*cd/e-+ irul obinut prin parcurgerea n preordine a arborelui binar ataat expresiei aritmetice se numete forma polonez prefixat asociat expresiei, iar irul obinut prin prin parcurgerea n postordine se numete forma polonez postfixat asociat expresiei aritmetice. Observaii: Se poate construi arborele binar asociat i pentru o expresie aritmetic care conine paranteze rotunde. n forma polonez nu apar parantezele, acestea nemaifiind necesare pentru a marca prioritile de calcul. Programul urmtor citete o expresie aritmetic care conine paranteze rotunde, operanzi de o liter i operatori binari +,-,*,/ i construiete forma polonez prefixat. Pentru a construi n memorie arborele binar ataat pornind de la expresia aritmetic (citit ca ir de caractere) se acord prioriti operatorilor i operanzilor astfel: - prioritatea iniial a operatorilor +,- este 1 - prioritatea iniial a operatorilor *,/ este 10 - la prioritatea unui operand se adaug zece uniti pentru fiecare pereche de paranteze ntre care se gsete - prioritatea unui operand este 1000 Construirea prioritilor se realizeaz astfel: - se citete expresia aritmetic n irul de caractere e - se utilizeaz o variabil j care indic ce valoare se adaug la prioritatea iniial a unui operator (la ntlnirea unei paranteze deschise j crete cu 10, iar la ntlnirea unei paranteze nchise scade cu 10) - se parcurge expresia caracter cu caracter i se memoreaz n vectorul p prioritile operatorilor i operanzilor

2 n vectorul efp se construiete expresia aritmetic fr paranteze, iar n pfp se obine vectorul prioritilor din care, spre deosebire de epf, lipsesc componentele corespunztoare parantezelor - utiliznd vectorii efp i pfp funcia Creare() construiete n heap arborele binar ataat expresiei aritmetice. Conform tehnicii Divide Et Impera, funcia Creare() lucreaz astfel: - de la limita superioar (ls) ctre cea inferioar (li), limite corespunztoare irurilor din efp, se caut operandul sau operatorul cu prioritate minim, reinndu-se i poziia acestuia - n situaia n care limita superioar este diferit de cea inferioar, pentru completarea adresei subarborelui stng, respectiv drept, se reapeleaz funcia Creare() #include<iostream> #include<string.h> using namespace std; #define MAX 100 typedef struct nod{ char inf; nod *st,*dr; }ARB; char e[MAX],efp[MAX]; int p[MAX],pfp[MAX]; ARB *rad; void Creare(ARB* &c,int li,int ls,char epf[],int pfp[]) { int i,j,min; min=pfp[ls]; i=ls; for(j=ls;j>=li;j--) if(pfp[j]<min) { min=pfp[j]; i=j; } c=new ARB; c->inf=efp[i]; if(li==ls) c->st=c->dr=0; else { Creare(c->st,li,i-1,efp,pfp); Creare(c->dr,i+1,ls,efp,pfp); } } void Parcurgere(ARB *c) { if(c) { cout<<c->inf;Parcurgere(c->st); Parcurgere(c->dr); } } int main() { int i,j=0; cout<<"introduceti expresia: "; gets(e); for(i=0;e[i];i++) switch(e[i]) { case ')': j-=10; break; case '(': j+=10; break; case '+': case '-': p[i]=j+1; break; case '*': case '/': p[i]=j+10; break; default: p[i]=1000; } j=-1; for(i=0;e[i];i++) if(e[i]!=')'&&e[i]!='(') { j++; efp[j]=e[i]; pfp[j]=p[i];

3 } Creare(rad,0,j,efp,pfp); cout<<"\nForma poloneza prefixata este: "; Parcurgere(rad); cout<<"\n"; return 0; } Modul n care se folosete forma polonez prefixat pentru evaluarea expresiei aritmetice asociate este urmtorul: se parcurge forma polonez prefixat de la dreapta la stnga utilizndu-se o stiv pentru memorarea operanzilor. Dac simbolul curent este un operand, el se introduce n vrful stivei. Dac simbolul citit este un operator, se aplic acest operator primilor doi operanzi din vrful stivei obinndu-se un rezultat. Cei doi operanzi sunt eliminai din stiv i n locul lor se trece rezultatul obinut. Se trece apoi la urmtorul simbol care conine forma polonez prefixat asociat expresiei aritmetice. Programul urmtor ilustreaz aceast modalitate de evaluare a expresiilor aritmetice. Operanzii sunt identificai printr-o singur liter, iar operatorii sunt binari din mulimea +,-,*,/. #include<iostream> #include<string.h> using namespace std; char e[100]; float s[100],x,y; //s este stiva int n,i,p; int main() { cout<<"\tIntroduceti expresia aritmetica in forma prefixata\n"; gets(e); n=strlen(e); for(i=n-1;i>=0;i--) if(e[i]=='+'||e[i]=='-'||e[i]=='*'||e[i]=='/') { x=s[p--]; y=s[p]; switch(e[i]) { case '+': s[p]=x+y; break; case '-': s[p]=x-y; break; case '*': s[p]=x*y; break; case '/': s[p]=x/y; break; } } else s[++p]=e[i]-'0'; cout<<"\nvaloarea expresiei este "<<s[1]<<endl; return 0; }