Sunteți pe pagina 1din 31

Structuri de Date în Java (VII)

● Aplicaţie pentru stive şi cozi


● Evaluarea expresiei aritmetice postfixate

● Translatarea din formă infixată în postfixată

● Recursivitate

● Explicaţii şi teste

● Fractali. Proprietăţi

● Setul Mandelbrot

● O culme muntoasă

● Setul Sierpinski

1
Aplicaţie pentru stive şi cozi
● Temă de laborator
● Translatarea unei expresii aritmetice din forma

infixată cu paranteze în forma poloneză


inversă (postfixată)
● Calcularea expresiei obţinute

● Se citeşte întreaga expresie de la tastatură, într-

un string
● Programul trebuie să evalueze expresia şi să

afişeze forma postfixată asociată


● Eventualele erori trebuie semnalizate

2
Expresie aritmetică postfixată
● notaţia infixată: 2+3
● notaţia prefixată: + 2 3 (forma poloneză)
● inventată de matematicianul polonez Jan Lukasiewicz

● expresia (2 + 3) * 7 se scrie în formă poloneză * + 2 3 7

(scăpăm de paranteze)
● notaţia poloneză inversă, sau notaţia postfixată pentru

expresia (2 + 3) * 7 este 2 3 + 7 *
● notaţia postfixată nu necesită paranteze şi poate fi evaluată

uşor folosind o stivă


● principiul: se citeşte expresia postfixată; dacă se întâlneşte un

număr, acesta se pune în stivă; un semn se foloseşte de îndată


ce este întâlnit
3
Evaluarea unei expresii postfixate

while mai există cuvinte în expresie do


citeşte cuvântul următor
if cuvântul este o valoare then
push (cuvânt)
else cuvântul este un operator
pop () două valori de pe stivă
rezultat = aplicarea operator-ului valorilor
push (rezultat)
rezultatul final = pop ()
// rezultatul evaluării expresiei se găseşte pe vârful stivei

4
Exemplu de evaluare postfixată
532*+4–5+ 532*+4–5+ 532*+4–5+

2
3 3
5 5 5

532*+4–5+ 532*+4–5+ 532*+4–5+

6 4
5 11 11

532*+4–5+ 532*+4–5+ 532*+4–5+

5 Rezultatul
7 7 12 evaluării
expresiei
5
Translatarea unei expresii din forma
infixată în forma postfixată (i)
3 * X + (Y – 12) - Z 3 * X + (Y – 12) - Z 3 * X + (Y – 12) - Z

Tiparit: Tiparit: Tiparit:


3 * 3 * 3X
numerele se tipăresc înmulţirea pe stivă operandul se tipăreşte

3 * X + (Y – 12) - Z 3 * X + (Y – 12) - Z 3 * X + (Y – 12) - Z

Tiparit: ( Tiparit: ( Tiparit:


+ 3X* + 3X* + 3X*Y
* are precedenţă mai ( se pune pe stivă operandul se tipăreşte
mare decât + şi se
tipăreşte

6
Translatarea unei expresii din forma
infixată în forma postfixată (ii)
3 * X + (Y – 12) - Z 3 * X + (Y – 12) - Z 3 * X + (Y – 12) - Z

- -
( Tiparit: ( Tiparit: Tiparit:
+ 3X*Y + 3 X * Y 12 + 3 X * Y 12 -
- este pus pe stivă (era numerele se tipăresc se scoate tot până la
doar paranteza) paranteza (

3 * X + (Y – 12) - Z 3 * X + (Y – 12) - Z 3 * X + (Y – 12) - Z

Tiparit:
Tiparit: Tiparit: 3 X * Y 12 - + Z -
- 3 X * Y 12 - + - 3 X * Y 12 - + Z
tipăreşte, + are aceeaşi operandul se tipăreşte goleşte stiva
precedenţă cu -

7
Algoritmul de translatare
● iniţializează stiva
● repetă paşii următori
● dacă urmează o paranteză deschisă “(“, atunci o pune în stivă

● dacă însă urmează un număr sau operand, atunci îl tipăreşte

● dacă însă e un operator, atunci:

● dacă în vârful stivei este un alt operator cu precedenţa mai mare

sau egală cu a acestuia, atunci se scoate acel operator din stivă şi


se tipăreşte
● se pune pe stivă operatorul

● altfel, ceea ce urmează este o paranteză închisă “)”

● se scot simboluri din stivă şi se afişează până se întâlneşte

paranteza deschisă corespondentă, care se scoate şi ea din stivă


● până când expresia se termină
● se scot şi se afişează operatorii care au mai rămas în stivă (nu ar trebui să
mai avem paranteze deschise)
8
Recursivitate

“În matematică sau computer science, recursivitatea


specifică (sau construieşte) o clasă de obiecte sau
metode prin definirea câtorva cazuri de bază
(deseori doar unul) şi prin descrierea regulilor ce
descompun cazurile complexe într-unele mai
simple.”
(Wikipedia)

9
Metode recursive

● recursivitatea înseamnă rezolvarea unei probleme cu


ajutorul rezultatului obţinut prin rezolvarea unei aceleiaşi
probleme dar de mărime mai redusă
● practic o metodă se poate autoapela dar cu un argument

de mărime mai mică


● se poate formula o abordare recursivă pentru o problemă

● la formularea unei metode recursive, trebuie acordată

atenţie la evoluţia argumentului metodei, pentru a nu


ajunge la valori invalide

10
:-P
Recursion
If you still don't get it, See: "Recursion".

Recursive acronyms
● GNU: GNU's Not Unix

● PHP: PHP Hypertext Preprocessor

● GNU HURD: HIRD of Unix-Replacing Daemons

● HIRD: HURD of Interfaces Representing Death

(hurd/hird/herd of gnus – i.e. the antelope)

11
Metoda writeVertical
● problema: să se scrie cifrele unui număr pe verticală,
folosind o metodă recursivă
public class RecWrite
{
public static void writeVertical (int number)
{
if( number < 10 )
System.out.println (number); problema opririi
else
{
writeVertical (number / 10); apelul recursiv
System.out.println (number % 10);
}
}

public static void main (String[] args)


{
writeVertical (1234);
}
}
12
Desfăşurarea apelurilor (I)
apel writeVertical( 1234 )

1234 < 10 ? NU
apel writeVertical( 123 )
apelăm writeVertical(123)
scriem cifra '4'
123 < 10 ? NU
apelăm writeVertical( 12 )
apel writeVertical( 12 )
scriem cifra '3'
12 < 10 ? NU
apelăm writeVertical(1)
apel writeVertical( 1 )
scriem cifra '2'
1 < 10 ? DA
scriem cifra '1'

13
Desfăşurarea apelurilor (II)
apel writeVertical( 1234 ) apel writeVertical( 123 )

1234 < 10 ? NU 123 < 10 ? NU


apelăm writeVertical(123) apelăm writeVertical( 12 )
scriem cifra '4' scriem cifra '3'

apel writeVertical( 1 ) apel writeVertical( 12 )

1 < 10 ? DA 12 < 10 ? NU
scriem cifra '1' apelăm writeVertical(1)
scriem cifra '2'
14
Desfăşurarea apelurilor (III)

● Colecţia de parametri ai metodei curente precum


şi variabilele sale locale sunt salvate pe stivă
înainte de efectuarea apelului recursiv
● La întoarcerea din apel, se refac aceste valori tot

folosind stiva
● Instrucţiunea de după apel se execută după ce s-a

revenit din apel, valorile parametrilor rămîn


aceleaşi cu cele de dinainte de apel

15
Teste - A

// ce se afişează pentru apelul f(3) ?

public static void f(int n) {


System.out.println (n);
if (n > 1)
f (n-1);
}

16
Teste - B

// ce se afişează pentru apelul f(3) ?

public static void f(int n) {


if (n > 1)
f (n-1);
System.out.println (n);
}

17
Teste - C

// ce se afişează pentru apelul f(3) ?

public static void f(int n) {


System.out.println (n);
if (n > 1)
f (n-1);
System.out.println (n);
}

18
Fractali
● Noţiunea de “fractal” inventată de Benoît
Mandelbrot (1975) descrie obiecte a căror
porţiune mărită (cu o lupă) prezintă similaritate
cu întregul obiect
● Denumire derivată din latinescul fractus

● Un fractal matematic este bazat pe o ecuaţie

iterativă, bazată pe recursie


● Structuri geometrice folosite de programatori
pentru a realiza scene naturale reprezentînd
arbori, munţi, nori etc.
19
Setul Mandelbrot

detaliu:
20
Proprietăţi

● Are o structură fină oricât de mult ar fi “mărit”

● Este mult prea neregulat pentru a fi descris cu


ajutorul geometriei euclidiene

●Întregul are aceeaşi formă ca una sau mai multe


părţi ale sale (self-similarity)

● Are o definiţie simplă şi recusivă


21
Generarea fractalilor
● Punctul situat la jumătatea segmentului este deplasat în sus sau în jos cu
o distanţă aleatoare
● Se aplică regula din nou pe subsegmentele create
● Se opreşte când mărimea unui subsegment devine relativ mică

a) segmentul iniţial b) mijlocul segmentului este


mutat mai sus sau mai jos

c) două mijloace
sunt mutate d) se mută patru mijloace
22
O coamă muntoasă

Procedeul se aplică
recursiv până când
distanţa dintre două
puncte devine < 50

(rezoluţie 512 x 512)

23
randomFractal (0, height/2, width, height/2)
public void randomFractal (
int leftX, int leftY, int rightX, int rightY) {
final int STOP = 50;
int midX, midY, deltam, deltap, delta;

if ((rightX - leftX) <= STOP)


drawArea.drawLine (leftX, leftY, rightX, rightY);
else {
midX = (leftX + rightX) / 2;
midY = (leftY + rightY) / 2;
deltam = - (int)(Math.random() * midY / 2);
deltap = (int)(Math.random () * (width - midY) / 2);
delta = -deltam < deltap ? deltam : deltap;
midY += delta;

randomFractal (leftX, leftY, midX, midY);


randomFractal (midX, midY, rightX, rightY);
}
}
24
Un fractal cu pătrate

● Care este regula


recursivă
de formare?

●Care este condiţia


de oprire ?

25
cubFractal (0, 0, width, height);
public void cubFractal (
int leftX, int leftY, int rightX, int rightY) {
final int STOP = 4;
int midX, midY;

if (rightX - leftX <= STOP)


drawArea.drawRect (leftX, leftY,
rightX - leftX, rightY - leftY);
else {
midX = (leftX + rightX) / 2;
midY = (leftY + rightY) / 2;
drawArea.drawRect (leftX, leftY,
midX - leftX, midY - leftY);
drawArea.drawRect (midX, midY,
rightX - midX, rightY - midY);

cubFractal (midX, midY, rightX, rightY);


cubFractal (midX, leftY, rightX, midY);
cubFractal (leftX, midY, midX, rightY);
}
}
26
Triunghiul Sierpinski

Fractal descris
în 1915 de către
matematicianul
polonez
Waclaw Sierpinski

27
Abstractizarea unui punct
static class Pair {
public int x;
public int y;
public Pair (int x, int y) {
this.x = x;
this.y = y;
}
public static Pair mid (Pair a, Pair b) {
return new Pair ((a.x + b.x) / 2,
(a.y + b.y) / 2);
}
public static int len (Pair a, Pair b) {
double x = a.x - b.x;
double y = a.y - b.y;
x *= x; y *= y;
return (int)Math.sqrt (x + y);
} } 28
Triunghiul iniţial

public void sierpinski () {


Pair a = new Pair (width / 2, 0);
Pair b = new Pair (0, height);
Pair c = new Pair (width, height);
sierpinski (a, b, c);
}

29
Procedura de generare
public void sierpinski (Pair a, Pair b, Pair c) {
if (Pair.len (a, b) < 10) {
drawArea.drawLine (a.x, a.y, b.x, b.y);
drawArea.drawLine (b.x, b.y, c.x, c.y);
drawArea.drawLine (a.x, a.y, c.x, c.y);
return;
}

Pair ab = Pair.mid (a, b);


Pair bc = Pair.mid (b, c);
Pair ac = Pair.mid (a, c);

sierpinski (a, ab, ac);


sierpinski (ab, b, bc);
sierpinski (ac, bc, c);

}
30
Mult mai mult

http://en.wikipedia.org/wiki/Fractal

31