Sunteți pe pagina 1din 237

Analiza i proiectarea

algoritmilor
Curs, anul II Calculatoare, Tehnologia informaiei,
Ingineria sistemelor multimedia
Puncte de credit: 5
Autor: Dr. rpd GELLRT
Web: http://webspace.ulbsibiu.ro/arpad.gellert
E-mail: arpad.gellert@ulbsibiu.ro
Universitatea Lucian Blaga din Sibiu,
Catedra de Calculatoare i Automatizri
2
Cuprins (1)
Partea I Limbajul Java
Structura lexical i instruciuni
Variabile i constante
Tablouri i matrici
Tratarea excepiilor
Operaii I/O
Crearea claselor
Interfee grafice
Fire de execuie
Colecii
3
Partea II Analiza algoritmilor
Complexitate, notaii asimptotice
Recurene
Algoritmi de cutare i sortare
Tabele de dispersie
Arbori binari
Heap-uri
Grafuri
Cuprins (2)
4
Partea III Proiectarea algoritmilor
Divide et impera
Greedy
Programare dinamic
Backtracking
Algoritmi genetici
Reele neuronale
Cuprins (3)
5
Nota final
Nota laborator (NL) = 0,2*T1 + 0,2*T2 + 0,1*A + 0,5*C
Nota final = 0,5*NL + 0,5*E
T1 = Test gril susinut din noiunile predate n cadrul
capitolului Limbajul Java;
T2 = Test susinut la laborator din aplicaiile propuse la
laborator n cadrul capitolului Limbajul Java;
A = Activitatea la laborator (teme);
C = Colocviu de laborator din aplicaiile propuse la laborator n
cadrul capitolelor Analiza algoritmilor respectiv Proiectarea
algoritmilor;
E = Examen susinut din capitolele Analiza algoritmilor i
Proiectarea algoritmilor.
6
Bibliografie de baz
[Knu00] Knuth D., Arta programrii calculatoarelor, Teora, 2000.
[Cor00] Cormen T., Leiserson C., Rivest R., Introducere n algoritmi, Agora, 2000.
[Giu04] Giumale C., Introducere n analiza algoritmilor, Polirom, 2004.
[Wai01] Waite M., Lafore R., Structuri de date i algoritmi n Java, Teora, 2001.
[Log07] Logoftu D., Algoritmi fundamentali n Java, Polirom, 2007.
[Tan07] Tanas ., Andrei ., Olaru C., Java de la 0 la expert, Polirom, 2007.
7
Geneza cuvntului algoritm: provine din
latinizarea numelui savantului Al-Khwarizmi
(algoritmi) matematician, geograf,
astronom i astrolog persan (780-850),
considerat i printele algebrei moderne.
Introducere (1)
Algoritmul este o secven de operaii care transform
mulimea datelor de intrare n datele de ieire.
Proiectarea algoritmului const n dou etape:
Descrierea algoritmului printr-un pseudolimbaj (schem logic,
pseudocod);
Demonstrarea corectitudinii rezultatelor n raport cu datele de
intrare.
Analiza algoritmului se refer la evaluarea
performanelor acestuia (timp de execuie, spaiu de
memorie).
8
Imlementarea algoritmilor se va face n limbajul Java. Medii de
dezvoltare:
Java Development Kit (JDK) http://www.sun.com
Eclipse http://www.eclipse.org
Java Builder
NetBeans
Principalele caracteristici ale limbajului Java:
Simplitate elimin suprancrcarea operatorilor, motenirea multipl, etc.;
Complet orientat pe obiecte;
Portabilitate Java este un limbaj compilat i interpretat, fiind astfel
independent de platforma de lucru (Write Once, Run Enywhere);
Ofer posibilitatea, prin JNI (Java Native Interface), de a implementa aplicaii
mixte (ex. Java/C++), preul folosirii codului nativ fiind ns dependena de
platform [Gor98];
Permite programarea cu fire de execuie.
Introducere (2)
9
n urma compilrii codului surs, se obine codul de octei (bytecode)
care este apoi interpretat de maina virtual Java (JVM). Astfel,
aplicaia poate fi rulat pe orice platform care folosete mediul de
execuie Java.
Pe lng aplicaii obinuite, pot fi implementate aplicaii web (applet),
aplicaii server (servlet, JavaServer Pages, etc.), aplicaii n reea,
telefonie mobil (midlet), aplicaii distribuite RMI (Remote Method
Invocation), etc.
Compilarea programelor (javac.exe):
javac *.java
Rularea programelor (java.exe):
java *
.java
Compilator
Java
.class
Java
Virtual
Machine
Cod surs Bytecode
Introducere (3)
Partea I
Limbajul Java
11
Limbajul Java
O aplicaie simpl:
class HelloWorld{
public static void main(String args[]){
System.out.println("Hello world");
}
}
Aplicaia HelloWorld afieaz la consol mesajul Hello world.
n orice aplicaie trebuie s existe o clas primar, care conine
metoda main de la care ncepe execuia n momentul rulrii.
Parametrul args al metodei main este un tablou de iruri de
caractere i reprezint argumentele din linie de comand.
Fiierul care conine clasa primar trebuie s aib numele clasei
(case sensitive!).
Java permite o singur clas public ntr-un fiier.
Compilarea programului: javac HelloWorld.java
Rularea programului: java HelloWorld
12
Limbajul Java convenii de scriere a codului [Web01]
Principalele segmentele ale codului Java apar n urmtoarea ordine:
Declaraia de pachet (package);
Directivele de import;
Declaraia de clas sau interfa;
Declaraiile variabilelor membru ale clasei (statice) sau ale instanei;
Constructori i metode;
Convenii de nume
Numele de clase, implicit de constructori, ncep cu majuscul (ex.:
NumeClasa);
Numele de metode ncep cu liter mic (ex.: numeMetoda);
Numele de variabile i obiecte ncep cu liter mic (ex.: numeObiect);
Numele constantelor se scriu cu majuscule, cuvintele fiind desprite
prin _ (ex.: NUME_CONSTANTA);
Numele trebuie s fie ct mai sugestive.
13
Limbajul Java Structura lexical
Structura lexical a limbajului Java este foarte asemntoare cu cea
a limbajului C++.
Comentariile se fac ca n C++.
Operatorii sunt n mare parte la fel ca n C++.
Instruciunile sunt i ele foarte asemntoare cu cele din C++. O
diferen important const n faptul c expresiile care apar n
instruciunile condiionale (if, for, while, do) sunt strict de tip
boolean, n timp ce n C++ pot fi de tip int.
Tipurile de date se clasific n dou categorii:
Tipuri de date primitive: byte (1 octet), short (2 octei), int (4 octei),
long (8 octei), char (2 octei unicode), float (4 octei), double (8
octei), boolean (1 bit);
Tipuri de date referin: clase, interfee, tablouri. Exist i variantele
referin ale tipurilor de date primitive: Byte, Short, Integer, Long,
Character, Float, Double, Boolean. Variantele referin ale tipurilor de
date primitive sunt necesare pentru c n Java nu exist operatorul &
pentru definiia unei referine. Pentru iruri de caractere, pe lng
char[], exist i tipul referin String.
14
Limbajul Java variabile
Variabilele primitive se pot crea prin declaraie. Exemple:
int i = 10;
float pi = 3.14f;
Variabilele referin se pot crea doar cu operatorul new (care returneaz
o referin), exceptnd variabilele de tip String care se pot crea i prin
declaraie. Exemple:
Integer integer = new Integer(10);
String strHello = new String(Hello);
String strWorld = world;
n Java nu este admis suprancrcarea operatorilor, excepie fiind doar
operatorul de adunare pentru clasa String, care permite concatenarea
irurilor. Exemplu:
String strHello = Hello;
String strWorld = world;
String strHelloWorld = strHello + + strWorld;
Concatenarea unui String cu o variabil primitiv determin conversia
implicit a acesteia n String. Exemplu:
String strTwo = Two;
int i = 2;
boolean b = true;
String str = strTwo + = + i + is + b; //Rezultat: Two = 2 is true
15
Limbajul Java constante
Pentru crearea unei constante, declaraia de variabil
trebuie precedat de cuvntul cheie final.
Nu este permis modificarea valorii unei constante.
O clas declarat final nu poate fi derivat (v.
motenirea).
Exemple
public class Main {
public static void main(String[] args) {
final String APA = "Analiza si proiectarea algoritmilor";
final int TEN = 10;
TEN++; //Eroare!
APA = "Analiza, proiectarea si implementarea algoritmilor"; //Eroare!
int eleven = TEN + 1;
}
}
16
Limbajul Java clasa String (1)
Principalele operaii:
substring cu parametrii index0 i indexf returneaza subirul care ncepe
la index0 i se termin la indexf-1, lungimea fiind indexf-index0. Exemplu:
String str = Hello world;
String substr = str.substring(0, 5); //Rezultat: Hello
charAt returneaz caracterul de pe o anumit poziie din ir. Exemplu:
String str = Hello world;
char c = str.charAt(6); //Rezultat: w
length retuneaz lungimea irului n numr de caractere. Exemplu:
String str = Hello world;
int len = str.length(); //Rezultat: 11
equals / equalsIgnoreCase permite comparaia unui ir cu alt ir.
Returneaz true dac cele dou iruri sunt egale, respectiv false dac ele
nu sunt egale. Exemplu:
String hello = Hello;
if(hello.equals(Hello)) //Rezultat: true
System.out.println(equal); //Rezultat: equal
17
compareTo / compareToIgnoreCase compar dou iruri.
Returneaz valoarea 0 dac cele dou iruri sunt lexicografic egale, o
valoare negativ dac parametrul este un ir lexicografic mai mare
dect irul curent i o valoare pozitiv dac parametrul este un ir
lexicografic mai mic dect irul curent. Exemplu:
String hello = Hello;
if(hello.compareTo(Hello) == 0) //Rezultat: 0
System.out.println(equal); //Rezultat: equal
trim elimin eventualele spaii de la nceputul i sfritul irului.
Exemplu:
String hello = Hello ;
System.out.println(hello.length()) ; //Rezultat: 7
hello = hello.trim();
System.out.println(hello.length()) ; //Rezultat: 5
toLowerCase / toUpperCase transform toate literele din ir n
litere mici / mari. Exemplu:
String str = Hello world;
str = str.toUpperCase(); //Rezultat: HELLO WORLD
Limbajul Java clasa String (2)
18
Limbajul Java clasa StringTokenizer
Permite separarea unui ir de caractere n simboluri;
Se instaniaz un obiect StringTokenizer, specificnd irul
de caractere i setul de delimitatori;
Urmtoarea secven de program afieaz pe ecran
simbolurile (cuvintele) irului delimitate prin caracterele
spaiu i virgul:
String apia = "Analiza, proiectarea si implementarea algoritmilor";
StringTokenizer st = new StringTokenizer(apia, " ,");
while(st.hasMoreTokens())
System.out.println(st.nextToken());
Setul de delimitatori poate fi specificat i prin funcia
nextToken:
while(st.hasMoreTokens())
System.out.println(st.nextToken(" ,"));
19
Limbajul Java tablouri
Posibiliti de declarare a tablourilor:
int[] fibo = new int[10];
int fibo[] = new int[10];
int n = 10;
int fibo[] = new int[n];
int fibo[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34};
Tablou cu elemente primitive vs. referin:
int pTab[] = new int[5]; //tablou (referinta!) cu 5 elem. primitive
for(int i=0; i<pTab.length; i++)
pTab[i] = i+1;
Integer rTab[] = new Integer[5]; //tablou (referinta!) cu 5 elem. referinta
for(int i=0; i<rTab.length; i++)
rTab[i] = new Integer(i+1);
Afiarea elementelor unui tablou:
for(int i=0; i<fibo.length; i++)
System.out.println(fibo[i]);
20
Limbajul Java clasa Arrays
Principalele operaii:
fill permite umplerea tabloului sau a unei zone din tablou cu o anumit valoare:
int tab[] = new int[5];
Arrays.fill(tab, 7); //Rezultat: tab={7,7,7,7,7}
Arrays.fill(tab, 1, 3, 8); //Rezultat: tab={7,8,8,7,7}
equals compar dou tablouri returnnd true dac au toate elementele egale:
int a[] = {1,2,3,4};
int b[] = {1,2,3,4};
int c[] = {1,2,4,8};
System.out.println(Arrays.equals(a, b) ? "a==b" : "a!=b"); //Rezultat: a==b
System.out.println(Arrays.equals(a, c) ? "a==c" : "a!=c"); //Rezultat: a!=c
sort sorteaz elementele tabloului n ordine cresctoare folosind algoritmul Quicksort pentru tipuri primitive
respectiv Mergesort pentru tipuri referin:
int pTab[] = {9,6,2,1,5,3};
Arrays.sort(pTab,1,4); //Rezultat: tab={9,1,2,6,5,3}
Arrays.sort(pTab); //Rezultat: tab={1,2,3,5,6,9}
Integer rTab[] = new Integer[5];
for(int i=0, k=rTab.length; i<rTab.length; i++, k--) //Rezultat : tab={5,4,3,2,1}
rTab[i] = new Integer(k);
Arrays.sort(rTab); //Rezultat : tab={1,2,3,4,5}
binarySearch returneaz poziia elementului cutat n tablou sau o valoare negativ dac valoarea cutat
nu este gsit. Algoritmul folosit este cutarea binar, de aceea tabloul trebuie sortat nainte de apelul acestei
metode. Exemplu:
int tab[] = {5,4,1,7,3}; //tablou nesortat
int v = Arrays.binarySearch(tab, 4); //Rezultat greit: -4
Arrays.sort(tab); //Rezultat: tab={1,3,4,5,7}
v = Arrays.binarySearch(tab, 4); //Rezultat corect: 2
21
Limbajul Java matrici
Posibiliti de declarare a matricilor:
int m[][] = new int[3][4];
int nRow=3, nCol=4;
int m[][] = new int[nRow][nCol];
int m[][] = new int[3][];
for(int i=0; i<3; i++)
m[i] = new int[4];
int m[][] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
Tablou multidimensional cu numr variabil de coloane. Exemplu de alocare, iniializare i
afiare:
int m[][] = new int[3][];
for(int i=0, k=1; i<3; i++){
m[i] = new int[4+i];
for(int j=0; j<4+i; j++, k++)
m[i][j] = k;
}
for(int i=0; i<3; i++){ //Rezultat afiat:
for(int j=0; j<4+i; j++) //1 2 3 4
System.out.print(m[i][j]+"\t"); //5 6 7 8 9
System.out.println(); //10 11 12 13 14 15
}
O matrice m are m.length linii i m[0].length coloane.
22
Limbajul Java conversii
Conversia variabilelor primitive
Conversie implicit. Exemplu:
int a = 3, b = 2;
double c = a/b; //Conversie din int in double. Rezultat: 1.0
Conversie explicit (casting). Exemplu:
double pi = 3.14;
int i = (int)pi; //Conversie din double in int. Rezultat: 3
Conversia variabilelor primitive n variabile referin. Exemple:
int x = 10;
Integer y = new Integer(x); //Conversie din int in Integer
float m = 3.14f;
Float n = new Float(m); //Conversie din float in Float
String str10 = String.valueOf(x); //Conversie din int in String
Conversia variabilelor referin n variabile primitive. Exemple:
Integer zece = new Integer(10);
int z = zece.intValue(); //Conversie din Integer in int
Double p = new Double(3.14);
double q = p.doubleValue(); //Conversie din Double in duble
String str20 = 20;
int d = Integer.parseInt(str20); //Conversie din String in int
String strPi = 3.14;
double pi = Double.parseDouble(strPi); //Conversie din String in double
23
Limbajul Java comparaii
Variabile primitive (comparaie)
int a = 5;
int b = 5;
System.out.println(a==b ? "a==b" : "a!=b"); //Rezultat : "a==b"
Variabile referin
Comparaie greit (se compar adrese!):
Integer a = new Integer(5);
Integer b = new Integer(5);
System.out.println(a==b ? "a==b" : "a!=b"); //Rezultat: "a!=b"
Comparaie corect (se compar valori!):
Integer a = new Integer(5);
Integer b = new Integer(5);
System.out.println(a.equals(b) ? "a==b" : "a!=b"); //Rezultat : "a==b
Comparaie corect (se compar valori!):
Integer a = new Integer(5);
Integer b = new Integer(5);
System.out.println(a.compareTo(b)==0 ? "a==b" : "a!=b"); //Rezultat: "a==b"
Comparaie corect (se compar valori!):
Integer a = new Integer(5);
Integer b = new Integer(5);
System.out.println(a.intValue()==b.intValue() ? "a==b" : "a!=b"); //Rezultat: "a==b"
24
Limbajul Java clasa File (1)
Clasa File ofer informaii despre fiiere i directoare i permite
redenumirea respectiv tergerea acestora. Principalele operaii:
length returneaz dimensiunea n octei a fiierului;
getName returneaz numele fiierului;
getPath / getAbsolutePath / getCanonicalPath returneaz calea fiierului;
getAbsoluteFile / getCanonicalFile returneaz un obiect File aferent fiierului;
isFile / isDirectory returneaz true dac e fiier / director;
canRead / canWrite returneaz true dac aplicaia poate citi / modifica fiierul;
exists verific dac fiierul exist;
delete terge fiierul sau directorul;
deleteOnExit terge fiierul sau directorul la nchiderea mainii virtuale;
list apelat pentru un director returneaz un tablou de tip String cu toate fiierele i
subdirectoarele din acel director. Exemplu:
File file = new File("e:\\algoritmi_curs");
String str[] = file.list();
for(int i=0; i<str.length; i++)
System.out.println(str[i]);
listFile apelat pentru un director returneaz un tablou de tip File cu toate fiierele i
subdirectoarele din acel director;
listRoots returneaz un tablou de tip File reprezentnd rdcinile sistemelor de fiiere
disponibile n sistem (ex.: "C:\\", "D:\\", "E:\\");
25
mkdir creeaz un director nou, returnnd true n caz de succes. Exemplu:
File file = new File("algoritmi");
System.out.println(file.mkdir());
mkdirs creeaz un director nou, inclusiv directoarele inexistente care apar n cale
renameTo permite redenumirea fiierelor, returnnd true n caz de succes. Exemplu:
File file = new File("Algoritmi.pdf");
System.out.println(file.renameTo(new File("algoritmi_curs.pdf")));
separator / separatorChar returneaz un String / char reprezentnd separatorul
dependent de sistem: '/' n UNIX respectiv '\' n Win32.
Limbajul Java clasa File (2)
26
Limbajul Java clasa System
Principalele operaii
currentTimeMillis returneaz un long
reprezentnd timpul n milisecunde. Poate fi folosit ca
parametru n constructorul clasei Date pentru
obinerea datei i orei n formatul dorit.
exit(0) provoac ieirea din aplicaie.
gc ruleaz mecanismul de garbage collector pentru
eliberarea zonelor de memorie ocupate de obiecte
neutilizate.
getProperties returneaz un obiect Properties din
care se pot extrage diferite informaii referitoare la
sistemul de operare.
27
Limbajul Java clasa Math
Cteva exemple
public class Main {
public static void main(String[] args) {
double pi = Math.PI;
System.out.println(pi); //3.141592653589793
System.out.println(Math.round(pi)); //3 - rotunjire la cel mai apropiat intreg
System.out.println(Math.floor(pi)); //3.0 - rotunjire in jos
System.out.println(Math.ceil(pi)); //4.0 - rotunjire in sus
System.out.println(Math.pow(2, 3)); //8.0 - ridicare la putere
System.out.println(Math.sqrt(9)); //3.0 - radical
System.out.println(Math.exp(1)); //2.7182818284590455 - valoarea exponentiala
double e = Math.E;
System.out.println(e); //2.718281828459045
System.out.println(Math.min(2, 8)); //2 - minimul
System.out.println(Math.max(2, 8)); //8 - maximul
System.out.println(Math.abs(-5)); //5 - valoarea absoluta
System.out.println(Math.log(e)); //1.0 - logaritmul natural
System.out.println(Math.random()); //valoare aleatoare subunitara
System.out.println(Math.sin(pi/2)); //1.0 - sinusul, exista si celelalte functii
System.out.println(Math.toDegrees(pi/2)); //90.0 - conversie in grade
System.out.println(Math.toRadians(180)); //3.141592653589793 - conv. in rad.
}
}
Aplicaii propuse
1. Cutarea minimului i a maximului ntr-un tablou de n elemente;
2. Generarea i afiarea unui tablou cu numerele lui Fibonacci.
3. Cutarea minimului i a maximului ntr-o matrice;
4. Adunarea a dou matrici;
5. nmulirea a dou matrici.
6. S se scrie un program care, prin intermediul clasei File, s permit navigarea n structura de directoare din sistem.
28
Limbajul Java tratarea excepiilor (1)
Excepiile sunt erorile care apar n timpul execuiei programelor.
O instruciune sau o secven de instruciuni trebuie inclus ntr-un bloc try n
vederea tratrii eventualelor excepii pe care le poate genera. Blocul try este
urmat de unul sau mai multe blocuri catch prin care sunt detectate diferitele
excepii. n blocul opional finally se introduc zonele de cod care trebuie
executate indiferent c apare sau nu o excepie. Forma general:
try{
//instructiuni care pot genera Exceptia1 si Exceptia2
}
catch(Exceptia1 e1){
//instructiunile care se executa daca apare Exceptia1
}
catch(Exceptia2 e2){
//instructiunile care se executa daca apare Exceptia2
}
finally{
//instructiunile care se executa indiferent ca apare sau nu o exceptie
}
Dac nu apar excepii, blocul try execut toate instruciunile. Dac o instruciune
din blocul try genereaz o excepie, se caut blocul catch corespunztor,
trecnd peste restul instruciunilor din try. Dac exist un catch corespunztor,
se execut instruciunile din acel bloc catch. Dac nu este gsit un bloc catch
corespunztor, excepia este transmis mai departe n ierarhia apelant. Dac
excepia ajunge n vrful ierarhiei fr s fie tratat, programul afieaz un
mesaj de eroare i se ntrerupe.
29
Este posibil ignorarea excepiilor i transmiterea lor mai sus prin throws n
ierarhia apelant.
n exemplul urmtor, dac n metoda apare Exceptia1 sau Exceptia2, ea este
ignorat, transmis mai departe i tratat n metoda apelant main (ca n
exemplul precedent):
public void metoda() throws Exceptia1, Exceptia2 {
//instructuni care pot genera Exceptia1 si Exceptia2
}
public static void main(String[] args) {
try{
metoda();
}
catch(Exceptia1 e1){
//instructiunile care se executa daca apare Exceptia1
}
catch(Exceptia2 e2){
//instructiunile care se executa daca apare Exceptia2
}
finally{
//instructiunile care se executa indiferent ca apare sau nu o exceptie
}
}
Limbajul Java tratarea excepiilor (2)
30
Exemplul 1
Implementai i apoi rulai urmtoarea secven de cod:
String str = "I'm a String!";
int i = Integer.parseInt(str);
System.out.println("Program execution finished...");
Conversia din String n int determin euarea execuiei programului
datorit coninutului nenumeric al variabilei str. Astfel nu se mai ajunge
la afiarea mesajului "Program execution finished...". Excepia
semnalat este NumberFormatException.
Tratarea excepiei:
String str = "I'm a String!";
try {
int i = Integer.parseInt(str);
}
catch (NumberFormatException nfe) {
System.out.println("Conversia nu a fost posibila!");
}
Excepia fiind tratat, execuia programului nu va mai eua.
Limbajul Java tratarea excepiilor (3)
31
Exemplul 2
Implementai i apoi rulai urmtoarea secven de cod:
int tab[] = new int[10];
tab[10] = 10;
Accesarea unui element inexistent, al 11-lea element, nealocat,
determin o excepie ArrayIndexOutOfBoundsException.
Tratarea excepiei:
int tab[] = new int[10];
try {
tab[10] = 10;
}
catch (ArrayIndexOutOfBoundsException aioobe) {
System.out.println("Ati accesat un element inexistent!");
}
Evident, excepia nu apare dac indexul folosit pentru accesarea
tabloului este ntre 0 i 9.
Limbajul Java tratarea excepiilor (4)
32
Limbajul Java operaii I/O (1)
Citirea irurilor de caractere de la tastatur
Fluxuri de caractere:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = null;
try {
str = br.readLine();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
Fluxuri de octei:
DataInputStream dis = new DataInputStream(System.in);
String str = null;
try {
str = dis.readLine();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
33
Citirea valorilor de la tastatur
Clasa DataInputStream pe lng metoda readLine (folosit pe
pagina anterioar pentru introducerea irurilor de caractere)
dispune i de funcii pentru citirea valorilor (readInt,
readDouble, etc.). Dar aceste metode sunt funcionale doar
pentru valori scrise prin interfaa DataOutput (writeInt,
writeDouble, etc.).
Citirea valorilor poate fi efectuat prin citire de iruri de
caractere urmat de conversia acestora:
DataInputStream dis = new DataInputStream(System.in);
String str = null;
try {
str = dis.readLine();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
int i = Integer.parseInt(str);
Limbajul Java operaii I/O (2)
34
Limbajul Java operaii I/O (3)
Citirea din fiiere
Urmtoarea secven de cod afieaz pe ecran toate liniile citite din fiierul
input.txt. Citirea se face prin aceeai clas DataInputStream care n loc de un
InputStream va primi ca parametru un FileInputStream:
FileInputStream fis = null;
try{
fis = new FileInputStream("input.txt");
}
catch(FileNotFoundException fnfe){
fnfe.printStackTrace();
}
DataInputStream dis = new DataInputStream(fis);
String str = null;
try{
while((str = dis.readLine()) != null)
System.out.println(str);
dis.close();
System.in.read();
}
catch(IOException ioe){
ioe.printStackTrace();
}
35
Scrierea n fiiere
Urmtoarea secven de program scrie n fiierul data.txt ntregul 10 i valoarea
float 3.14
try{
FileOutputStream fos = new FileOutputStream("data.txt");
DataOutputStream dos = new DataOutputStream(fos);
dos.writeInt(10);
dos.writeFloat(3.14f);
dos.close();
}
catch(IOException ioe){
ioe.printStackTrace();
}
Fiind scrise prin metodele writeInt i writeFloat, valorile pot fi citite din fiier
folosind metodele readInt respectiv readFloat ale clasei DataInputStream
try{
FileInputStream fis = new FileInputStream("data.txt");
DataInputStream dis = new DataInputStream(fis);
System.out.println(dis.readInt());
System.out.println(dis.readFloat());
dis.close();
}
catch(IOException ioe){
ioe.printStackTrace();
}
Limbajul Java operaii I/O (4)
36
Arhivare ZIP
Arhivarea unui fiier const n citirea datelor din acel fiier prin FileInputStream i scrierea
lor n arhiv prin ZipOutputStream. Pentru vitez mai mare, transferul datelor se face printr-
un tablou de tip byte:
String fisier = "Algoritmi.pdf"; //fisierul care se arhiveaza
String zip = "Algoritmi.zip"; //numele arhivei
byte buffer[] = new byte[1024];
try{
FileInputStream fileIn = new FileInputStream(fisier);
FileOutputStream f = new FileOutputStream(zip);
ZipOutputStream zipOut = new ZipOutputStream(f);
zipOut.putNextEntry(new ZipEntry(fisier));
int nBytes;
while((nBytes = fileIn.read(buffer, 0, 1024)) != -1)
zipOut.write(buffer, 0, nBytes);
zipOut.close();
fileIn.close();
f.close();
}
catch(ZipException ze){
System.out.println(ze.toString());
}
catch(FileNotFoundException fnfe){
fnfe.printStackTrace();
}
catch(IOException ioe){
ioe.printStackTrace();
}
Limbajul Java operaii I/O (5)
37
Dezarhivare ZIP
Dezarhivarea unui fiier const n citirea datelor din arhiv prin ZipInputStream i scrierea
lor prin FileOutputStream n fiierul destinaie. Pentru eficien, transferul datelor se face
printr-un tablou de tip byte:
String fisier = "Algoritmi.pdf"; //numele fisierului destinatie
String zip = "Algoritmi.zip"; //numele arhivei
byte buffer[] = new byte[1024];
try{
FileInputStream fileIn = new FileInputStream(zip);
FileOutputStream fileO = new FileOutputStream(fisier);
ZipInputStream zipIn = new ZipInputStream(fileIn);
zipIn.getNextEntry();
int nBytes;
while((nBytes = zipIn.read(buffer, 0, 1024)) != -1)
fileO.write(buffer, 0, nBytes);
fileIn.close();
fileO.close();
}
catch(ZipException ze){
System.out.println(ze.toString());
}
catch(IOException ioe){
ioe.printStackTrace();
}
Limbajul Java operaii I/O (6)
38
Aplicaii propuse
1. S se scrie un program care cere introducerea numelui utilizatorului i afieaz pe ecran
mesajul Hello urmat de numele introdus (afiare-citire-afiare).
2. Citirea unui ntreg pn la introducerea unei valori valide (tratnd excepia
NumberFormatException).
3. S se implementeze un program care citete de la tastatur lungimea unui tablou de tip String
i elementele acestuia (numele studenilor din semigrup). Sortai n ordine alfabetic tabloul
(v. metoda sort a clasei Arrays). Atenie, irurile trebuie transformate dup citire astfel nct
toate literele s fie mici sau toate mari (v. toLowerCase sau toUpperCase din String).
4. Modificai prima aplicaie propus astfel nct s citeasc i vrsta utilizatorului. Dac vrsta
introdus depete 100 s afieze mesajul "Eti btrn!", altfel s afieze "Eti tnr!";
5. S se implementeze un program care citete de la tastatur lungimea unui tablou de valori
ntregi i elementele acestuia. S se sorteze tabloul folosind metoda sort a clasei Arrays. S se
afieze pe ecran tabloul sortat.
6. S se implementeze un program care citete dintr-un fiier ntr-un tablou de tip String numele
studenilor din semigrup. Sortai n ordine alfabetic tabloul (v. metoda sort a clasei Arrays).
Atenie, irurile trebuie transformate dup citire astfel nct toate literele s fie mici sau toate
mari (v. toLowerCase sau toUpperCase din String).
7. S se citeasc dintr-un fiier un tablou de valori ntregi i s se afieze pe ecran media lor
aritmetic. Separarea valorilor de pe linii se va face prin clasa StringTokenizer prezentat
anterior.
8. Studiai clasa RandomAccessFile care, spre deosebire de FileInputStream i FileOutputStream
(acces secvenial), permite citirea respectiv scrierea unei anumite locaii din fiier.
Limbajul Java operaii I/O (7)
39
Java ofer suportul prin numeroase clase pentru
internaionalizarea i naionalizarea aplicaiilor
Clasa Locale
Locale locale = Locale.getDefault();
System.out.println(locale.getCountry()); //RO
System.out.println(locale.getDisplayCountry()); //Romnia
System.out.println(locale.getDisplayCountry(Locale.FRANCE)); //Roumanie
System.out.println(locale.getDisplayLanguage()); //romn
System.out.println(locale.getDisplayLanguage(Locale.FRANCE)); //roumain
System.out.println(locale.getDisplayName()); //romn (Romnia)
System.out.println(locale.getLanguage()); //ro
Locale g = Locale.GERMANY;
System.out.println(g.getLanguage()); //de
Clasa NumberFormat
System.out.println(NumberFormat.getInstance(locale).format(12.3)); //12,3
System.out.println(NumberFormat.getCurrencyInstance(locale).format(6.8)); //6,80 LEI
Clasa DateFormat
Date date = new Date(2009-1900, 8-1, 31); //Y-1900, M-1, D
System.out.println(DateFormat.getDateInstance(0, locale).format(date)); //31 august 2009
System.out.println(DateFormat.getDateInstance(2, locale).format(date)); //31.08.2009
Internaionalizare i naionalizare
40
Limbajul Java crearea claselor (1)
Definiia unei clase trebuie s conin cuvntul cheie class, numele clasei i corpul clasei.
Opional, nainte de cuvntul class pot fi folosii modificatorii public (clasa este vizibil n
toate pachetele), abstract (v. clase abstracte) sau final (clasa nu poate fi derivat).
Exemplu:
class Person {
private String name;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
Clasele pot conine:
Variabile membru;
Constructori;
Metode.
Tipuri de acces: private, protected, public
Variabilele i metodele private pot fi accesate doar n cadrul clasei n care s-au declarat;
Variabilele i metodele protejate pot fi accesate n interiorul clasei, al subclaselor (v. motenirea) sau
n pachetul (package) n care au fost declarate;
Variabilele i metodele publice pot fi accesate oriunde;
Tipul de acces este implicit protejat (dac nu se precizeaz).
Recomandare (ncapsulare, v. cursul POO):
Variabile private;
Set de metode publice care s permit accesarea variabilelor private.
41
Exemplul 1 (un singur pachet)
package person;
public class Person {
private String name;
private String address;
private int age;
private void setName(String name){
this.name = name;
}
private String getName(){
return name;
}
protected void setAddress(String address){
this.address = address;
}
protected String getAddress(){
return address;
}
public void setAge(int age){
this.age = age;
}
int getAge(){
return age;
}
}
Limbajul Java crearea claselor (2)
package person;
public class Main {
public static void main(String[] args) {
Person p = new Person();
p.name = "Popescu"; //Eroare!
p.setName("Popescu"); //Eroare!
p.setAddress("Str. N. Balcescu, Nr. 5");
p.setAge(103);
System.out.println("Numele: " + p.getName()); //Eroare!
System.out.println("Adresa: " + p.getAddress());
System.out.println("Varsta: " + p.getAge());
}
}
42
Limbajul Java crearea claselor (3)
Exemplul 2 (pachete diferite, clasa de baz nepublic)
package person;
class Person {
private String name;
private String address;
private int age;
private void setName(String name){
this.name = name;
}
private String getName(){
return name;
}
protected void setAddress(String address){
this.address = address;
}
protected String getAddress(){
return address;
}
public void setAge(int age){
this.age = age;
}
int getAge(){
return age;
}
}
package main;
import person.Person;
public class Main {
public static void main(String[] args) {
Person p = new Person(); //Eroare!
}
}
43
Limbajul Java crearea claselor (4)
Exemplul 3 (pachete diferite, clasa de baz public)
package person;
public class Person {
private String name;
private String address;
private int age;
private void setName(String name){
this.name = name;
}
private String getName(){
return name;
}
protected void setAddress(String address){
this.address = address;
}
protected String getAddress(){
return address;
}
public void setAge(int age){
this.age = age;
}
int getAge(){
return age;
}
}
package main;
import person.Person;
public class Main {
public static void main(String[] args) {
Person p = new Person();
p.name = "Popescu"; //Eroare!
p.setName("Popescu"); //Eroare!
p.setAddress("Str. N. Balcescu, Nr. 5"); //Eroare!
p.setAge(103);
System.out.println("Numele: " + p.getName()); //Eroare!
System.out.println("Adresa: " + p.getAddress()); //Eroare!
System.out.println("Varsta: " + p.getAge()); //Eroare!
}
}
44
Limbajul Java crearea claselor (5)
Exemplul 4 (o variant corect)
package person;
public class Person {
private String name;
private String address;
private int age;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAddress(String address){
this.address = address;
}
public String getAddress(){
return address;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
}
package person;
public class Main {
public static void main(String[] args) {
Person p = new Person();
p.setName("Popescu");
p.setAddress("Str. N. Balcescu, Nr. 5");
p.setAge(103);
System.out.println("Numele: " + p.getName());
System.out.println("Adresa: " + p.getAddress());
System.out.println("Varsta: " + p.getAge());
}
}
45
Limbajul Java constructori (1)
Este o metod public fr tip (nici void) avnd
acelai nume cu al clasei;
Principalul rol al constructorului este acela de a
iniializa obiectul pentru care s-a apelat;
Dac ntr-o clas nu se declar un constructor, atunci
compilatorul genereaz unul implicit, fr parametri;
ntr-o clas pot coexista mai muli constructori cu
parametri diferii (tip, numr);
La instanierea unui obiect se apeleaz constructorul
corespunztor parametrilor de apel;
n Java nu exist destructori. Sistemul apeleaz
periodic mecanismul garbage collector.
46
Limbajul Java constructori (2)
Exemplu
public class Person {
private String name;
private String address;
private int age;
public Person(String name, String address, int age) {
this.name = name;
this.address = address;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAddress(String address){
this.address = address;
}
public String getAddress(){
return address;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
}
public class Main {
public static void main(String[] args) {
Person p = new Person("Pop", "Sibiu", 103);
System.out.println("Numele: " + p.getName()); //Pop
System.out.println("Adresa: " + p.getAddress()); //Sibiu
System.out.println("Varsta: " + p.getAge()); //103
p.setName("Rus");
p.setAddress("Avrig");
p.setAge(98);
System.out.println("Numele: " + p.getName()); //Rus
System.out.println("Adresa: " + p.getAddress()); //Avrig
System.out.println("Varsta: " + p.getAge()); //98
}
}
47
Unul dintre marile avantaje ale programrii orientate-obiect (POO) const n
reutilizarea codului;
Toate clasele Java, cu excepia interfeelor, sunt subclase ale clasei rdcin
Object;
Procesul prin care o clas nou refolosete o clas veche se numete motenire;
O clas, numit clas derivat, poate moteni variabilele i metodele unei alte
clase, numit clas de baz;
Dac apare aceeai metod cu aceiai parametri att n clasa de baz ct i n
cea derivat (prin redefinire) i se apeleaz metoda instanei clasei derivate, se
execut metoda clasei derivate;
Derivarea unei clase n Java se face prin cuvntul cheie extends urmat de
numele clasei de baz;
O clas declarat final nu poate fi derivat;
Java nu permite motenire multipl: o clas poate deriva o singur clas de
baz. Motenirea multipl este permis doar folosind interfeele (vor fi
prezentate);
Constructorii clasei derivate pot folosi printr-un apel super constructorii clasei
de baz pentru iniializarea variabilelor motenite;
n exemplul prezentat n continuare, clasele Student i Teacher motenesc clasa
Person;
Limbajul Java motenirea (1)
48
Limbajul Java motenirea (2)
Exemplu
public class Person {
private String name;
private String address;
private int age;
public Person(String name, String address, int age) {
this.name = name;
this.address = address;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAddress(String address){
this.address = address;
}
public String getAddress(){
return address;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
}
public class Student extends Person {
private int grade; //medie
public Student(String name, String address, int age, int grade) {
super(name, address, age); //trebuie sa fie prima instructiune!
this.grade = grade;
}
public void setGrade(int grade){
this.grade = grade;
}
public int getGrade(){
return grade;
}
}
public class Teacher extends Person {
private int courses; //nr. cursuri
public Teacher(String name, String address, int age, int courses) {
super(name, address, age); //trebuie sa fie prima instructiune!
this.courses = courses;
}
public void setCourses(int courses){
this.courses = courses;
}
public int getCourses(){
return courses;
}
}
public class Main {
public static void main(String[] args) {
Student s = new Student("Rus", "Avrig", 98, 4);
System.out.println(s.getAge()); //98
}
}
49
Dac un constructor al clasei derivate nu apeleaz prin super un
constructor al clasei de baz, compilatorul va apela implicit
constructorul fr parametri al clasei de baz. Dac ns clasa de baz
are doar constructori cu parametri, compilatorul nu va genera
constructorul implicit. n acest caz, n clasa de baz trebuie declarat i
un constructor fr parametri.
Exemplu:
public class Base {
public Base(){
}
public Base(int p) {
}
}
public class Sub extends Base{
public Sub() {
}
}
Limbajul Java motenirea (3)
50
Suprancrcarea metodelor
public class Base {
public void method(int i) {
System.out.println("Base integer is " + i);
}
public void method(String s){
System.out.println("Base string is " + s);
}
}
public class Sub extends Base {
public void method(int j){
System.out.println("Sub integer is " + j);
}
public static void main(String[] args) {
Base b1 = new Base();
Base b2 = new Sub();
Sub s = new Sub();
b1.method(1); //"Base integer is 1"
b2.method(2); //"Sub integer is 2"
s.method(3); //"Sub integer is 3"
s.method("4"); //"Base string is 4"
}
}
Limbajul Java motenirea (4)
51
Aplicaii
1. S se implementeze o aplicaie care s permit introducerea de la
tastatur a numrului de studeni din semigrup urmat de datele lor
(ntr-un tablou) i a numrului de profesori din acest semestru urmat de
datele lor (ntr-un alt tablou). Cutai i afiai studentul cu media cea
mai mare respectiv profesorul cu cele mai multe cursuri.
2. Definii clasa Employee (angajat) derivat din clasa Person prezentat,
avnd cmpul suplimentar salary. Introducei de la tastatur 5 obiecte
de tip Employee ntr-un tablou. Cutai i afiai angajatul cu salariul cel
mai mare.
3. Definii clasa Product cu cmpul price (pre). Definii clasa Book
(carte) derivat din clasa Product avnd cmpurile suplimentare title,
author i publisher (editor). Introducei de la tastatur 5 obiecte de tip
Book ntr-un tablou. Cutai i afiai cartea cu preul cel mai mic.
4. Definii clasa Book (carte) cu cmpurile title, author i publisher
(editor). Definii clasa LibraryCard (fi de bibliotec) derivat din clasa
Book avnd cmpul suplimentar copies (nr. exemplare). Introducei de
la tastatur 5 obiecte de tip LibraryCard ntr-un tablou. Cutai i afiai
cartea cu numrul cel mai mare de exemplare.
5. Definii clasa Vehicle cu cmpul manufacturer (fabricant). Definii
clasa Car derivat din clasa Vehicle avnd cmpurile suplimentare
model, length (lungime), maxSpeed (vitez maxim), price (pre).
Introducei de la tastatur 5 obiecte de tip Car ntr-un tablou. Cutai i
afiai maina cu preul cel mai mic.
Limbajul Java motenirea (5)
52
Limbajul Java clase abstracte
O clas trebuie declarat abstract dac conine cel puin o metod abstract.
Metodele abstracte sunt declarate fr implementare urmnd ca ele s fie
implementate n clasele derivate. O clas abstract nu poate fi instaniat.
Exemplu:
public abstract class Product {
private double price;
public Product(double price) {
this.price = price;
}
public abstract double computeFinalPrice();
public void setPrice(double price){
this.price = price;
}
public double getPrice(){
return price;
}
}
public class Book extends Product {
public Book(double price) {
super(price);
}
public double computeFinalPrice(){ //TVA=9%
return getPrice() + (9*getPrice())/100;
}
}
public class Car extends Product{
public Car(double price) {
super(price);
}
public double computeFinalPrice(){ //TVA=19%
return getPrice() + (19*getPrice())/100;
}
}
public class Main {
public static void main(String[] args) {
Product p = new Product(10); //Eroare!
Book b = new Book(100);
System.out.println(b.computeFinalPrice());
Car c = new Car(100000);
System.out.println(c.computeFinalPrice());
}
}
53
Interfeele ofer avantajele motenirii multiple, evitnd complicaiile
acesteia.
Toate metodele dintr-o interfa sunt implicit publice i abstracte. O
interfa furnizeaz numele metodelor fr implementarea lor.
Interfeele nu pot fi instaniate.
Clasa care folosete o interfa trebuie s implementeze toate
metodele acesteia.
Se poate deriva o interfa din alte interfee prin acelai mecanism
care a fost prezentat la clase (v. motenirea).
n continuare vor fi prezentate cteva exemple:
O interfa Price folosit de clasele Product, Book i Car.
Folosirea interfeelor Comparator sau Comparable pentru sortarea unui
tablou de obiecte prin metoda sort din clasa Arrays. n cazul interfeei
Comparator trebuie implementat metoda compare.
Interfaa Serializable pentru serializarea obiectelor.
Limbajul Java interfee (1)
54
Limbajul Java interfee (2)
Exemplul 1 (interfaa Price, implementare computeFinalPrice)
public interface Price {
public double computeFinalPrice();
}
public abstract class Product implements Price{
private double price;
public Product(double price) {
this.price = price;
}
public void setPrice(double price){
this.price = price;
}
public double getPrice(){
return price;
}
}
public class Book extends Product {
public Book(double price) {
super(price);
}
public double computeFinalPrice(){ //TVA=9%
return getPrice() + (9*getPrice())/100;
}
}
public class Car extends Product{
public Car(double price) {
super(price);
}
public double computeFinalPrice(){ //TVA=19%
return getPrice() + (19*getPrice())/100;
}
}
public class Main {
public static void main(String[] args) {
Product p = new Product(10); //Eroare!
Book b = new Book(100);
System.out.println(b.computeFinalPrice());
Car c = new Car(100000);
System.out.println(c.computeFinalPrice());
}
}
55
Limbajul Java interfee (3)
Exemplul 2 (interfaa Comparator, implementare compare)
public class Item {
String str;
int num;
Item(String str, int num) {
this.str = str;
this.num = num;
}
}
public class Main {
public static void main(String[] args) {
Item t[] = new Item[5];
t[0] = new Item("c", 2);
t[1] = new Item("a", 1);
t[2] = new Item("e", 4);
t[3] = new Item("b", 5);
t[4] = new Item("d", 3);
//Sortare dupa campul num
java.util.Arrays.sort(t, new Comparator() {
public int compare(Object o1, Object o2) {
//return ((Item)o1).num-((Item)o2).num;
if(((Item)o1).num<((Item)o2).num) return -1;
if(((Item)o1).num>((Item)o2).num) return 1;
return 0;
}
});
//Sortare dupa campul str
java.util.Arrays.sort(t, new Comparator() {
public int compare(Object o1, Object o2) {
return ((Item)o1).str.compareTo(((Item)o2).str);
}
});
}
}
56
Limbajul Java interfee (4)
Exemplul 3 (interfaa Comparator, implementare compare)
public class Item implements Comparator {
String str;
int num;
Item() {}
Item(String str, int num) {
this.str = str;
this.num = num;
}
public int compare(Object o1, Object o2) {
return ((Item)o1).num-((Item)o2).num;
}
}
public class Main {
public static void main(String[] args) {
Item t[] = new Item[5];
t[0] = new Item("c", 2);
t[1] = new Item("a", 1);
t[2] = new Item("e", 4);
t[3] = new Item("b", 5);
t[4] = new Item("d", 3);
//Sortare dupa campul num
java.util.Arrays.sort(t, new Item());
//Afisare
for (int i=0; i<t.length; i++)
System.out.println(t[i].str + " - " + t[i].num);
//Sortare dupa campul str
java.util.Arrays.sort(t, new Comparator() {
public int compare(Object o1, Object o2) {
return ((Item)o1).str.compareTo(((Item)o2).str);
}
});
//Afisare
for (int i=0; i<t.length; i++)
System.out.println(t[i].str + " - " + t[i].num);
}
}
57
Limbajul Java interfee (5)
Exemplul 4 (interfaa Comparable, implementare compareTo)
public class Item implements Comparable {
String str;
int num;
Item(String str, int num) {
this.str = str;
this.num = num;
}
public int compareTo(Object o) {
return num-((Item)o).num;
//return str.compareTo(((Item)o).str);
}
}
public class Main {
public static void main(String[] args) {
Item t[] = new Item[5];
t[0] = new Item("c", 2);
t[1] = new Item("a", 1);
t[2] = new Item("e", 4);
t[3] = new Item("b", 5);
t[4] = new Item("d", 3);
//Sortare dupa campul num
java.util.Arrays.sort(t);
//Afisare
for (int i=0; i<t.length; i++)
System.out.println(t[i].str + " - " + t[i].num);
//Sortare dupa campul str
java.util.Arrays.sort(t, new Comparator() {
public int compare(Object o1, Object o2) {
return ((Item)o1).str.compareTo(((Item)o2).str);
}
});
//Afisare
for (int i=0; i<t.length; i++)
System.out.println(t[i].str + " - " + t[i].num);
}
}
58
Limbajul Java interfee (6)
Exemplul 5 (interfaa Serializable permite serializarea obiectelor)
public class Item implements Serializable {
String str;
int num;
Item(String str, int num) {
this.str = str;
this.num = num;
}
}
public class Main {
public static void main(String[] args) {
FileOutputStream fos = null;
FileInputStream fis = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try{
fos = new FileOutputStream("data.txt");
fis = new FileInputStream("data.txt");
}
catch(FileNotFoundException e){
e.printStackTrace();
}
try{
oos = new ObjectOutputStream(fos);
ois = new ObjectInputStream(fis);
}
catch(IOException e){
e.printStackTrace();
}
try{
oos.writeObject(new Item("c", 2)); //Scrierea obiectului in fisier
oos.close(); fos.close();
}
catch(IOException e){
e.printStackTrace();
}
try{
Item item=(Item)ois.readObject(); //Citirea obiectului din fisier
System.out.println(item.str + " - " + item.num);
ois.close(); fis.close();
}
catch(IOException e){
e.printStackTrace();
}
catch(ClassNotFoundException e){
e.printStackTrace();
}
}
}
59
Aplicaii
1. Definii clasa Person cu cmpurile name, address i age. Definii clasa Student
derivat din clasa Person avnd cmpul suplimentar grade (medie). Introducei
dintr-un fiier student.txt numrul de studeni din semigrup urmat de datele lor,
ntr-un tablou. Sortai i afiai studenii n ordinea cresctoare a mediei.
2. Definii clasa Person cu cmpurile name, address i age. Definii clasa Teacher
derivat din clasa Person avnd cmpul suplimentar courses (nr. cursuri).
Introducei dintr-un fiier teacher.txt numrul de profesori din acest semestru
urmat de datele lor, ntr-un tablou. Sortai i afiai profesorii n ordinea cresctoare
a numrului de cursuri predate.
3. Definii clasa Person cu cmpurile name, address i age. Definii clasa
Employee (angajat) derivat din clasa Person avnd cmpul suplimentar salary
(salariu). Introducei dintr-un fiier employee.txt numrul de angajai urmat de
datele lor, ntr-un tablou. Sortai i afiai angajaii n ordinea cresctoare a
salariilor.
4. Definii clasa Product cu cmpul price (pre). Definii clasa Book (carte) derivat
din clasa Product avnd cmpurile suplimentare title, author i publisher
(editor). Introducei dintr-un fiier book.txt numrul de cri urmat de datele lor,
ntr-un tablou. Sortai i afiai crile n ordinea cresctoare a preului.
5. Definii clasa Book (carte) cu cmpurile title, author i publisher (editor).
Definii clasa LibraryCard (fi de bibliotec) derivat din clasa Book avnd
cmpul suplimentar copies (nr. exemplare). Introducei dintr-un fiier
librarycard.txt numrul de fie urmat de datele acestora, ntr-un tablou. Sortai i
afiai crile n ordinea cresctoare a numrului de exemplare disponibile.
6. Definii clasa Vehicle cu cmpul manufacturer (fabricant). Definii clasa Car
derivat din clasa Vehicle avnd cmpurile suplimentare model, length
(lungime), maxSpeed (vitez maxim), price (pre). Introducei dintr-un fiier
car.txt numrul de maini, urmat de datele lor, ntr-un tablou. Sortai i afiai
mainile n ordinea cresctoare a preului.
Limbajul Java interfee (7)
60
Limbajul Java partajarea datelor (1)
Partajarea datelor de ctre obiectele unei clase poate fi realizat prin intermediul membrilor
statici ai clasei respective.
n timp ce variabilele obinuite (non-statice) aparin instanelor clasei (obiectelor),
variabilele declarate statice aparin clasei i sunt partajate de ctre toate obiectele acesteia.
Unei variabile statice i se aloc memorie o singur dat, la prima instaniere a clasei. La
urmtoarele instanieri ale clasei variabilei statice nu i se mai aloc memorie, dar toate
obiectele clasei pot accesa aceeai variabil static, alocat la prima instaniere.
Metodele statice pot fi apelate fr instanierea clasei.
Metodele statice nu pot utiliza variabile i metode non-statice.
Un exemplu de utilizare a unei variabile statice este contorizarea obiectelor instaniate
dintr-o clas:
public class Person {
private String name;
static int counter;
public Person(String name) {
this.name = name;
counter++;
System.out.println(counter + " persoane.");
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person("Popescu"); //"1 persoane."
Person p2 = new Person("Ionescu"); //"2 persoane."
}
}
61
Exemple de folosire a metodelor statice:
public class Person {
private String name;
private int age;
static int counter;
public Person(String name, int age) {
this.name = name;
this.age = age;
increaseCounter();
}
public static void increaseCounter(){
counter++;
System.out.println(counter + " persoane.");
}
public static void increaseAge(){
age++; //Eroare!
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
}
Limbajul Java partajarea datelor (2)
public class Main {
public static void main(String[] args) {
Person p1 = new Person("Popescu", 61); //"1 persoane."
Person p2 = new Person("Ionescu", 72); //"2 persoane."
Person.increaseCounter() ; //"3 persoane."
p1 = new Person("Petrescu", 53); //"4 persoane."
}
}
62
Alte exemple de folosire a variabilelor i metodelor statice:
public class Person {
private String name;
private int age;
static int counter;
public Person(String name, int age) {
this.name = name;
this.age = age;
increaseCounter();
}
public static void increaseCounter(){
counter++;
System.out.println(counter + " persoane.");
}
public void printCounter(){
System.out.println(counter);
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
Limbajul Java partajarea datelor (3)
public static void main(String[] args) {
Person p1 = new Person("Popescu", 61); //"1 persoane."
Person p2 = new Person("Ionescu", 72); //"2 persoane."
Person.increaseCounter() ; //"3 persoane."
p1 = new Person("Petrescu", 53); //"4 persoane.
printCounter(); //Eroare!
p2.printCounter(); //4
}
}
63
Limbajul Java atribuire vs. clonare (1)
Folosirea operatorului de atribuire
n cazul obiectelor operatorul de atribuire determin atribuirea referinelor (adreselor)
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person("Pop", 61);
Person p2 = p1;
System.out.println(p1.getName() + ", " + p1.getAge()); //"Pop, 61"
System.out.println(p2.getName() + ", " + p2.getAge()); //"Pop, 61"
p1.setAge(p1.getAge() + 1);
System.out.println(p1.getName() + ", " + p1.getAge()); //"Pop, 62"
System.out.println(p2.getName() + ", " + p2.getAge()); //"Pop, 62"
p2.setName("Rus");
System.out.println(p1.getName() + ", " + p1.getAge()); //"Rus, 62"
System.out.println(p2.getName() + ", " + p2.getAge()); //"Rus, 62"
p1 = new Person("Lup", 53);
System.out.println(p1.getName() + ", " + p1.getAge()); //"Lup, 53"
System.out.println(p2.getName() + ", " + p2.getAge()); //"Rus, 62"
p1.setAge(p1.getAge() + 1);
System.out.println(p1.getName() + ", " + p1.getAge()); //"Lup, 54"
System.out.println(p2.getName() + ", " + p2.getAge()); //"Rus, 62"
}
}
64
Limbajul Java atribuire vs. clonare (2)
Clonarea obiectelor
public class Person implements Cloneable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Object clone() { //protected in Object
Object obj = null;
try {
obj = super.clone();
}
catch (CloneNotSupportedException ex) {
}
return obj;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person("Pop", 61);
Person p2 = (Person)p1.clone();
System.out.println(p1.getName() + ", " + p1.getAge()); //"Pop, 61"
System.out.println(p2.getName() + ", " + p2.getAge()); //"Pop, 61"
p1.setAge(p1.getAge() + 1);
System.out.println(p1.getName() + ", " + p1.getAge()); //"Pop, 62"
System.out.println(p2.getName() + ", " + p2.getAge()); //"Pop, 61"
p2.setName("Rus");
System.out.println(p1.getName() + ", " + p1.getAge()); //"Pop, 62"
System.out.println(p2.getName() + ", " + p2.getAge()); //"Rus, 61"
}
}
65
Limbajul Java interfa grafic (1)
O component foarte important a aplicaiilor
moderne este interfaa grafic prin care
acestea comunic cu utilizatorul: se citesc
datele i se afieaz rezultatele.
Mediile de dezvoltare Java ofer numeroase
pachete cu diverse componente vizuale.
n urmtoarea aplicaie vom folosi
componente din pachetul AWT (Advanced
Windowing Toolkit) pentru citirea studenilor
ntr-o list
Fereastra neredimensionabil a aplicaiei este
prezentat pe pagina urmtoare.
66
Numele studentului se introduce printr-un TextField;
Acionarea butonului Add determin adugarea textului din
TextField n componenta List respectiv tergerea din TextField;
Adugarea n componenta List determin apariia unui scroll
atunci cnd numrul de linii introduse trece de limita de
vizualizare.
Limbajul Java interfa grafic (2)
Fereastra aplicaiei
67
Codul surs al aplicaiei
public class StudentFrame extends Frame {
private List studentList = new List();
private TextField studentTextField = new TextField();
private Button addButton = new Button();
public StudentFrame() {
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
show();
}
public static void main(String[] args) {
StudentFrame studentFrame = new StudentFrame();
}
private void jbInit() throws Exception {
this.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(WindowEvent e) {
this_windowClosing(e);
}
});
studentList.setBounds(new Rectangle(210, 60, 160, 140));
studentTextField.setBounds(new Rectangle(25, 60, 160, 30));
addButton.setLabel("Add");
addButton.setBounds(new Rectangle(70, 120, 80, 25));
Limbajul Java interfa grafic (3)
addButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
addButton_actionPerformed(e);
}
});
this.setSize(400, 220);
this.setResizable(false);
this.setLayout(null); //componentele pot fi asezate cu mouse-ul
this.setTitle("Students");
this.setBackground(new Color(240, 240, 240));
this.add(addButton, null);
this.add(studentTextField, null);
this.add(studentList, null);
}
void this_windowClosing(WindowEvent e) {
System.exit(0); //inchiderea aplicatiei
}
void addButton_actionPerformed(ActionEvent e) {
studentList.add(studentTextField.getText());
studentTextField.setText(""); //stergere
}
}
68
Limbajul Java interfa grafic (4)
Tratarea evenimentelor
Evenimentele sunt generate de aciunile utilizatorului asupra
componentelor interfeei grafice.
Pentru tratarea unui anumit eveniment ntr-o clas, trebuie
implementat interfaa Listener corespunztoare care s prelucreze
evenimentul respectiv. De exemplu, pentru tratarea evenimentelor
ActionEvent, se implementeaz interfaa ActionListener.
Astfel, evenimentele sunt recepionate de obiecte de tip Listener care
apeleaz metode de tratare a evenimentelor.
Aplicaia anterioar trateaz evenimentele de nchidere a ferestrei i de
click pe butonul Add.
n continuare vom extinde aplicaia astfel nct s rspund la
apsarea tastei ENTER, tratnd evenimentul KeyEvent. Pentru asta se
poate folosi interfaa KeyListener implementnd toate metodele
(keyPressed, keyReleased, keyTyped) sau clasa abstract KeyAdapter
care ne permite s implementm doar metodele necesare (n cazul
nostru keyPressed).
69
public class StudentFrame extends Frame {
private List studentList = new List();
private TextField studentTextField = new TextField();
private Button addButton = new Button();
public StudentFrame() {
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
show();
studentTextField.requestFocus();
}
public static void main(String[] args) {
StudentFrame studentFrame = new StudentFrame();
}
private void jbInit() throws Exception {
this.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(WindowEvent e) {
this_windowClosing(e);
}
});
studentList.setBounds(new Rectangle(210, 60, 160, 140));
studentTextField.setBounds(new Rectangle(25, 60, 160, 30));
studentTextField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(KeyEvent e) {
studentTextField_keyPressed(e);
}
});
addButton.setLabel("Add");
addButton.setBounds(new Rectangle(70, 120, 80, 25));
Limbajul Java interfa grafic (5)
addButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
addButton_actionPerformed(e);
}
});
this.setSize(400, 220);
this.setResizable(false);
this.setLayout(null); //componentele pot fi asezate cu mouse-ul
this.setTitle("Students");
this.setBackground(new Color(240, 240, 240));
this.add(addButton, null);
this.add(studentTextField, null);
this.add(studentList, null);
}
void this_windowClosing(WindowEvent e) {
System.exit(0); //inchiderea aplicatiei
}
void addButton_actionPerformed(ActionEvent e) {
studentList.add(studentTextField.getText());
studentTextField.setText(""); //stergere
studentTextField.requestFocus();
}
void studentTextField_keyPressed(KeyEvent e) {
if(e.getKeyCode()==e.VK_ENTER)
addButton_actionPerformed(new ActionEvent(this, 0, null));
}
}
70
Layout manager
(aranjarea componentelor)
Toate obiectele grafice de tip container (Frame,
Panel, etc.) au o proprietate layout prin care se
specific cum s fie aezate i dimensionate
componentele: null, XYLayout, BorderLayout,
FlowLayout, GridLayout, GridBagLayout, etc.
Un layout null (folosit i n aplicaia prezentat) sau
XYLayout pstreaz poziiile i dimensiunile originale
ale componentelor. Se pot folosi n cazul
containerelor neredimensionabile.
BorderLayout, FlowLayout, GridLayout i
GridBagLayout repoziioneaz i/sau rescaleaz
obiectele n cazul redimensionrii containerului.
Limbajul Java interfa grafic (6)
71
BorderLayout permite aranjarea componentelor din
container n 5 zone: nord, sud, est, vest i centru.
Componentele din nord i sud i pstreaz nlimea
original i sunt scalate la limea containerului.
Componentele din est i vest i pstreaz limea original
i sunt scalate vertical astfel nct s acopere spaiul dintre
nord i sud. Componenta din centru se expandeaz pentru
acoperirea ntreg spaiului rmas.
Constructori:
BorderLayout() fr distan ntre componente;
BorderLayout(int hgap, int vgap) primete ca parametri
distanele orizontale i verticale dintre componente.
Limbajul Java interfa grafic (7)
public class BorderFrame extends Frame {
private BorderLayout bLayout = new BorderLayout();
private Button northButton = new Button("North Button");
private Button southButton = new Button("South Button");
private Button westButton = new Button("West Button");
private Button eastButton = new Button("East Button");
private Button centerButton = new Button("Center Button");
public BorderFrame() {
this.setSize(400, 220);
this.setTitle("BorderLayout");
this.setLayout(bLayout);
this.setBackground(new Color(240, 240, 240));
this.add(northButton, BorderLayout.NORTH);
this.add(southButton, BorderLayout.SOUTH);
this.add(westButton, BorderLayout.WEST);
this.add(eastButton, BorderLayout.EAST);
this.add(centerButton, BorderLayout.CENTER);
this.show();
}
public static void main(String[] args) {
new BorderFrame();
}
}
72
public class FlowFrame extends Frame {
private FlowLayout fLayout = new FlowLayout();
private Button firstButton = new Button("First Button");
private Button secondButton = new Button("Second Button");
private Button thirdButton = new Button("Third Button");
private Button fourthButton = new Button("Fourth Button");
private Button fifthButton = new Button("Fifth Button");
private Button lastButton = new Button("Last Button");
public FlowFrame() {
this.setSize(400, 220);
this.setTitle("FlowLayout");
this.setLayout(fLayout);
this.setBackground(new Color(240, 240, 240));
this.add(firstButton);
this.add(secondButton);
this.add(thirdButton);
this.add(fourthButton);
this.add(fifthButton);
this.add(lastButton);
this.show();
}
public static void main(String[] args) {
new FlowFrame();
}
}
FlowLayout aranjeaz componentele pe linii pstrnd
dimensiunile. Aliniaz componentele care ncap ntr-o linie
i dac e nevoie continu pe linia urmtoare. Se folosete
de obicei pentru aranjarea butoanelor ntr-un Panel.
Constructori:
FlowLayout() aliniere centrat i distan implicit de 5
ntre componente att pe orizontal ct i pe vertical;
FlowLayout(int align) primete ca parametru tipul de
aliniere (LEFT, RIGHT, CENTER din FlowLayout), distana
dintre componente fiind implicit 5;
FlowLayout(int align, int hgap, int vgap) primete ca
parametri tipul de aliniere (LEFT, RIGHT, CENTER din
FlowLayout) i distanele orizontale i verticale dintre
componente.
Limbajul Java interfa grafic (8)
73
GridLayout mparte containerul n linii i coloane i
pstreaz componentele n celulele astfel obinute. Toate
celulele au aceeai dimensiune. Fiecare component este
expandat la dimensiunea celulei. n cazul unor interfee
complexe, se pot introduce n celule containere Panel cu
subcomponente aranjate tot prin GridLayout. Pentru
obinerea unor spaii libere se pot introduce componente
Panel goale n celulele corespunztoare.
Constructori:
GridLayout() creeaz o singur linie cu cte o coloan
pentru fiecare component adugat, fr distan ntre
componente;
GridLayout(int rows, int cols) primete ca parametri
numrul de linii i coloane;
GridLayout(int rows, int cols, int hgap, int vgap)
primete ca parametri numrul de linii i coloane
respectiv distanele orizontale i verticale dintre
componente.
Limbajul Java interfa grafic (9)
public class GridFrame extends Frame {
private GridLayout gLayout = new GridLayout(2, 3, 50, 100);
private Button firstButton = new Button("First Button");
private Button secondButton = new Button("Second Button");
private Button thirdButton = new Button("Third Button");
private Button fourthButton = new Button("Fourth Button");
private Button fifthButton = new Button("Fifth Button");
private Panel emptyPanel = new Panel();
public GridFrame() {
this.setSize(400, 220);
this.setTitle("GridLayout");
this.setLayout(gLayout);
this.setBackground(new Color(240, 240, 240));
this.add(firstButton);
this.add(secondButton);
this.add(thirdButton);
this.add(fourthButton);
this.add(emptyPanel);
this.add(fifthButton);
show();
}
public static void main(String[] args) {
new GridFrame();
}
}
74
GridBagLayout mparte containerul n celule care
pot avea dimensiuni diferite. O component poate
ocupa mai multe celule. Exemplu:
Alinierea componentelor:
First Button:
gridy = 0, gridx = 0 (celula [0,0])
gridwidth = 2, gridheight = 1 (dou coloane, o linie)
weightx = 0.6 (0.6 din extraspaiul orizontal)
weighty = 0.0 (0.0 din extraspaiul vertical)
Second Button:
gridy = 0, gridx = 2 (celula [0,2])
gridwidth = 2, gridheight = 1 (dou coloane, o linie)
weightx = 0.3 (0.3 din extraspaiul orizontal)
weighty = 0.0 (0.0 din extraspaiul vertical)
Third Button:
gridy = 1, gridx = 0 (celula [1,0])
gridwidth = 4, gridheight = 1 (patru coloane, o linie)
weightx = 0.0 (0.0 din extraspaiul orizontal)
weighty = 0.3 (0.3 din extraspaiul vertical)
Fourth Button:
gridy = 2, gridx = 0 (celula [2,0])
gridwidth = 1, gridheight = 3 (o coloan, trei linii)
weightx = 0.0 (0.0 din extraspaiul orizontal)
weighty = 0.3 (0.3 din extraspaiul vertical)
Fifth Button:
gridy = 2, gridx = 1 (celula [2,1])
gridwidth = 3, gridheight = 2 (trei coloane, dou linii)
weightx = 0.6 (0.6 din extraspaiul orizontal)
weighty = 0.6 (0.6 din extraspaiul vertical)
Last Button:
gridy = 4, gridx = 1 (celula [4,1])
gridwidth = 3, gridheight = 1 (trei coloane, o linie)
weightx = 0.6 (0.6 din extraspaiul orizontal)
weighty = 0.3 (0.3 din extraspaiul vertical)
Limbajul Java interfa grafic (10)
First Button [0,0] Second Button [0,2]
Third Button [1,0]
Fifth Button [2,1]
Last Button [4,1]
Fourth
Button
[2,0]
75
Limbajul Java interfa grafic (11)
GridBagLayout codul surs
public class GridBagFrame extends Frame {
private GridBagLayout gbLayout = new GridBagLayout();
private GridBagConstraints gbc = new GridBagConstraints();
private Button firstButton = new Button("First Button");
private Button secondButton = new Button("Second Button");
private Button thirdButton = new Button("Third Button");
private Button fourthButton = new Button("Fourth Button");
private Button fifthButton = new Button("Fifth Button");
private Button lastButton = new Button("Last Button");
public GridBagFrame() {
this.setSize(400, 220);
this.setTitle("GridBagLayout");
this.setLayout(gbLayout);
this.setBackground(new Color(240, 240, 240));
gbc.fill = GridBagConstraints.BOTH; //directii de extindere
gbc.insets = new Insets(5, 5, 5, 5); //dist. fata de marginile celulei
gbc.gridy = 0; //linia 0
gbc.gridx = 0; //coloana 0
gbc.gridwidth = 2; //ocupa doua coloane
gbc.weightx = 0.6; //0.6 din extraspatiul orizontal
gbLayout.setConstraints(firstButton, gbc);
this.add(firstButton);
gbc.gridy = 0; //linia 0
gbc.gridx = 2; //coloana 2
gbc.weightx = 0.3; //0.3 din extraspatiul orizontal
gbLayout.setConstraints(secondButton, gbc);
this.add(secondButton);
gbc.gridy = 1; //linia 1
gbc.gridx = 0; //coloana 0
gbc.gridwidth = 4; //ocupa 4 coloane
gbc.weightx = 0.0; //resetare
gbc.weighty = 0.3; //0.3 din extraspatiul vertical
gbLayout.setConstraints(thirdButton, gbc);
this.add(thirdButton);
gbc.gridy = 2; //linia 2
gbc.gridx = 0; //coloana 0
gbc.gridwidth = 1; //resetare
gbc.gridheight = 3; //ocupa trei linii
gbLayout.setConstraints(fourthButton, gbc);
this.add(fourthButton);
gbc.gridy = 2; //linia 2
gbc.gridx = 1; //coloana 1
gbc.gridwidth = 3; //ocupa trei coloane
gbc.gridheight = 2; //ocupa doua linii
gbc.weighty = 0.6; //0.6 din extraspatiul vertical
gbc.weightx = 0.6; //0.6 din extraspatiul orizontal
gbLayout.setConstraints(fifthButton, gbc);
this.add(fifthButton);
gbc.gridy = 4; //linia 4
gbc.gridx = 1; //coloana 1
gbc.gridheight = 1; //resetare
gbc.weighty = 0.3; //0.3 din extraspatiul vertical
gbLayout.setConstraints(lastButton, gbc);
this.add(lastButton);
show();
}
public static void main(String[] args) {
new GridBagFrame();
}
}
76
Crearea tabelelor
O clas care permite crearea tabelelor este JTable;
Gestionarea componentelor JTable se poate face prin clasa
DefaultTableModel;
Pentru o funcionare corect cu scroll, obiectul JTable trebuie
adugat pe un JScrollPane i nu pe ScrollPane!
Aplicaia urmtoare folosete dou tabele, unul prencrcat, iar
cellalt cu ncrcare dinamic a datelor:
Limbajul Java interfa grafic (12)
77
Codul surs al aplicaiei cu tabele
public class TableFrame extends Frame {
private GridLayout gLayout = new GridLayout(1, 2, 10, 10);
private JScrollPane leftScrollPane = new JScrollPane();
private JScrollPane rightScrollPane = new JScrollPane();
private String leftTableColumns[] = {"Name", "Age"}; //header
private Object leftTableData[][] = {{"Popescu", "103"}, {"Ionescu", "98"}}; //continut
private JTable leftTable = new JTable(leftTableData, leftTableColumns); //tabel cu date preincarcate
private JTable rightTable = new JTable(); //tabel gol
private String rightTableColumns[] = {"Column 1", "Column 2"}; //header
private DefaultTableModel rightTableModel = new DefaultTableModel(rightTableColumns, 0);
public TableFrame() {
this.setSize(400, 150);
this.setLayout(gLayout);
this.setTitle("Tables");
this.setBackground(new Color(240, 240, 240));
this.add(leftScrollPane);
this.add(rightScrollPane);
leftScrollPane.getViewport().add(leftTable, null);
rightScrollPane.getViewport().add(rightTable, null);
rightTable.setModel(rightTableModel);
for(int i=1; i<=10; i++){
String row[] = {"Row" + i + ", Col 1", "Row" + i + ", Col 2"};
rightTableModel.addRow(row);
}
show();
}
public static void main(String[] args) {
new TableFrame();
}
}
Limbajul Java interfa grafic (13)
78
Aplicaii
1. Introducei n fereastra aplicaiei care gestioneaz lista de
studeni un buton Clear care s permit tergerea coninutului
listei. tergerea coninutului componentei List (din pachetul
AWT) se poate face prin metodele clear sau removeAll.
2. Modificai funcia de adugare n list astfel nct aceasta s
pstreze lista sortat la introducerea unui nou student. Preluarea
coninutului componentei List (din AWT) ntr-un tablou de tip
String se poate efectua prin metoda getItems, iar preluarea liniei
de pe o anumit poziie se poate face prin metoda getItem cu un
parametru de tip int, reprezentnd poziia n list. Inserarea pe o
poziie n list se poate efectua prin metoda add cu un
parametru String i unul de tip int, reprezentnd poziia. De
asemenea, getItemCount returneaz numrul de linii din list.
3. nlocuii lista din aplicaia prezentat cu un tabel.
4. Dezvoltai aplicaia astfel nct, pe lng nume, s se introduc
n tabel adresa, vrsta i media studentului.
5. Rearanjai componentele pe fereastr prin GridLayout sau
GridBagLayout i setai fereastra redimensionabil.
Limbajul Java interfa grafic (14)
79
Limbajul Java fire de execuie (1)
Un fir de execuie (thread) este o secven de instruciuni executat de un
program.
Firul de execuie primar este metoda main i atunci cnd acesta se termin, se
ncheie i programul.
Un program poate utiliza fire multiple care sunt executate concurenial.
Utilizarea firelor multiple este util n cazul programelor complexe care
efectueaz seturi de activiti multiple.
Fiecare fir de execuie are o prioritate care poate lua valori de la 1 (prioritate
mic) la 10 (prioritate maxim). Firele cu prioritate mare sunt avantajate la
comutare, ele primesc mai des controlul procesorului.
Pentru implementarea unui fir de execuie n Java, se poate extinde clasa
Thread. Deoarece Java nu accept motenirea multipl, n cazul n care a fost
deja extins o clas, pentru crearea unui fir de execuie trebuie implementat
interfaa Runnable. Indiferent de metoda utilizat, se suprascrie metoda run
care trebuie s conin instruciunile firului.
Aplicaia urmtoare pornete dou fire de execuie: unul pentru afiarea
numerelor i cellalt pentru afiarea literelor. Pentru a observa diferenele dintre
cele dou metode de implementare, firul de execuie Numbers extinde clasa
Thread, n timp ce Letters implementeaz interfaa Runnable.
80
Afiare concurenial de numere i litere:
public class Numbers extends Thread { //extinde clasa Thread
public void run(){
for(int i=0; i<1000; i++){
System.out.println(i);
}
}
}
public class Letters implements Runnable { //implementeaza interfata Runnable
char a = 'a';
public void run(){
for(int i=0; i<1000; i++){
int c = a + i%26;
System.out.println((char)c);
}
}
}
public class Main {
public static void main(String[] args) {
Numbers numbers = new Numbers();
Thread letters = new Thread(new Letters());
letters.start();
numbers.start();
}
}
Limbajul Java fire de execuie (2)
81
Principalele operaii care pot fi efectuate dup
crearea unui fir de execuie:
start pornete firul de execuie
setPriority seteaz prioritatea firului de execuie (valoare
ntre 1 i 10)
getPriority returneaz prioritatea firului de execuie
(valoare ntre 1 i 10)
sleep suspend execuia unui fir pentru o perioad
precizat n milisecunde.
yield suspend temporar execuia firului curent n
favoarea altor fire de execuie.
Se recomand oprirea firului prin ncheierea execuiei
metodei run.
Urmtoarea aplicaie folosete un fir de execuie
pentru deplasarea unei mingi pe orizontal.
Limbajul Java fire de execuie (3)
82
public class Ball extends Thread {
private int px = 0; //pozitia x
private int py = 0; //pozitia y
private int size = 0;
private Color color = null;
private MyFrame parent = null;
public Ball(MyFrame parent, int px, int py, int size, Color color) {
this.parent = parent; //referinta la fereastra
this.px = px;
this.py = py;
this.size = size;
this.color = color;
}
public int getPX(){
return px;
}
public int getPY(){
return py;
}
public int getSize(){
return size;
}
public Color getColor(){
return color;
}
public void run(){
while(px < parent.getSize().width){ //iesire din fereastra
px++;
parent.paint();
}
}
}
Limbajul Java fire de execuie (4)
83
public class MyFrame extends Frame {
Ball ball = null;
Image buffer = null;
public MyFrame() {
this.setSize(new Dimension(400, 300));
this.setTitle("Balls");
this.addWindowListener(new java.awt.event.WindowAdapter() { //detectia evenimentului de inchidere a ferestrei
public void windowClosing(WindowEvent e) {
this_windowClosing(e);
}
});
setVisible(true);
buffer = createImage(getSize().width, getSize().height);
ball = new Ball(this, 20, 50, 20, Color.red);
ball.start();
}
void paint(){
Graphics gbuffer = buffer.getGraphics();
//se deseneaza mai intai in buffer (tehnica Double Buffering)
gbuffer.setColor(Color.white);
gbuffer.fillRect(0, 0, getSize().width, getSize().height);
gbuffer.setColor(ball.getColor());
gbuffer.fillOval(ball.getPX(), ball.getPY(), ball.getSize(), ball.getSize());
paint(gbuffer);
//se copiaza imaginea din buffer pe fereastra (tehnica Double Buffering)
Graphics g = getGraphics();
g.drawImage(buffer, 0, 0, getSize().width, getSize().height, 0, 0, getSize().width, getSize().height, this);
}
void this_windowClosing(WindowEvent e) { //evenimentul de inchidere a ferestrei
System.exit(0);
}
public static void main(String[] args){
new MyFrame();
}
}
Limbajul Java fire de execuie (5)
84
Sincronizarea firelor de execuie
Dac n cadrul unui program Java exist un fir de
execuie care creeaz (produce) date i un al doilea
fir de execuie care le prelucreaz (consum), de
regul se declar un bloc synchronized, ceea ce
permite ca un singur fir s aib acces la resurse
(metode, date) la un moment dat.
Atunci cnd un fir de execuie apeleaz wait n cadrul
unui bloc de cod synchronized, alt fir poate accesa
codul.
Iar atunci cnd un fir de execuie ncheie procesarea
codului synchronized, el apeleaz metoda notify
pentru a anuna alte fire de execuie s nceteze
ateptarea.
Relum n continuare aplicaia care afieaz numere
i litere sincroniznd cele dou fire de execuie.
Limbajul Java fire de execuie (6)
85
public class Numbers extends Thread {
Main m;
public Numbers(Main m){
this.m = m;
}
public void run(){
m.numbers();
}
}
public class Letters implements Runnable {
Main m;
public Letters(Main m){
this.m = m;
}
public void run(){
m.letters();
}
}
public class Main {
public Main(){
Numbers numbers = new Numbers(this);
Thread letters = new Thread(new Letters(this));
letters.start();
numbers.start();
}
Limbajul Java fire de execuie (7)
public synchronized void numbers(){
for(int i=0; i<1000; i++){
if(i%26==0){
try {
this.notify();
this.wait();
}
catch (InterruptedException ex) { }
}
System.out.println(i);
}
this.notify();
}
public synchronized void letters(){
char a = 'a';
for(int i=0; i<1000; i++){
if(i%26==0){
try {
this.notify();
this.wait();
}
catch (InterruptedException ex) { }
}
int c = a + i%26;
System.out.println((char)c);
}
this.notify();
}
public static void main(String[] args) {
new Main();
}
}
86
Aplicaii propuse:
1. Introducerea unei ntrzieri de 10 ms n algoritmul de micare a bilei din aplicaia prezentat.
2. Modificarea aplicaiei astfel nct s permit pornirea mai multor mingi simultan.
3. S se nlocuiasc algoritmul de deplasare a mingii pe orizontal cu urmtorul algoritm de micare:
dx = 1;
dy = 1;
while (true){
px += dx;
py += dy;
if((px <= 0) || (px >= frame_width))
dx = -dx;
if((py <= 0) || (py >= frame_height))
dy = -dy;
paint();
}
Un alt algoritm de micare:
gravy = 1;
speed = -30
speedy = -30;
speedx = 0;
while(true){
speedy += gravy;
py += speedy;
px += speedx;
if(py > frameheight){
speedy = speed;
speed += 3;
}
if(speed == 0) break;
paint();
}
Limbajul Java fire de execuie (8)
87
O colecie grupeaz date ntr-un singur obiect i permite manipularea acestora.
Clasele Vector i ArrayList
Permit implementarea listelor redimensionabile cu elemente referin de orice
tip, inclusiv null.
O diferen important: Vector este sincronizat, iar ArrayList este nesincronizat,
ceea ce-l face mai rapid. Dac un ArrayList este accesat i modificat de mai
multe fire de execuie concurenial, necesit sincronizare extern (a obiectului
care ncapsuleaz lista). O alt soluie const n crearea unei instane
sincronizate, prevenind astfel eventualele accese nesincronizate:
List list = Collections.synchronizedList(new ArrayList(...));
Clasa Vector s-a pstrat pentru compatibilitate cu versiuni JDK mai vechi de 1.2.
Exemple
Vector vector = new Vector(); //vector gol
vector.addElement(new Integer(1)); //vector = {1}
vector.add(new Integer(3)); //vector = {1, 3}
vector.insertElementAt(new Integer(5), 1); //vector = {1, 5, 3}
vector.setElementAt(new Integer(2), 1); //vector = {1, 2, 3}
ArrayList list = new ArrayList(); //lista goala
list.add(new Integer(1)); //list = {1}
list.add(new Integer(3)); //list = {1, 3}
list.add(1, new Integer(5)); //list = {1, 5, 3}
list.set(1, new Integer(2)); //list = {1, 2, 3}
Limbajul Java colecii (1)
88
Clasa Stack
Permite implementarea sincronizat a stivelor
Extinde clasa Vector cu operaiile specifice stivei:
push introduce un element n vrful stivei;
pop scoate elementul din vrful stivei;
peek preia (citete) elementul din vrful stivei, fr s-l scoat;
empty verific dac stiva e goal;
search returneaz poziia unui obiect din stiv fa de vrf.
Exemple:
Stack stack = new Stack(); //stiva goala
System.out.println(stack.empty()); //true
stack.push(new Integer(1)); //stack = {1}
stack.push(new Integer(2)); //stack = {1, 2}
stack.push(new Integer(3)); //stack = {1, 2, 3}
System.out.println(stack.search(new Integer(3))); //1
System.out.println(stack.search(new Integer(2))); //2
System.out.println(stack.empty()); //false
System.out.println(stack.pop()); //3, stack = {1, 2}
System.out.println(stack.peek()); //2, stack = {1, 2}
System.out.println(stack.pop()); //2, stack = {1}
System.out.println(stack.pop()); //1, stiva goala
System.out.println(stack.empty()); //true
Limbajul Java colecii (2)
89
Clasa LinkedList
Permite implementarea stivelor i a cozilor.
Diferena fa de Stack: LinkedList este nesincronizat (deci mai rapid). Nefiind
sincronizat, LinkedList necesit sincronizare extern n caz de accesare
concurenial multifir.
Exemple:
LinkedList stack = new LinkedList(); //stiva goala
stack.addLast(new Integer(1)); //stack = {1}
stack.addLast(new Integer(2)); //stack = {1, 2}
stack.addLast(new Integer(3)); //stack = {1, 2, 3}
System.out.println(stack.removeLast()); //3, stack = {1, 2}
System.out.println(stack.getLast()); //2, stack = {1, 2}
System.out.println(stack.removeLast()); //2, stack = {1}
System.out.println(stack.removeLast()); //1, stiva goala
LinkedList queue = new LinkedList(); //coada goala
queue.addFirst(new Integer (1)); //queue = {1}
queue.addFirst(new Integer(2)); //queue = {2, 1}
queue.addFirst(new Integer(3)); //queue = {3, 2, 1}
System.out.println(queue.removeLast()); //1, queue = {3, 2}
System.out.println(queue.removeLast()); //2, queue = {3}
System.out.println(queue.removeLast()); //3, coada goala
Limbajul Java colecii (3)
90
Clasele HashSet, TreeSet i LinkedHashSet
Interfaa Set permite folosirea mulimilor colecii de date n care elementele
sunt unice.
Clasa HashSet pstreaz elementele adugate n ordinea stabilit de o funcie
de dispersie, asigurnd astfel operaii de introducere i preluare a unui element
rapide, de complexitate O(1). Funcia de dispersie poate fi schimbat prin
redefinirea metodei hashCode().
Clasa TreeSet pstreaz elementele sortate n ordine cresctoare, ceea ce
determin operaii de introducere i preluare a unui element mai lente, de
complexitate O(log n).
Clasa LinkedHashSet (disponibil ncepnd cu versiunea JDK 1.4) pstreaz
elementele n ordinea n care au fost introduse asigurnd operaii de accesare a
unui element de complexitate O(1).
Exemple
HashSet hs = new HashSet(); //hs = {}
hs.add(new Integer(1)); //hs = {1}
hs.add(new Integer(2)); //hs = {2, 1}
hs.add(new Integer(4)); //hs = {2, 4, 1}
hs.add(new Integer(2)); //hs = {2, 4, 1}
TreeSet ts = new TreeSet(hs); //ts = {1, 2, 4}
ts.add(new Integer(3)); //ts = {1, 2, 3, 4}
LinkedHashSet lhs = new LinkedHashSet(); //lhs = {}
lhs.add(new Integer(1)); //lhs = {1}
lhs.add(new Integer(2)); //lhs = {1, 2}
lhs.add(new Integer(4)); //lhs = {1, 2, 4}
lhs.add(new Integer(3)); //lhs = {1, 2, 4, 3}
Limbajul Java colecii (4)
91
Implementarea interfeei Comparable pentru
obiectele ncrcate n TreeSet
Obiectele ncrcate n TreeSet sunt sortate prin intermediul funciei compareTo. De
aceea, clasa obiectelor ncrcate trebuie s implementeze interfaa Comparable.
Proprietatea de set (mulime) se aplic cmpului dup care se face comparaia n
compareTo. Dac valoarea acelui cmp este aceeai n dou obiecte, chiar dac celelalte
cmpuri difer, n set rmne doar unul din obiecte. De aceea, dac n compareTo
valorile cmpului comparat sunt egale se poate ine cont de celelalte cmpuri, aplicnd
astfel proprietatea de set pe ntregul obiect.
Exemplu:
public class Person implements Comparable{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int compareTo(Object p){
return this.name.compareTo(((Person)p).name);
}
}
public class Main {
public static void main(String[] args) {
Person p = new Person("Popescu", 103);
TreeSet ts = new TreeSet();
ts.add(p); //{Popescu-103}
Person q = new Person("Ionescu", 98);
ts.add(q); //{Ionescu-98, Popescu-103}
Person r = new Person("Petrescu", 49);
ts.add(r); //{Ionescu-98, Petrescu-49, Popescu-103}
}
}
Limbajul Java colecii (5)
92
Clasele HashMap, TreeMap i LinkedHashMap
Interfaa Map permite pstrarea de perechi cheie-valoare, ambele de tip
referin, cu chei unice. Principalele operaii:
put(k, v) asociaz cheii k valoarea v. Dac exist deja cheia k atunci
vechea valoare se nlocuiete cu v.
get(k) returneaz valoarea corespunztoare cheii k.
Clasa HashMap pstreaz cheile n ordinea stabilit de o funcie de dispersie
asigurnd astfel accesri rapide, de complexitate O(1).
Clasa TreeMap pstreaz cheile ordonate cresctor, accesarea fiind astfel mai
lent, de complexitate O(log n).
Clasa LinkedHashMap (disponibil ncepnd cu JDK 1.4) pstreaz cheile n
ordinea n care au fost introduse asigurnd accesri de complexitate O(1).
Exemple
HashMap hm = new HashMap();
hm.put("Romania", "Bucuresti");
hm.put("Franta", "Paris");
hm.put("Germania", "Bonn");
hm.put("Germania", "Berlin");
System.out.println(hm); //{Romania=Bucuresti, Germania=Berlin, Franta=Paris}
System.out.println(hm.get("Germania")); //Berlin
TreeMap tm = new TreeMap(hm);
System.out.println(tm); //{Franta=Paris, Germania=Berlin, Romania=Bucuresti}
LinkedHashMap lhm = new LinkedHashMap();
lhm.put("Romania", "Bucuresti");
lhm.put("Franta", "Paris");
lhm.put("Germania", "Berlin");
System.out.println(lhm); //{Romania=Bucuresti, Franta=Paris, Germania=Berlin}
Limbajul Java colecii (6)
93
Implementarea interfeei Comparable pentru
cheile ncrcate n TreeMap
Perechile cheie-valoare ncrcate n TreeMap sunt sortate n ordinea cresctoare a
cheilor, prin intermediul funciei compareTo. De aceea, clasa obiectelor cheie trebuie s
implementeze interfaa Comparable.
Exemplu:
public class Person implements Comparable{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int compareTo(Object p){
return this.name.compareTo(((Person)p).name);
}
}
public class Main {
public static void main(String[] args) {
Person p = new Person("Pop", 54);
TreeMap tm = new TreeMap();
tm.put(p, "Romania");
//tm={Pop-54-Romania}
Person q = new Person("Brown", 98);
tm.put(q, "Anglia");
//tm={Brown-98-Anglia, Pop-54-Romania}
Person r = new Person("Schmitt", 49);
tm.put(r, "Germania");
//tm={Brown-98-Anglia, Pop-54-Romania, Schmitt-49-Germania}
}
}
Limbajul Java colecii (7)
94
Iteratori
Iteratorii permit traversarea n ordine a coleciilor de date.
Exemplu:
TreeSet ts = new TreeSet();
ts.add("Romania");
ts.add("Anglia");
ts.add("Germania");
ts.add("Franta");
Iterator i = ts.iterator();
while(i.hasNext()) System.out.println(i.next());
Secvena de cod afieaz:
Anglia
Franta
Germania
Romania
Limbajul Java colecii (8)
95
Aplicaii propuse
1. S se modifice programele prezentate la TreeSet i TreeMap astfel nct sortarea
persoanelor s se fac dup vrst n cazul n care au acelai nume.
2. Definii clasa Course cu cmpurile title, teacher (profesor), credits (nr. credite) i
year (an de studiu). Introducei de la tastatur cinci obiecte de tip Course ntr-un
TreeSet i afiai cursul cu cel mai mic numr de credite.
3. Definii clasa Course cu cmpurile title, teacher (profesor), credits (nr. credite) i
year (an de studiu). Introducei de la tastatur cinci obiecte de tip Course ntr-un
TreeSet i afiai cursul cu cel mai mare numr de credite.
4. Definii clasa Course cu cmpurile title, teacher (profesor), credits (nr. credite) i
year (an de studiu). Introducei de la tastatur cinci obiecte de tip Course ntr-un
TreeSet i afiai-le n ordinea descresctoare a numrului de credite.
5. Definii clasa Course cu cmpurile title, teacher (profesor), credits (nr. credite) i
year (an de studiu). Introducei de la tastatur cinci obiecte de tip Course ntr-un
TreeSet i afiai-le n ordinea cresctoare a anului de studiu.
6. Definii clasa Course cu cmpurile title, teacher (profesor), credits (nr. credite) i
year (an de studiu). Introducei de la tastatur cinci obiecte de tip Course ntr-un
TreeSet i afiai-le n ordinea alfabetic a titlului.
7. Definii clasa Course cu cmpurile title, teacher (profesor), credits (nr. credite) i
year (an de studiu). Introducei de la tastatur cinci obiecte de tip Course ntr-un
TreeSet i afiai-le n ordinea alfabetic a profesorului.
Limbajul Java colecii (9)
96
Test gril (T1) susinut la curs din noiunile
predate n cadrul capitolului Limbajul Java;
Test (T2) susinut la laborator din aplicaiile
propuse la laborator se va implementa i
rula pe calculator o aplicaie care implic o
motenire respectiv folosirea unor colecii de
date.
Limbajul Java test
Partea II
Analiza algoritmilor
98
Analiza algoritmilor
Algoritmul este o secven de operaii care
transform mulimea datelor de intrare n datele de
ieire.
Analiza algoritmului se refer la evaluarea
performanelor acestuia (timp de execuie, spaiu de
memorie). Scopul este acela de a gsi algoritmul cel
mai eficient pentru o anumit problem.
La analiza algoritmilor trebuie avut n vedere modelul
de implementare (secvenial, paralel) i arhitectura
mainii de calcul (superscalar, multithreading,
multicore) respectiv dac aceasta permite sau nu
execuia speculativ a instruciunilor.
99
Conjectura Church-Turing postuleaz c pentru orice algoritm
exist o main Turing echivalent. Cu alte cuvinte, nicio
procedur de calcul nu este algoritm dac nu poate fi executat
de o main Turing. n esen, maina Turing reprezint ceea
ce astzi numim algoritm. Aadar, o main Turing este
echivalent cu noiunea de algoritm.
O main Turing const din:
O band mprit n celule, fiecare coninnd un simbol (inclusiv
cel vid) dintr-un alfabet finit.
Un cap care poate scrie i citi i care se poate deplasa la stnga
sau la dreapta.
Un registru de stare care stocheaz starea mainii Turing. Numrul
strilor este finit i exist o stare iniial.
O funcie de tranziie (tabel de aciuni) care, n funcie de starea
curent i simbolul citit, determin ce simbol s se scrie, cum s se
deplaseze capul (la stnga sau la dreapta) i care va fi noua stare.
Maina Turing se oprete dac se ajunge ntr-o stare final sau
dac nu exist combinaia de simbol-stare n tabela de aciuni.
Analiza algoritmilor maina Turing
100
Complexitatea unui algoritm, exprimat n funcie de dimensiunea
datelor de intrare (n), are urmtoarele componente:
Complexitate temporal numrul de operaii necesare pentru rezolvarea
unei probleme
Complexitate spaial spaiul de memorie utilizat
Complexitatea temporal este indicatorul principal al performanei unui
algoritm.
Complexitatea temporal a unui algoritm poate fi determinat
experimental (prin msurarea timpului de rulare) sau prin analiz
teoretic (prin aproximarea numrului de operaii primitive).
Complexitatea unui algoritm este de regul exprimat (aproximat) prin
notaii asimptotice [Cor00] care rein doar termenul dominant al
expresiei, ceilali termeni devenind neglijabili pentru valori mari ale lui n.
Exemple:
Dac execuia unui algoritm necesit 2
n
+n
5
+8 operaii, atunci complexitatea
temporal este 2
n
;
Un algoritm cu 7n
4
+10n
2
+1000n operaii elementare are complexitate n
4
.
Analiza algoritmilor complexitate (1)
101
Analiza algoritmilor complexitate (2)
-notaia

} ), ( ) ( ) ( 0 . . 0 , , ) ( { )) ( (
0 2 1 0 2 1
n n n g c n f n g c a n c c n f n g > =
-notaia delimiteaz o funcie asimptotic inferior i
superior, g(n) este o margine asimptotic tare pentru f(n).
n
f(n)
c
2
g(n)
c
1
g(n)
n
0
102
O-notaia delimiteaz o funcie asimptotic superior,
g(n) este o margine asimptotic superioar.
Analiza algoritmilor complexitate (3)
O-notaia
n
f(n)
c g(n)
n
0
} ), ( ) ( 0 . . 0 , ) ( { )) ( (
0 0
n n n g c n f a n c n f n g O > =
103
-notaia delimiteaz o funcie asimptotic inferior,
g(n) este o margine asimptotic inferioar.
Analiza algoritmilor complexitate (4)
-notaia
} ), ( ) ( 0 . . 0 , ) ( { )) ( (
0 0
n n n f n g c a n c n f n g > =
n
n
0
f(n)
c g(n)
104
o-notaia: Delimitarea asimptotic superioar dat de notaia O
poate sau nu s fie o delimitare asimptotic strns. De exemplu,
2n
2
=O(n
2
) este o delimitare asimptotic strns, pe cnd 2n
2
=O(n
3
)
nu este. Vom folosi o-notaia pentru a desemna o delimitare
superioar care nu este asimptotic strns: 2n
2
=o(n
3
).
-notaia desemneaz o delimitare asimptotic inferioar care nu
este asimptotic strns: 2n
2
=(n).
Teorem: Pentru orice dou funcii f(n) i g(n), avem f(n)=(g(n))
dac i numai dac f(n)=O(g(n)) i f(n)=(g(n)).
Convenie: n orice ecuaie n care se folosesc notaii asimptotice
membrul drept ofer un nivel de detaliu mai sczut dect membrul
stng. Exemplu: 2n
2
+3n+1 = 2n
2
+(n) = (n
2
). Putem scrie
2n
2
+3n+1 = (n
2
), dar nu scriem niciodat (n
2
) = 2n
2
+3n+1.
Analiza algoritmilor complexitate (5)
} ), ( ) ( 0 . . 0 , 0 ) ( { )) ( (
0 0
n n n g c n f a n c n f n g o < > > =
} ), ( ) ( 0 . . 0 , 0 ) ( { )) ( (
0 0
n n n f n g c a n c n f n g < > > =
105
Alte exemple [Knu00]
tim c
Rezult c
Ecuaia (2) este destul de nerafinat, dar nu incorect; ecuaia
(3) este mai puternic, iar ecuaia (4) i mai puternic.
Analiza algoritmilor complexitate (6)
) 1 (
6
1
2
1
3
1
6
) 1 2 )( 1 (
... 2 1
2 3 2 2 2
n n n
n n n
n + + =
+ +
= + + +
) 4 ( ) (
3
1
... 2 1
) 3 ( ) ( ... 2 1
) 2 ( ) ( ... 2 1
2 3 2 2 2
3 2 2 2
4 2 2 2
n O n n
n O n
n O n
+ = + + +
= + + +
= + + +
106
Analiza algoritmilor complexitate (7)
Ordinul de complexitate
O(a
n
) Exponenial
O(n
p
) Polinomial (p>2)
O(n
2
) Ptratic
O(n log n) Liniar logaritmic
O(n) Liniar
O(log n) Logaritmic
O(1) Constant
107
Exprimai urmtoarele complexiti cu ajutorul
notaiei :
Analiza algoritmilor complexitate (8)
2 2 2
3 3 3
2 2 2
2
2
2 3
) 1 2 ( ... 3 1 ) 10
) 1 ( ... 3 2 2 1 ) 9
... 2 1 ) 8
... 2 1 ) 7
... 2 1 ) 6
ln ) 5
ln 2 ) 4
2 4 ) 3
3 5 2 ) 2
100 ) 1
+ + +
+ + + +
+ + +
+ + +
+ + +
+ +
+
+
+ +
+
n
n n
n
n
n
n n n n
n n n
n
n
n n
k k
n
n
n
108
Vom utiliza urmtoarele notaii:
Deoarece schimbarea bazei unui logaritm de la o
constant la alta schimb valoarea logaritmului doar
printr-un factor constant, vom folosi notaia lgn
atunci cnd factorii constani nu vor fi importani.
Analiza algoritmilor logaritmi (1)
) lg(lg lg lg
) (lg lg
log ln
log lg
2
n n
n n
n n
n n
k k
e
=
=
=
=
109
Pentru orice numere reale a>0, b>0, c>0 i n,
Analiza algoritmilor logaritmi (2)
a n
b b
b b b
c b b
a b
a
b
c
c
b
b
n
b
c c c
a
b b
b
n a
a
a
a c
a
c
a c a
b a
b
a
b
a
a
a n a
b a ab
b a
log log
log
log
1
log
log log log
log log log
1 log log
log
1
log
log
log
log
log log
log log ) ( log
=
=
=
=
=
=
=
=
+ =
=
110
O recuren este o ecuaie care descrie o funcie exprimnd valoarea sa pentru
argumente mai mici. Cnd un algoritm conine o apelare recursiv la el nsui,
timpul su de execuie poate fi descris printr-o recuren. Recurenele pot fi
rezolvate prin metoda substituiei, metoda iteraiei sau metoda master [Cor00].
Metoda master ofer o soluie simpl pentru rezolvarea recurenelor de forma:
unde a1, b>1, iar f(n) este o funcie dat.
Teorema master. Fie a1 i b>1 constante, f(n) o funcie i T(n) definit pe
ntregii nenegativi prin recurena
atunci T(n) poate fi delimitat asimptotic dup cum urmeaz:
Analiza algoritmilor recurene (1)
) ( ) ( n f
b
n
T a n T +
|

\
|
=
) ( ) ( n f
b
n
T a n T +
|

\
|
=
)). ( ( ) ( 1 ), ( 0 ), ( ) ( . 3
) lg ( ) ( ) ( ) ( . 2
) ( ) ( 0 ), ( ) ( . 1
log
log log
log log
n f n T mari de suficient n i c n cf
b
n
af i n n f dac
n n n T n n f dac
n n T n O n f dac
a
a a
a a
b
b b
b b
= <
|

\
|
> =
= =
= > =
+

111
Exemplu de utilizare a metodei master
S considerm
Pentru aceast recuren a=9, b=3, f(n)=n, astfel
Deoarece
aplicnd cazul 1 al teoremei master,
Analiza algoritmilor recurene (2)
n
n
T n T +
|

\
|
=
3
9 ) (
2 9 log log
3
n n n
a
b
= =
, 1 ), ( ) ( ) (
9 log
3
= = =

n O n O n f
) ( ) ( ) (
2 9 log
3
n n n T = =
112
Exemplu de neaplicabilitate a metodei master
S considerm urmtoarea recuren:
Pentru aceast recuren a=2, b=2, f(n)=nlgn. Astfel,
Se poate observa c niciunul din cazurile teoremei master
nu se poate aplica:
Vom folosi n continuare metoda iteraiei pentru rezolvarea
acestei recurene.
Analiza algoritmilor recurene (3)
n n n T n T lg ) 2 / ( 2 ) ( + =
) lg , 01 . 0 . ( 0 ), ( lg . 3
) ( lg . 2
0 ), ( lg . 1
01 . 1 1
1
n n n ex n n n
n n n
n O n n
> = >

>
+

n n n n
a
b
= = =
1 2 log log
2
113
Rezolvare prin metoda iteraiei a recurenei
Iterm recurena dup cum urmeaz:
Considernd condiia la limit T(1)=(1), recurena se termin pentru
Analiza algoritmilor recurene (4)
n n n T n T lg ) 2 / ( 2 ) ( + =
1 1
1
2 3
3
2 2 3
2
2
2
2
2
2
lg
2
2
2
2
2
lg
2
2
2
lg
2 2
2 2
2
2
2
lg
2
2
2
lg
2 2
2
2 2
2
2
lg
2
2 ) (

+
|

\
|
=
|

\
|
+
|

\
|
=
(

+
|

\
|
=
|

\
|
+
|

\
|
=
(
(
(
(

+
|
|
|
|

\
|
=
|

\
|
+
|

\
|
=
q q
q
q
q
n
n
n
T
n
T
n
n
n
T
n n n
T
n
T
n
n
n
T
n n
n
T
n
T
n n
n
T n T
n q n
n
q
q
lg 2 1
2
= = =
114
Am artat c la limita T(1)=(1), q=lg n. Obinem:
Analiza algoritmilor recurene (5)
( )
( ) n n n T
n n n
n n n n T
n n
k
n n
k
k n n n n n T
n n n n n n T
n n n T
n
n T n T
n
k
n
k
n
k
n
k
k
n
k
k n
n
k
k
n
2
2
1 lg
0
1
0
1 lg
0
2 1
1 lg
0
2 lg
1 lg
0
lg
1 lg
0
lg
lg ) (
2
) 1 (lg lg
lg ) (
2
) 1 (lg lg
2
) 1 (
lg ) 1 ( ) (
2 lg lg lg ) 1 ( ) (
2 lg lg ) 1 ( 2 ) (
2
lg ) 1 ( 2 ) (
=
|

\
|

+ =

=

=
+ =
+ =
+ =
+ =


=
115
Exerciii. Dai o delimitare asimptotic strns
pentru urmtoarele recurene:
1) T(n) = T(2n/3) + 1
2) T(n) = 3T(n/4) + n lg n
3) T(n) = 3T(n/3) + n/2
4) T(n) = 2T(n/2) + n
5) T(n) = 16T(n/4) + n
6) T(n) = 4T(n/2) + n
2
7) T(n) = 4T(n/2) + n
3
Analiza algoritmilor recurene (6)
116
Principalele tipuri de analiz
Analiza cazului cel mai favorabil cel mai scurt
timp de execuie posibil pe date de intrare de
dimensiune constant n;
Analiza cazului cel mai defavorabil cel mai mare
timp de execuie posibil relativ la orice date de
intrare de dimensiune constant n;
Analiza cazului mediu timpul mediu de execuie
al unui algoritm considernd toate datele de
intrare de dimensiune constant n. Exist ns
probleme la care nu e prea clar care sunt datele
de intrare de complexitate medie.
Urmeaz cteva exemple de analiz a unor
algoritmi: cutare, sortare, etc.
Analiza algoritmilor tipuri de analiz
117
Analiza algoritmilor cutarea maximului (1)
Se d un tablou X de n elemente. S se gseasc m astfel nct
m = max
1kn
X[k], considernd cel mai mare indice k care
satisface aceast relaie.
1. k n-1, m X[n].
2. Dac k=0, algoritmul se ncheie.
3. Dac X[k]m, mergei la pasul 5.
4. m X[k].
5. Decrementai k cu 1 i revenii la pasul 2.
Pentru ca analiza s fie
complet trebuie s
determinm mrimea A, care
reprezint numrul de
modificri ale valorii maxime
curente.
n-1 c5 5.
A c4 4.
n-1 c3 3.
n c2 2.
1 c1 1.
Nr. execuii Cost Pasul
118
Analiza algoritmilor cutarea maximului (2)
Determinarea mrimii A
Cazul cel mai favorabil: A=0, se obine atunci cnd
maximul este X[n];
Cazul cel mai defavorabil: A=n-1, se obine atunci
cnd maximul este X[1];
Cazul mediu: presupunnd c cele n valori sunt
distincte, conteaz doar ordinea lor relativ. Dac
n=3, exist urmtoarele posibiliti echiprobabile:
0 X[3]>X[2]>X[1]
0 X[3]>X[1]>X[2]
1 X[2]>X[3]>X[1]
1 X[2]>X[1]>X[3]
1 X[1]>X[3]>X[2]
2 X[1]>X[2]>X[3]
A Situaie
119
Determinarea valorii A pentru cazul mediu
Probabilitatea ca A s aib valoarea k va fi
p
nk
=(nr. situaii n care A=k)/n!
n exemplul anterior p
30
=1/3, p
31
=1/2, p
32
=1/6
Valoarea medie a lui A este definit astfel:
A
n
reprezint de fapt media ponderat a valorilor lui A.
n exemplul anterior valoarea medie a lui A pentru n=3
va fi 5/6. Knuth arat c pentru n mare A
n
=lnn.
Analiza algoritmilor cutarea maximului (3)

=
k
nk n
p k A
120
Determinarea complexitii
Cazul cel mai favorabil:
c
1
+ c
2
n + c
3
(n-1) + 0 + c
5
(n-1) =
(c
2
+c
3
+c
5
)n + (c
1
-c
3
-c
5
) = an+b = (n)
Cazul cel mai defavorabil:
c
1
+ c
2
n + c
3
(n-1) + c
4
(n-1) + c
5
(n-1) =
(c
2
+c
3
+c
4
+c
5
)n + (c
1
-c
3
-c
4
-c
5
) = an+b = (n)
Cazul mediu:
c
1
+ c
2
n + c
3
(n-1) + c
4
ln n + c
5
(n-1) =
(c
2
+c
3
+c
5
)n + c
4
ln n + (c
1
-c
3
-c
5
) = an + b ln n + c = (n)
Analiza algoritmilor cutarea maximului (4)
121
Punnd problema mai simplu,
Cost Execuii
m X[n] c
1
1
for k n-1 downto 1 do c
2
n
if X[k]>m then m X[k] c
3
n-1
considernd operaie elementar fiecare iteraie a ciclului, e
uor de observat c bucla este parcurs n ntregime, deci
algoritmul are aceeai complexitate
(c
2
+c
3
)n + (c
1
-c
3
) = an+b = (n)
indiferent de ordinea relativ a celor n valori.
Analiza algoritmilor cutarea maximului (5)
122
Se d un tablou X de n elemente. Se parcurge secvenial tabloul X pn la primul element care
are valoarea k.
Cost Execuii
1. i 1. c
1
1
2. Dac X[i] = k, algoritmul se ncheie cu succes. c
2
C
3. i i+1. c
3
C-S
4. Dac in se revine la pasul 2. c
4
C-S
n caz contrar, algoritmul se ncheie fr succes.
unde C este numrul de comparaii de chei i S este 1 n caz de succes respectiv 0 n caz de
cutare fr succes. Complexitatea algoritmului este:
c
1
+ c
2
C + c
3
(C-S) + c
4
(C-S)
n cazul n care valoarea nu este gsit, avem C=n, S=0, cu o complexitate
(c
2
+c
3
+c
4
)n + c
1
= an+b = (n)
n caz de succes, cu X[i]=k, avem C=i, S=1, cu o complexitate
(c
2
+c
3
+c
4
)i + (c
1
-c
3
-c
4
)
Considernd c valorile din tablou sunt distincte i echiprobabile, valoarea medie a lui C este
deci complexitatea n cazul mediu este tot (n).
Analiza algoritmilor cutarea secvenial
2
1 ... 2 1 +
=
+ + + n
n
n
123
Se d un tablou X de n elemente ordonate cresctor. Valoarea cutat k
se compar cu elementul din mijlocul tabloului, iar rezultatul acestei
comparaii ne arat n care jumtate trebuie continuat cutarea.
Cost Execuii
1. s 1, d n c
1
1
2. Dac d<s alg. se ncheie fr succes. c
2
C+1-S
Altfel, i (s+d)/2.
3. Dac k<X[i] se trece la pasul 4. c
3
C
Dac k>X[i] se trece la pasul 5.
Dac k=X[i] alg. se ncheie cu succes.
4. d i-1 i se revine la pasul 2. c
45
C-S
5. s i+1 i se revine la pasul 2.
unde C este numrul de comparaii de chei i S este 1 n caz de succes
respectiv 0 n caz de cutare fr succes. Complexitatea algoritmului
este:
c
1
+ c
2
(C+1-S) + c
3
C + c
45
(C-S)
Analiza algoritmilor cutarea binar (1)
124
Determinarea valorii C pentru cazul cel mai defavorabil
Valoarea maxim a lui C (numrul comparaiilor de chei) poate
fi exprimat prin urmtoarea recuren
care descrie njumtirea recurent a spaiului de cutare cu un
cost constant (1).
Aplicnd terorema master, avem a=1 (cutarea se continu pe
o singur ramur st./dr.), b=2 (spaiul de cutare se reduce la
jumtate) i f(n)=(1). Astfel,
deci putem aplica cazul 2 al teoremei master. Prin urmare,
Astfel, n cazul cel mai defavorabil, C=(lg n) iar complexitatea
temporal este:
(c
2
+c
3
+c
45
)(lg n) + (c
1
+c
2
) = (lg n).
Analiza algoritmilor cutarea binar (2)
) 1 (
2
) ( +
|

\
|
=
n
T n T
1
0 1 log log
2
= = = n n n
a
b
) (lg ) lg ( ) lg ( ) (
0 log
n n n n n n T
a
b
= = =
125
Determinarea valorii C pentru cazul mediu
Considernd c valorile din tablou sunt distincte i echiprobabile,
n cazul mediu valoarea cutat este gsit la jumtatea
procesului de cutare, ceea ce n numr de iteraii este echivalent
cu parcurgere total dar divizarea recurent a spaiului de cutare
la un sfert:
Aplicnd teorema master, avem a=1, b=4 i f(n)=(1). Astfel,
deci putem aplica cazul 2 al teoremei master. Prin urmare,
Astfel, n cazul mediu, la fel ca n cazul cel mai defavorabil,
C=(lg n), deci complexitatea temporal este tot (lg n).
Analiza algoritmilor cutarea binar (3)
) 1 (
4
) ( +
|

\
|
=
n
T n T
1
0 1 log log
4
= = = n n n
a
b
) (lg ) lg ( ) lg ( ) (
0 log
n n n n n n T
a
b
= = =
126
Se d un tablou X de n elemente. Se consider pe rnd vectorii formai
din primele 2, 3, ..., n elemente din tablou, ordonate prin aducerea noului
element (al 2-lea, al 3-lea, ..., al n-lea) pe poziia corespunztoare valorii
sale. Aceasta presupune deplasarea la dreapta a elementelor cu valori
mai mari, astfel nct noul element s poat fi inserat naintea lor:
Cost Execuii
for j 2 to n do c
1
n
k X[j] c
2
n-1
i j-1 c
3
n-1
while i>0 and X[i]>k do c
4
X[i+1] X[i] c
5
i i-1 c
6
X[i+1] k c
7
n-1
unde am notat cu t
j
numrul de execuii ale testului while
Analiza algoritmilor sortare prin inserie (1)
sortat nesortat
1
n
k

=
n
j
j
t
2

n
j
j
t
2
) 1 (

n
j
j
t
2
) 1 (
127
Determinarea complexitii n cazul cel mai favorabil
Vectorul de intrare este deja sortat, deci bucla while nu
se execut niciodat (se verific doar condiiile o singur
dat n fiecare iteraie for), astfel t
j
=1, rezult:

Analiza algoritmilor sortare prin inserie (2)

=
=
n
j
j
n t
2
1
0 ) 1 (
2
=

=
n
j
j
t
) ( ) ( ) (
) 1 ( ) 1 ( ) 1 ( ) 1 (
7 4 3 2 7 4 3 2 1
7 4 3 2 1
n b an c c c c n c c c c c
n c n c n c n c n c
= + = + + + + + + +
= + + + +
128
Determinarea complexitii n cazul cel mai defavorabil
Vectorul de intrare este sortat n ordine invers, deci bucla while se
execut de 1, 2, ..., n-1 ori (condiiile fiind verificate de 2, 3, ..., n ori)
pentru j=2, 3, ...,n, astfel t
j
=j,

Analiza algoritmilor sortare prin inserie (3)



= =

+
= =
n
j
n
j
j
n n
j t
2 2
1
2
) 1 (
2
) 1 (
) 1 ( 1
2
) 1 (
) 1 (
2

=
+
=

=
n n
n
n n
t
n
j
j
) (
) (
2 2 2 2 2 2
) 1 (
2
) 1 (
2
) 1 (
1
2
) 1 (
) 1 ( ) 1 (
2 2
7 4 3 2 7
6 5 4
3 2 1
2 6 5 4
7 6 5 4 3 2 1
n c bn an
c c c c n c
c c c
c c c n
c c c
n c
n n
c
n n
c
n n
c n c n c n c
= + +
= + + + |

\
|
+ + + + + |

\
|
+ +
= +

+
|

\
|

+
+ + +
129
Determinarea complexitii n cazul mediu
S presupunem c alegem la ntmplare n numere distincte i aplicm
sortarea prin inserie.
Cte iteraii sunt necesare pentru inserarea elementului X[j] n
subvectorul X[1...j-1]? n medie jumtate din elementele subvectorului
X[1...j-1] sunt mai mici dect X[j] i jumtate sunt mai mari. Prin
urmare, n medie, trebuie verificate jumtate din elementele
subvectorului X[1...j-1], deci t
j
=j/2,

Astfel, complexitatea n cazul mediu va fi tot (n


2
), la fel ca n cazul cel
mai defavorabil.
Analiza algoritmilor sortare prin inserie (4)

= =
+
=
|

\
|

+
= =
n
j
n
j
j
n n n n
j t
2
2
2
4
2
1
2
) 1 (
2
1
2
1
4
2 3
) 1 (
4
2
) 1 (
2 2
2
+
=
+
=

=
n n
n
n n
t
n
j
j
130
Se d un tablou X de n elemente. Se consider pe rnd
subtablourile formate din elementele i, ..., n (cu i=1, 2, ..., n) i
se aduce prin interschimbare elementul minim al fiecrui
subtablou pe poziia i:
SELSORT1 (X)
for i 1 to n-1 do
min i
for j i+1 to n do
if X[j] < X[min] then
min j
X[i] X[min]
Analiza algoritmilor sortare prin selecie (1)
sortat nesortat
1
n
i
min
131
Analiza algoritmilor sortare prin selecie (2)
O alt variant a sortrii prin
selecie:
SELSORT2 (X)
for i 1 to n-1 do
for j i+1 to n do
if X[j] < X[i] then
X[i] X[j]
Complexitatea algoritmului este:
) (
2
) 1 (
1 ... ) 2 ( ) 1 (
2
n
n n
n n C =

= + + + =
132
Se d un tablou X de n elemente. Algoritmul Bubblesort parcurge
repetat tabloul X interschimbnd dac e cazul elementele
consecutive:
BUBBLESORT1 (X)
n X.size
for i 1 to n do
for j 1 to n-1 do
if X[j] > X[j+1] then
X[j] X[j+1]
Complexitatea algoritmului este:
Analiza algoritmilor Bubblesort (1)
) ( ) 1 (
2
n n n C = =
133
Elementul de pe ultima poziie a iteraiei curente poate fi exclus
din iteraia urmtoare:
BUBBLESORT2 (X)
n X.size
for i 1 to n-1 do
for j 1 to n-i do
if X[j] > X[j+1] then
X[j] X[j+1]
Complexitatea algoritmului este:
Analiza algoritmilor Bubblesort (2)
) (
2
) 1 (
1 ... ) 2 ( ) 1 (
2
n
n n
n n C =

= + + + =
134
O alt variant n care elementul de pe prima poziie a iteraiei curente
poate fi exclus din iteraia urmtoare:
BUBBLESORT3 (X)
n X.size
for i 1 to n-1 do
for j n-1 downto i do
if X[j] > X[j+1] then
X[j] X[j+1]
Complexitatea algoritmului este:
Analiza algoritmilor Bubblesort (3)
) (
2
) 1 (
1 ... ) 2 ( ) 1 (
2
n
n n
n n C =

= + + + =
135
Algoritmul poate fi mbuntit reducnd numrul de iteraii de la n la cte sunt
necesare pn la obinerea tabloului sortat. i n acest caz elementul de pe ultima
poziie a iteraiei curente poate fi exclus din iteraia urmtoare:
BUBBLESORT4 (X)
sortat false
n X.size-1
while not sortat do
sortat true
for i 1 to n do
if X[i] > X[i+1] then
X[i] X[i+1]
sortat false
nn-1
Complexitatea algoritmului n cazul cel mai favorabil (o singur parcurgere) este
(n) iar n cazul cel mai defavorabil rmne:
Analiza algoritmilor Bubblesort (4)
) (
2
) 1 (
1 ... ) 2 ( ) 1 (
2
n
n n
n n C =

= + + + =
136
Algoritmul de sortare rapid se bazeaz pe paradigma divide et impera. Tabloul
este rearanjat n dou subtablouri astfel nct fiecare element al primului
subtablou este mai mic sau egal cu orice element din al doilea subtablou. Cele
dou subtablouri sunt sortate prin apeluri recursive ale algoritmului de sortare
rapid.
QUICKSORT (X, primul, ultimul)
i primul
j ultimul
pivot X[primul]
while i<j do
while X[i]<pivot do
i i+1
while X[j]>pivot do
j j-1
if i<j then
X[i] X[j]
if ij then
i i+1
j j-1
if primul<j then QUICKSORT (X, primul, j)
if i<ultimul then QUICKSORT (X, i, ultimul)
Analiza algoritmilor Quicksort (1)
137
Analiza cazului cel mai defavorabil
Cazul cel mai defavorabil este acela n care toate
partiionrile sunt total dezechilibrate: un subtablou
de un element i unul de n-1 elemente. Astfel, cazul
cel mai defavorabil poate fi descris prin urmtoarea
recuren:
Unde (n) este timpul de partiionare. Deoarece
T(1)=(1), se ajunge la recurena
Apoi, iternd recurena, obinem:
Analiza algoritmilor Quicksort (2)
) ( ) 1 ( ) 1 ( ) ( n n T T n T + + =
) ( ) 1 ( ) ( n n T n T + =

= =
=
|

\
|
+
= |

\
|
= =
n
k
n
k
n
n n
k k n T
1
2
1
) (
2
) 1 (
) ( ) (
138
Analiza cazului cel mai favorabil
Atunci cnd partiiile sunt aproximativ egale se ajunge la
urmtoarea recuren:
Folosind teorema master avem a=2 (sortarea se continu pe
ambele partiii), b=2 (vectorul de sortat se njumtete) i
f(n)=(n) (timpul de partiionare). Astfel,
Deci putem aplica cazul 2 al teoremei master. Prin urmare,
avem:
Analiza algoritmilor Quicksort (3)
) (
2
2 ) ( n
n
T n T +
|

\
|
=
n n n n
a
b
= = =
1 2 log log
2
) lg ( ) lg ( ) lg ( ) (
2 log log
2
n n n n n n n T
a
b
= = =
139
Analiza cazului mediu
Atunci cnd partiionrile echilibrate i dezechilibrate alterneaz,
combinarea unei partiionri defavorabile i a uneia favorabile produce
trei subvectori de dimensiuni 1, (n-1)/2 i (n-1)/2 cu un cost total:
n + n-1 = 2n-1 = (n)
Se poate observa c o partiionare defavorabil de un cost (n) poate
fi absorbit de o partiionare echilibrat de cost (n), i partiionarea
rezultat este favorabil.
Astfel, complexitatea medie este aceeai ca n cazul cel mai favorabil,
O(nlgn), doar constanta din notaia O este mai mare. Alternana
partiionrilor dezechilibrate cu cele echilibrate poate fi descris prin
recurena
unde T(1)=(1), iar (n)+(1)+(n)=(n), deci obinem recurena
Analiza algoritmilor Quicksort (4)
|

\
|

+
|

\
|

+ + + = + + =
2
1
2
1
) ( ) 1 ( ) ( ) 1 ( ) 1 ( ) ( ) (
n
T
n
T n T n n T T n n T
) (
2
1
2 ) ( n
n
T n T +
|

\
|

=
140
Rezolvarea recurenei cazului mediu
Metoda master nu e aplicabil pentru recurena
Prin urmare, vom folosi metoda iteraiei:
Analiza algoritmilor Quicksort (5)
) (
2
1
2 ) ( n
n
T n T +
|

\
|

=
|
|

\
| +
+
|
|

\
| +
=
|
|

\
| +
|

\
|

+
|

\
|

=
(
(
(
(

\
|

+
|
|
|
|

\
|

=
|

\
|

|

\
|

+
|

\
|

=
(
(
(
(

\
|

+
|
|
|
|

\
|

=
|

\
|

+
|

\
|

=

1
1
1
1
1
1
2
2
3
3
2
2
2
2
2
1
1
2
2
2
1 2
2
2
1 2
2
2
1 2
2
2
3
2
2
7
2
2
3
2
1
2
3
2 2
2
3
2
2
1
2
2
3
2
2
1
2
1
2
1
2 2
2
1
2
) (
2
1
2 ) (
q
q
q
q
q
q
q
q
q
n n
T
n
T
n n
T
n
n
T
n
T
n n
T
n
n
T
n
T
n
n
T n T
141
Considernd condiia la limit T(1)=(1), recurena se termin pentru
Astfel, obinem:
1 ) 1 lg( ) 1 lg( 1 1 2 1
2
1 2
1
+ = + = + + = =
+
+
n q n q n
n
q
q
q
Analiza algoritmilor Quicksort (6)
( )
( )
) lg ( ) (
) 1 lg( ) (
) ( 1 ) 1 lg( ) ( ) (
) ( ) 1 ( 2 ) (
2
1 2
2 ) 1 ( 2 ) (
1 ) 1 lg(
1
1 ) 1 lg(
1 ) 1 lg(
1
1
1
1 1 ) 1 lg(
n n n T
n n n n n T
n n n n T
n n T
n
T n T
n
k
n
n
k
k
k
k n
=
+ + =
+ + =
+ =
|
|

\
|
|
|

\
|
+
+ =

+
=
+
+
=

+
142
Aplicaii
1. S se rezolve recurena aferent cazului cel mai defavorabil al
algoritmului de cutare binar folosind metoda iteraiei.
2. S se determine complexitatea temporal a algoritmului de
sortare prin interclasare (Mergesort). Pseudocodul algoritmului
este prezentat pe pagina urmtoare.
3. S se rezolve recurena aferent cazului cel mai favorabil al
algoritmului Quicksort folosind metoda iteraiei.
4. S se implementeze algoritmii de sortare prezentai.
5. Comparai algoritmii de sortare, pe un tablou mare, msurnd
timpii de execuie.
Analiza algoritmilor cutare i sortare
143
MERGESORT (X, primul, ultimul)
if primul<ultimul then
pivot (primul+ultimul)/2
MERGESORT (X, primul, pivot)
MERGESORT (X, pivot+1, ultimul)
MERGE (X, primul, pivot, ultimul)
Analiza algoritmilor mergesort
MERGE (X, primul, pivot, ultimul)
k primul
i primul
j pivot+1;
while ipivot and jultimul do
if X[i]<X[j] then
T[k] X[i]
k k+1
i i+1
else
T[k] X[j]
k k+1
j j+1
if j>ultimul then
for j i to pivot do
T[k] X[j]
k k+1
if i>pivot then
for i j to ultimul do
T[k] X[i]
k k+1
for i primul to ultimul do
X[i] T[i]
144
Analiza algoritmilor tabele de dispersie (1)
Funcii de dispersie
Mapeaz o cheie k ntr-una din cele m locaii ale tabelei de dispersie
Metoda diviziunii
Metoda nmulirii
Dispersia universal
unde cheia k s-a descompus n r+1 octei, astfel nct
k={k
0
, k
1
, ..., k
r
}, k
i
<m
a={a
0
, a
1
, ..., a
r
} valori alese aleator din mulimea {0, 1, ..., m-1}
m k k h mod ) ( =

1 0 , ) 1 mod ( ) ( < < = A kA m k h
, mod ) (
0

=
=
r
i
i i
m k a k h
145
Rezolvarea coliziunilor prin nlnuire
Elementele care se disperseaz n aceeai locaie se ncarc ntr-o list
nlnuit.
Locaia j conine un pointer ctre capul listei elementelor care se
disperseaz n locaia j, sau NULL dac nu exist astfel de elemente.
Operaia de cutare, n cazul cel mai defavorabil (cnd toate cele n
chei se disperseaz n aceeai locaie), este (n).
Analiza algoritmilor tabele de dispersie (2)
K (chei)
k
1
T
k
1
k
2
k
3
k
2
k
3
k
4
k
4
146
Rezolvarea coliziunilor prin adresare deschis
Toate elementele sunt memorate n interiorul tabelei de dispersie.
Locaia j conine elementul dispersat n locaia j sau NULL dac
nu exist un astfel de element.
Pentru inserare se examineaz succesiv tabela de dispersie,
ncepnd cu locaia indexat, pn la gsirea unei locaii libere.
Pentru cutarea unei chei se examineaz secvena de locaii
folosit de algoritmul de inserare. Cutarea se termin cu succes
dac se gsete cheia k sau fr succes dac se ntlnete o
locaie liber.
La tergerea unei chei nu poate fi marcat locaia ca fiind liber
pentru c ar face imposibil accesarea cheilor a cror inserare a
gsit aceast locaie ocupat. Prin urmare, locaia se marcheaz
cu o valoare special (TERS, -1, etc.). Evident c la inserare
locaiile marcate astfel se consider libere.
Analiza algoritmilor tabele de dispersie (3)
147
Verificarea liniar
Fiind dat o funcie de dispersie h, metoda verificrii liniare
folosete funcia de dispersie
pentru i=0, 1, ..., m-1.
n cazul accesrii tabelei de dispersie cu o cheie k, secvena
locaiilor examinate este:
T[h(k)], T[h(k)+1], ..., T[m-1], T[0], T[1], ..., T[h(k)-1].
Verificarea liniar poate genera grupri primare (iruri lungi de
locaii ocupate care tind s se lungeasc) crescnd timpul mediu
de cutare.
Analiza algoritmilor tabele de dispersie (4)
( ) m i k h i k h mod ) ( ) , ( +

=
148
Verificarea ptratic
Fiind dat funcia de dispersie h, verificarea ptratic folosete
o funcie de dispersie de forma
unde c
1
, c
2
0 sunt constante auxiliare i i=0, 1, ..., m-1.
Locaia verificat iniial este T[h(k)], urmtoarele locaii
examinate depinznd ntr-o manier ptratic de i.
Dac dou chei au aceeai poziie de start a verificrii, atunci
secvenele locaiilor verificate coincid:
Aceast situaie poate conduce la o form mai uoar de
grupare, numit grupare secundar.
Analiza algoritmilor tabele de dispersie (5)
( ) , mod ) ( ) , (
2
2 1
m i c i c k h i k h + +

=
) , ( ) , ( ) 0 , ( ) 0 , (
2 1 2 1
i k h i k h k h k h = =
149
Dispersia dubl
Se folosete o funcie de dispersie de forma:
unde h i h sunt funcii de dispersie auxiliare
Spre deosebire de verificarea liniar sau ptratic, secvena
locaiilor examinate depinde prin dou funcii de dispersie de
cheia k.
n cazul dispersiei duble, cnd cheia variaz, poziia iniial a
verificrii h(k) i decalajul h(k) pot varia independent,
evitnd astfel gruprile primare i secundare.
Analiza algoritmilor tabele de dispersie (6)
( ) , mod ) ( ) ( ) , ( m k h i k h i k h

+

=
150
Exerciii [Cor00]
1. Se consider o tabel de dispersie de dimensiune m=1000 i
funcia de dispersie
Calculai locaiile n care se pun cheile 61, 62, 63, 64 i 65.
2. Se consider c se insereaz cheile 10, 22, 31, 4, 15, 28, 17,
88, 59 ntr-o tabel de dispersie cu m=11 locaii folosind
adresarea deschis cu funcia primar de dispersie h=k mod
m. Ilustrai rezultatul inserrii acestor chei folosind verificarea
liniar, verificarea ptratic cu c
1
=1 i c
2
=3 respectiv
dispersia dubl cu h (k)=1+(k mod (m -1)).
Analiza algoritmilor tabele de dispersie (7)

2
1 5
, ) 1 mod ( ) (

= = A kA m k h
151
Arborele este o particularizare a unei structuri de date mai generale,
graful, care va fi prezentat n capitolul urmtor.
Utilizarea unei structuri arborescente binare face posibil inserarea
i tergerea rapid, precum i cutarea eficient a datelor.
Dac orice nod din arbore poate avea cel mult doi fii, atunci arborele se
numete arbore binar.
Pe lng un cmp cheie i date adiionale, fiecare nod al arborelui binar
conine cmpurile st, dr i p referine spre nodurile corespunztoare
fiului stng, fiului drept i printelui.
ntr-un arbore binar de cutare cheile sunt ntotdeauna astfel
memorate nct ele satisfac urmtoarea proprietate:
Fie x un nod dintr-un arbore binar de cutare. Dac y este un nod din
subarborele stng al lui x, atunci y.cheiex.cheie. Dac y este un nod din
subarborele drept al lui x, atunci y.cheiex.cheie.
Exemplu:
Analiza algoritmilor arbori binari (1)
6
3
2 5
7
8
152
Implementarea clasei Node n Java
public class Node {
int key; //cheia
float data; //alte informatii
Node leftChild; //fiul stang
Node rightChild; //fiul drept
Node parent; //parintele
public Node(int k){ //constructorul
key = k; //initializarea cheii
}
}
Analiza algoritmilor arbori binari (2)
153
Inserarea const n inserarea nodului z pe poziia corespunztoare n
arborele binar de cutare cu rdcina r.
INSEREAZA (z)
y NULL
x r
while xNULL do
y x
if z.cheie<x.cheie then
x x.st
else
x x.dr
z.p y
if y=NULL then
r z
else if z.cheie<y.cheie then
y.st z
else
y.dr z
Analiza algoritmilor arbori binari (3)
6
3
2 5
7
8
6
3
2 5
7
8
4
Inserarea nodului 4:
154
Implementarea inserrii n Java
public class BinaryTree {
Node root = null; //nodul radacina
public BinaryTree() {
insert(new Node(7)); //inserarea unui nod cu cheia 7
insert(new Node(1)); //inserarea unui nod cu cheia 1
insert(new Node(5)); //inserarea unui nod cu cheia 5
}
public void insert(Node z){
Node y = null; //parintele nodului curent x
Node x = root; //nodul curent
while(x!=null){ //deplasarea in jos in arbore
y=x;
if(z.key<x.key) x=x.leftChild; //deplasarea in jos pe subarborele stang
else x=x.rightChild; //deplasarea in jos pe subarborele drept
}
z.parent=y; //x==null, z este inserat pe aceasta pozitie null, cu y parinte
if(y==null) root=z; //daca parintele este null, z devine radacina arborelui
else if(z.key<y.key) y.leftChild=z; //setarea nodului z ca fiu stang al lui y
else y.rightChild=z; //setarea nodului z ca fiu drept al lui y
}
public static void main(String[] args) {
BinaryTree binaryTree1 = new BinaryTree();
}
}
Analiza algoritmilor arbori binari (4)
155
Traversarea arborelui n inordine viziteaz nodurile n ordinea cresctoare
a cheilor. Rdcina se viziteaz ntre nodurile din subarborele su stng i cele
din subarborele su drept. n exemplul anterior: 2, 3, 5, 6, 7, 8.
INORDINE (x)
if xNULL then
INORDINE (x.st)
AFIEAZ (x.cheie)
INORDINE (x.dr)
Traversarea arborelui n preordine viziteaz rdcina naintea nodurilor
din subarbori. n exemplul anterior: 6, 3, 2, 5, 7, 8.
PREORDINE (x)
if xNULL then
AFIEAZ (x.cheie)
PREORDINE (x.st)
PREORDINE (x.dr)
Traversarea arborelui n postordine viziteaz rdcina dup nodurile din
subarbori. n exemplul anterior: 2, 5, 3, 8, 7, 6.
POSTORDINE (x)
if xNULL then
POSTORDINE (x.st)
POSTORDINE (x.dr)
AFIEAZ (x.cheie)
Analiza algoritmilor arbori binari (5)
156
Cutarea unei chei
Cutarea returneaz nodul avnd cheia k dac exist sau NULL n caz contrar.
Cutarea recursiv
CAUTA_REC (x, k)
if x=NULL or k=x.cheie then
return x
if k<x.cheie then
return CAUTA_REC(x.st, k)
else
return CAUTA_REC(x.dr, k)
Cutarea iterativ (de obicei mai eficient dect varianta recursiv)
CAUTA_IT (x, k)
while xNULL and kx.cheie do
if k<x.cheie then
x x.st
else
x x.dr
return x
Analiza algoritmilor arbori binari (6)
157
Minimul determinarea nodului cu cheia minim dintr-un
arbore binar de cutare se realizeaz prin deplasare n jos pe
subarborele stng pn cnd se ajunge la un nod frunz.
MINIM (x)
while x.stNULL do
x x.st
return x
Maximul este nodul cu cheia maxim i se determin prin
deplasare n jos pe subarborele drept pn cnd se ajunge la un
nod frunz.
MAXIM (x)
while x.drNULL do
x x.dr
return x
Analiza algoritmilor arbori binari (7)
6
3
2 5
7
8
6
3
2 5
7
8
158
Succesorul unui nod x este nodul avnd cea mai mic cheie mai mare
dect cheia lui x, sau NULL, dac x are cea mai mare cheie din arbore.
Trebuie tratate dou alternative:
Dac x are subarbore drept, atunci succesorul lui x este nodul cu cheia
minim din acest subarbore. n exemplul anterior, succesorul lui 3 este 5.
Dac x nu are fiu drept, atunci succesorul lui x se determin traversnd
arborele de la x n sus pn cnd se ntlnete un nod care este fiu stng,
printele acelui nod fiind succesorul lui x. n exemplul anterior, succesorul
lui 5 este 6.
SUCCESOR (x)
if x.drNULL then
return MINIM (x.dr)
y x.p
while yNULL and x=y.dr do
x y
y y.p
return y
Analiza algoritmilor arbori binari (8)
6
3
2 5
7
8
Succesorul lui 3 este 5
Succesorul lui 5 este 6
159
tergerea unui nod z const n tratarea urmtoarelor trei
situaii:
Dac z nu are fii, se va modifica printele su pentru a-i nlocui fiul
z cu NULL.
Dac z are un fiu, z va fi eliminat prin setarea unei legturi de la
printele lui z la fiul lui z.
Dac z are doi fii, se va elimina din arbore succesorul y al lui z i
apoi se vor nlocui cheia i informaiile adiionale ale lui z cu cele
ale lui y.
Exemplu n care z are doi fii:
Analiza algoritmilor arbori binari (9)
15
5
3 12
16
20
13
10
6
7
18 23
z
y
15
6
3 12
16
20
13
10
7
18 23
160
Exemplu n care z are un singur fiu:
Exemplu n care z nu are fii:
Analiza algoritmilor arbori binari (10)
15
5
3 12
16
20
13
10
6
7
18 23
z
15
5
3 12
16
20
13
10
6
18 23
15
5
3 12
16
20
13
10
6
7
18 23
z
15
5
3 12
16
20
13
10
7
18 23
161
Algoritmul determin nodul y care se terge i reface legturile
(n al 3-lea caz chiar i cheia) nodurilor implicate
STERGE (z)
if z.st=NULL or z.dr=NULL then
y z
else
y SUCCESOR (z)
if y.stNULL then
x y.st
else
x y.dr
if xNULL then
x.p y.p
if y.p=NULL then
radacina x
else if y=y.p.st then
y.p.st x
else
y.p.dr x
if yz then
z.cheie y.cheie
return y
Analiza algoritmilor arbori binari (11)
162
Complexitatea operaiilor
Operaiile de baz pe arborii binari INSEREAZA, CAUTA, MINIM,
MAXIM, SUCCESOR i STERGE consum un timp proporional cu
nlimea arborelui.
Pentru un arbore binar relativ echilibrat cu n noduri, aceste operaii se
execut n cazul cel mai defavorabil ntr-un timp (lg n). n acest caz,
complexitatea temporal poate fi exprimat prin recurena
rezolvat deja pentru algoritmul de cutare binar.
Dac arborele binar este degenerat (ex. lan liniar de n noduri), atunci
timpul consumat n cazul cel mai defavorabil este (n).
Operaiile INORDINE, PREORDINE i POSTORDINE au nevoie de un
timp (n) pentru traversarea unui arbore binar de cutare cu n noduri.
Analiza algoritmilor arbori binari (12)
) 1 (
2
) ( +
|

\
|
=
n
T n T
163
Aplicaii
1. Fie secvena de valori: 4, 7, 2, 5, 3, 1, 6.
a) Reprezentai grafic arborele binar construit prin inserarea secvenei de valori de mai sus.
b) n ce ordine se afieaz valorile printr-o traversare n preordine? Dar printr-o traversare n
postordine?
c) Care este succesorul nodului cu cheia 4? Dar succesorul nodului cu cheia 6?
d) Reprezentai grafic arborele binar obinut dup tergerea nodului 4.
2. S se completeze clasa BinaryTree prezentat cu traversarea arborelui binar de cutare n
inordine, preordine i postordine.
3. S se implementeze n Java (n clasa BinaryTree) cutarea recursiv i cutarea iterativ a unei
chei n arborele binar.
4. S se introduc n clasa BinaryTree metode pentru determinarea cheii minime i maxime n
arborele binar de cutare.
5. S se implementeze n clasa BinaryTree o metod care s identifice succesorul unui nod n
arborele binar de cutare.
6. S se implementeze n clasa BinaryTree algoritmul de tergere a unui nod din arborele binar de
cutare.
7. S se modifice clasa Node i operaiile implementate n clasa BinaryTree astfel nct cheia s
fie numele studentului.
8. S se rezolve prin metoda iteraiei recurena aferent operaiilor de baz (inserare, cutare,
minim, maxim, succesor i tergere) pe un arbore binar de cutare echilibrat cu n noduri.
Analiza algoritmilor arbori binari (13)
164
Heap-ul (movila) este un arbore binar complet (pn la ultimul nivel) cu
urmtoarea proprietate:
orice nod dintr-un heap minimizant trebuie s aib o cheie mai mic (sau egal)
dect oricare dintre fiii si.
orice nod dintr-un heap maximizant trebuie s aib o cheie mai mare (sau egal)
dect oricare dintre fiii si.
Reprezentarea heap-urilor se face prin tablouri. ntr-un tablou indexat de la 1, fiii
nodului k au indicii 2k i 2k+1, iar printele nodului k are indicele k/2. ntr-un
tablou indexat de la 0 (ca n Java), fiii nodului k au indicii 2k+1 i 2k+2, iar
printele nodului k are indicele (k-1)/2. Exemplu de heap minimizant:
Heap-ul permite selecia rapid a elementului cu cheie minim sau maxim (care
este chiar rdcina), operaie realizat n O(1).
Heap-ul binar este slab ordonat n raport cu arborele binar de cutare, de aceea,
traversarea nodurilor n ordine este dificil.
Pentru o structur heap A notm cu A.size dimensiunea total a tabloului
respectiv A.heapsize dimensiunea heap-ului.
Analiza algoritmilor heap-uri (1)
5
34 27
49 53 42
1
2
3
4 5 6
5
34
27
42
53
49
1
2
3
4
5
6
165
Inserarea unui nod
Const n dou operaii:
Adugarea nodului pe ultimul nivel, sau pe un nou nivel dac arborele este
complet. n cazul reprezentrii prin tablouri, noul element se adaug n prima
poziie disponibil.
Propagarea n sus (spre rdcin) a nodului inserat pn la ndeplinirea condiiei
de heap.
Exemplu de inserare a valorii 3 ntr-un heap minimizant
Analiza algoritmilor heap-uri (2)
5
34 27
49 53 42
1
2
3
4 5 6
3
7
5
34 27
49 53 42
1
2
3
4 5 6
5
34 3
49 53 42
1
2
3
4 5 6
27
7
3
34 5
49 53 42
1
2
3
4 5 6
27
7
166
Determinarea printelui sau fiilor nodului cu indicele i ntr-un heap reprezentat prin tablou.
PARINTE (i)
return i/2
STANGA (i)
return 2i
DREAPTA (i)
return 2i+1
Inserarea nodului z n heap-ul minimizant A:
INSEREAZA (A, z)
A.heapsize A.heapsize+1
i A.heapsize
while i>1 and A[PARINTE(i)]>z do
A[i] A[PARINTE(i)]
i PARINTE(i)
A[i] z
Analiza algoritmilor heap-uri (3)
167
Extragerea rdcinii
Const n dou operaii:
Copierea ultimului nod n rdcin.
Propagarea n jos a rdcinii temporare pn la ndeplinirea condiiei de
heap (reconstituirea proprietii de heap). Propagarea se face spre fiul cu
cheia cea mai mic ntr-un heap minimizant respectiv spre fiul cu cheia
mai mare ntr-un heap maximizant.
Exemplu de extragere a rdcinii dintr-un heap minimizant
Analiza algoritmilor heap-uri (4)
3
34 5
49 53 42
1
2
3
4 5 6
27
7
27
34 5
49 53 42
1
2
3
4 5 6
5
34 27
49 53 42
1
2
3
4 5 6
168
La reconstituirea heap-ului se consider c subarborii care au ca rdcin
STANGA(i) respectiv DREAPTA (i) sunt heap-uri.
RECONSTITUIE (A, i)
s STANGA(i)
d DREAPTA(i)
if sA.heapsize and A[s]<A[i] then
min s
else
min i
if dA.heapsize and A[d]<A[min] then
min d
if mini then
A[i] A[min]
RECONSTITUIE (A, min)
EXTRAGE (A)
min A[1]
A[1] A[A.heapsize]
A.heapsize A.heapsize-1
RECONSTITUIE (A, 1)
return min
Analiza algoritmilor heap-uri (5)
169
Construcia heap-urilor
Prin reconstituirea recursiv a proprietii de heap de la nodul n/2 n
jos nodurile n/2+1...n sunt frunze i ndeplinesc condiia de heap:
CONSTRUIESTE (A)
A.heapsize A.size
for i A.size/2 downto 1 do
RECONSTITUIE (A, i)
Prin inserare repetat n heap considernd c primul element al
tabloului formeaz deja un heap:
CONSTRUIESTE (A)
A.heapsize 1
for i 2 to A.size do
INSEREAZA (A, A[i])
Analiza algoritmilor heap-uri (6)
170
Heapsort
Algoritmul heapsort ncepe cu apelul procedurii CONSTRUIESTE
prin care transform vectorul de intrare A n heap. Sortarea se
face prin interschimbarea repetat a rdcinii cu ultimul element
din heap urmat de excluderea lui din heap. Sortarea este
descresctoare cu un heap minimizant respectiv cresctoare cu
heap maximizant.
HEAPSORT (A)
CONSTRUIESTE (A)
for i A.size downto 2 do
A[1] A[i]
A.heapsize A.heapsize-1
RECONSTITUIE (A, 1)
Analiza algoritmilor heap-uri (7)
171
Complexitatea operaiilor n heap
Operaiile INSEREAZA, EXTRAGE i RECONSTITUIE sunt de complexitate O(lgn), la fel
ca operaiile ntr-un arbore binar de cutare (v. capitolul precedent).
Operaia de construire prin inserare repetat apeleaz de O(n) ori INSEREAZA de
complexitate O(lgn), deci, timpul total de execuie este O(nlgn).
n cazul operaiei de construire prin reconstituire recursiv se observ c nodurile de pe
ultimul nivel (aproximativ jumtate) ndeplinesc condiia de heap, deci nu sunt
propagate deloc. Nodurile de pe nivelul deasupra frunzelor (aproximativ un sfert) sunt
propagate cel mult un nivel. Nodul aflat n rdcin este propagat cel mult h-1 nivele,
(lgn rotunjit n jos). Astfel, numrul de propagri este
tim c pentru orice x subunitar
Astfel rezult c
Timpul de execuie al algoritmului heapsort este O(nlgn) deoarece CONSTRUIESTE se
execut n O(n) iar operaia RECONSTITUIE de O(lgn) este apelat de n-1 ori.
Analiza algoritmilor heap-uri (8)
( )

=

=
0
2
1
k
k
x
x
x k


= =
+ + + |
|

\
|
= = + + + +
n
k
n
k
k k k
k
n O k O
n
k
n n n n
lg
0
lg
0
1 1 1
2
) (
2 2
... 2
8
1
4
0
2

) (
2
1
1
2
1
2 2
1
2 2
2
0
lg
0
1
n O
n
O k
n
O
k
n O
k
k
n
k
k
=
|
|
|
|
|

\
|
|

\
|

=
|
|

\
|
|

\
|
=
|
|

\
|


= =
+
172
Aplicaii
1. Ilustrai modul de funcionare al procedurii CONSTRUIESTE, prin reconstituire
heap minimizant, pentru vectorul A={5,3,17,10,84,19,6,22,9}.
2. Ilustrai modul de funcionare al procedurii CONSTRUIESTE, prin inserare n
heap minimizant, pentru vectorul A={5,3,17,10,84,19,6,22,9}.
3. Ilustrai modul de funcionare al procedurii CONSTRUIESTE, prin reconstituire
heap maximizant, pentru vectorul A={5,3,17,10,84,19,6,22,9}.
4. Ilustrai modul de funcionare al procedurii CONSTRUIESTE, prin inserare n
heap maximizant, pentru vectorul A={5,3,17,10,84,19,6,22,9}.
5. Ilustrai modul de funcionare al procedurii HEAPSORT pentru vectorul
A={5,3,17,10,84,19,6,22,9}.
6. S se implementeze n Java operaiile de construire, inserare, extragere i
reconstituire.
7. S se implementeze n Java algoritmul heapsort.
8. S se rescrie funcia RECONSTITUIE pentru un heap maximizant.
9. S se implementeze n Java algoritmul heapsort folosind un heap maximizant,
astfel nct sortarea s se fac n ordine cresctoare.
10. S se adapteze i s se reutilizeze clasa Node de la arbori binari (cu informaie
suplimentar nume student) pentru heap-uri.
Analiza algoritmilor heap-uri (9)
173
Grafurile au o form determinat de o problem concret.
Nodurile grafului se numesc vrfuri i ele pot fi conectate prin muchii. Notm
un graf G=(V,E), unde V este mulimea vrfurilor i E este mulimea muchiilor.
Notm cu |V| numrul vrfurilor i cu |E| numrul muchiilor.
Fiecare vrf conine cmpurile i (index), c (color), d (distance/discovered), p
(predecessor), f (finalized).
Dou vrfuri se numesc adiacente dac sunt conectate direct printr-o muchie.
Un drum reprezint o secven de muchii.
Un graf se numete conex dac exist cel puin un drum ntre toate vrfurile.
Un graf n care muchiile nu au o direcie (deplasarea se poate face n orice sens)
se numete neorientat. Un graf n care muchiile au o singur direcie (marcat
prin sgeat) se numete orientat.
Un graf n care muchiile au asociate ponderi (costul drumurilor dintre vrfuri) se
numete ponderat.
Complexitatea unui algoritm pe un graf G=(V,E) se exprim n funcie de
dimensiunea intrrii descris prin doi parametri: numrul de vrfuri |V| i
numrul de muchii |E|. n cadrul notaiei asimptotice simbolul V nseamn |V|,
iar simbolul E nseamn |E|.
Analiza algoritmilor grafuri (1)
174
Podurile din Knigsberg
Analiza algoritmilor grafuri (2)
B
A
C
D
a
b
c
d
e
f
g
A
C
B
D
a
b
c
d
e
f
g
Unul dintre primii matematicieni care a
studiat grafurile a fost Leonhard Euler, n
secolul al XVIII-lea. El a rezolvat celebra
problem a podurilor din Knigsberg,
demonstrnd c nu exist un drum care s
cuprind toate cele apte poduri, fr a
traversa de dou ori acelai pod.
175
Implementarea clasei Vertex n Java
ntr-o implementare abstract vrfurile pot fi valori ntregi. n majoritatea aplicaiilor ns
pentru fiecare vrf trebuie pstrate mai multe informaii, ca n clasa Vertex de mai jos:
package graphs;
import java.awt.*;
public class Vertex {
Color color;
Vertex predecessor;
int distance;
int discovered; //for DFS
int finalized; //for DFS
char label;
int index;
int infinite = 100;
public Vertex(int i) {
index = i;
color = Color.white;
distance = infinite;
predecessor = null;
}
}
Analiza algoritmilor grafuri (3)
176
Reprezentarea grafurilor prin matrice de adiacen
Matricea de adiacen este un tablou bidimensional, n care elementele indic
prezena unei muchii ntre dou vrfuri. Dac graful are |V| vrfuri, numerotate
cu 1,2,...,|V| n mod arbitrar, matricea de adiacen este un tablou A=(a
ij
) cu
|V|x|V| elemente, unde
Matricea de adiacen poate fi folosit i pentru grafuri ponderate. n acest caz,
costul w(i,j) al unei muchii (i,j) E este memorat ca element din linia i i
coloana j a matricei de adiacen:
Avantajul const n verificarea rapid a adiacenelor. Dezavantajul const n
faptul c necesarul de memorie pentru matricea de adiacen a unui graf este
(V
2
) i nu depinde de numrul de muchii. Astfel, reprezentarea prin matrice de
adiacen este indicat n cazul grafurilor cu un numr relativ mic de vrfuri sau
atunci cnd graful este dens (|E| aproximativ egal cu |V|
2
).
Analiza algoritmilor grafuri (4)


=
. 0
, ) , ( 1
altfel
E j i dac
a
ij


=
. 0
, ) , ( ) , (
altfel
E j i dac j i w
a
ij
177
Implementarea n Java a unui graf neponderat reprezentat prin matrice de adiacen
package graphs;
import java.awt.*;
import java.util.*;
public class Graph {
int maxVerts = 20;
int nVerts = 0;
ArrayList vertexList = new ArrayList();
int A[][] = new int[maxVerts][maxVerts];
public Graph() {
for(int i=0; i<maxVerts; i++)
for(int j=0; j<maxVerts; j++)
A[i][j] = 0;
}
public void addVertex(){
vertexList.add(new Vertex(nVerts++));
}
public void addEdge(int v1, int v2){
A[v1][v2] = 1;
A[v2][v1] = 1;
}
Analiza algoritmilor grafuri (5)
public static void main(String[] args) {
Graph graph = new Graph();
graph.addVertex(); //0
graph.addVertex(); //1
graph.addVertex(); //2
graph.addVertex(); //3
graph.addEdge(0, 1);
graph.addEdge(1, 2);
graph.addEdge(0, 3);
}
}
1 2
3
0
178
Reprezentarea grafurilor prin liste de adiacen
Se folosete un tablou A cu |V| liste, cte una pentru fiecare
vrf din V. Pentru fiecare i V, lista de adiacen A[i] conine
toate vrfurile j pentru care exist o muchie (i,j) E.
Dac graful este orientat, suma lungimilor tuturor listelor de
adiacen este |E|. Dac graful este neorientat, lungimea total
a listelor de adiacen este 2|E| deoarece, dac (i,j) este o
muchie, atunci i apare n lista de adiacen a lui j dar i j apare
n lista de adiacen a lui i.
Dac graful este ponderat, costul w(i,j) al muchiei (i,j) E este
memorat mpreun cu vrful j n lista de adiacen a lui i.
Avantajul const n necesarul de memorie O(max(V,E)).
Reprezentarea prin liste de adiacen este preferat pentru c
ofer un mod compact de reprezentare a grafurilor rare (cu |E|
mult mai mic dect |V|
2
). Dezavantajul const n faptul c
verificarea adiacenelor implic operaii de cutare n liste.
Analiza algoritmilor grafuri (6)
179
Analiza algoritmilor grafuri (7)
Reprezentarea grafurilor neponderate. Exemple
Graf neorientat Listele de adiacen Matricea de adiacen
Graf orientat Listele de adiacen Matricea de adiacen
1 2
3
4 5
1 2
3
4 5
1 2 5
2 1 3 4 5
3 2 4
4 2 3 5
5 1 2 4
1 2 5
2 3 4
3 4
4 5
5 2
0 1 0 1 1 5
1 0 1 1 0 4
0 1 0 1 0 3
1 1 1 0 1 2
1 0 0 1 0 1
5 4 3 2 1
0 0 0 1 0 5
1 0 0 0 0 4
0 1 0 0 0 3
0 1 1 0 0 2
1 0 0 1 0 1
5 4 3 2 1
180
Analiza algoritmilor grafuri (8)
Reprezentarea grafurilor ponderate. Exemple
Graf neorientat Listele de adiacen Matricea de adiacen
Graf orientat Listele de adiacen Matricea de adiacen
0 21 0 17 15 5
21 0 29 18 0 4
0 29 0 26 0 3
17 18 26 0 12 2
15 0 0 12 0 1
5 4 3 2 1
1 2/12 5/15
2 1/12 3/26 4/18 5/17
3 2/26 4/29
4 2/18 3/29 5/21
5 1/15 2/17 4/21
1 2/12 5/15
2 3/26 4/18
3 4/29
4 5/21
5 2/17
1 2
3
4 5
12
15
17
18
21
26
29
1 2
3
4 5
12
15
17
18
21
26
29
0 0 0 17 0 5
21 0 0 0 0 4
0 29 0 0 0 3
0 18 26 0 0 2
15 0 0 12 0 1
5 4 3 2 1
181
Parcurgerea grafurilor n lime (breadth-first search)
Parcurgerea n lime a unui graf G=(V,E) pornete de la un vrf surs
s i exploreaz sistematic graful descoperind toate vrfurile accesibile
din s. Algoritmul calculeaz distana de la s la toate aceste vrfuri
accesibile.
Parcurgerea n lime lrgete uniform frontiera dintre vrfurile
descoperite i cele nedescoperite. Astfel, algoritmul descoper toate
vrfurile aflate la distana k fa de s nainte de cele aflate la distana
k+1.
Acest algoritm este implementat cu ajutorul unei cozi Q.
Pentru a ine evidena avansrii, parcurgerea n lime coloreaz fiecare
vrf cu alb (nedescoperit), gri (descoperit, cu lista de adiacen n curs
de explorare) sau negru (descoperit, cu lista de adiacen explorat).
Algoritmul pstreaz pentru fiecare vrf v V culoarea n v.c,
predecesorul n v.p i distana de la sursa s n cmpul v.d.
Complexitatea algoritmului const n operaiile efectuate cu coada
(fiecare vrf este inserat i scos o singur dat) cu un cost O(V) i n
examinarea listelor de adiacen cu un cost O(E), astfel timpul total de
execuie este O(V+E).
Analiza algoritmilor grafuri (9)
182
BFS (G, s)
foreach u V do
u.c ALB
u.d
u.p NULL
s.c GRI
s.d 0
Q.INSERT (s)
while Q do
u Q.HEAD
PRINT (u.i)
foreach v A[u] do
if v.c=ALB then
v.c GRI
v.d u.d+1
v.p u
Q.INSERT (v)
Q.DELETE (Q.HEAD)
u.c NEGRU
Analiza algoritmilor grafuri (10)
183
Implementarea n Java a parcurgerii grafurilor n lime
public void BFS(int s){
LinkedList queue = new LinkedList();
((Vertex)vertexList.get(s)).color = Color.gray;
((Vertex)vertexList.get(s)).distance = 0;
queue.addFirst(vertexList.get(s));
while(!queue.isEmpty()){
Vertex u = (Vertex)queue.getLast();
System.out.println(u.index);
for(int v=0; v<nVerts; v++)
if(A[v][u.index]==1 && ((Vertex)vertexList.get(v)).color==Color.white){
((Vertex)vertexList.get(v)).color = Color.gray;
((Vertex)vertexList.get(v)).distance = u.distance+1;
((Vertex)vertexList.get(v)).predecessor = u;
queue.addFirst(vertexList.get(v));
}
queue.removeLast();
u.color = Color.black;
}
}
Analiza algoritmilor grafuri (11)
184
Parcurgerea grafurilor n adncime (depth-first search)
Algoritmul exploreaz n adncime subgraful succesor al celui mai recent
descoperit vrf v dintr-un graf G=(V,E). Cnd toate muchiile care pleac din v
au fost explorate, algoritmul revine pentru explorarea urmtoarelor muchii care
pleac din predecesorul lui v.
Parcurgerea n adncime se implementeaz cu ajutorul stivei, fiind astfel natural
o abordare recursiv.
Pentru a ine evidena avansrii, parcurgerea n adncime coloreaz fiecare vrf
v V cu alb (nedescoperit), gri (descoperit, cu zona de graf accesibil din v n
curs de explorare) sau negru (descoperit, cu zona de graf accesibil din v
explorat).
Algoritmul pstreaz pentru fiecare vrf v V culoarea n v.c i predecesorul n
v.p. De asemenea, algoritmul folosete un ceas t al parcurgerii care crete
atunci cnd un nod i schimb culoarea. Algoritmul creeaz marcaje de timp
pentru fiecare vrf v V: momentul cnd v este descoperit (devine gri) este
pstrat n v.d, iar momentul n care explorarea zonei grafului accesibil din v a
fost finalizat este pstrat n v.f.
Marcajele de timp precum i predecesorii se pot folosi pentru o serie extins de
prelucrri.
Complexitatea algoritmului const n explorarea vrfurilor (V) i n examinarea
listelor de adiacen (E), astfel timpul total de execuie este (V+E).
Analiza algoritmilor grafuri (12)
185
DFS (G)
foreach u V do
u.c ALB
u.p NULL
t 0
foreach u V do
if u.c=ALB then
EXPLORARE (u)
EXPLORARE (u)
u.c GRI
PRINT (u.i)
u.d t t+1
foreach v A[u] do
if v.c=ALB then
v.p u
EXPLORARE (v)
u.c NEGRU
u.f t t+1
Analiza algoritmilor grafuri (13)
186
Drumuri minime. Algoritmul Dijkstra
Algoritmul de cutare n lime determin drumurile minime n grafuri
neponderate. Algoritmul Dijkstra permite determinarea drumurilor
minime de la vrful surs s ctre toate vrfurile unui graf ponderat cu
costuri nenegative. Astfel, vom presupune c w(u,v)0 pentru fiecare
muchie (u,v) E.
Pentru fiecare vrf v V algoritmul pstreaz n v.d estimarea drumului
minim fa de s, iar n v.p pstreaz predecesorul. Algoritmul folosete
o coad de prioriti Q iniializat cu V (conine toate vrfurile grafului).
La fiecare iteraie while, se extrage din Q vrful u cu drumul minim.
Pentru fiecare vrf v adiacent cu u se reactualizeaz v.d i v.p n cazul
n care drumul minim ctre v poate fi ameliorat dac trece prin u
(operaie de relaxare a muchiilor).
Complexitatea algoritmului const n extragerea minimului (operaie
O(V) efectuat de |V| ori) cu un cost O(V
2
) i n examinarea listelor de
adiacen (fiecare muchie este examinat o singur dat) cu un cost
O(E), astfel timpul total de execuie este O(V
2
+E)=O(V
2
).
Analiza algoritmilor grafuri (14)
187
DIJKSTRA (G, w, s)
foreach u V do
u.d
u.p NULL
s.d 0
Q V
while Q do
u MIN (Q, d)
Q Q-{u}
foreach v A[u] do
if v.d>u.d+w(u,v) then
v.d u.d+w(u,v)
v.p u
Analiza algoritmilor grafuri (15)
188
Cutare n spaiul strilor: algoritmul A*
A* (G, w, s, t) s=surs, t=int/target
foreach u V do
u.d
u.h
u.f
u.p NULL
s.d 0
s.h H (s, t) H=heuristic
s.f s.h
Q {s} Q=openset
C C=closedset
while Q do
u MIN (Q, f)
if u=t then return true
Q Q - {u}
C C U {u}
foreach v A[u] do
if v C then continue
if v Q then Q Q U {v}
if v.d>u.d+w(u,v) then
v.d u.d+w(u,v)
v.h H(v, t)
v.f v.d+v.h
v.p u
return false
Analiza algoritmilor grafuri (16)

189
Aplicaii
1. S se modifice clasa Graph, inclusiv metoda BFS,
astfel nct grafurile s fie reprezentate prin liste
de adiacen n loc de matrice de adiacen.
2. S se implementeze n clasa Graph algoritmul de
parcurgere a grafurilor n adncime.
3. S se implementeze n clasa Graph algoritmul
Dijkstra care s afieze drumurile minime ntr-un
graf ponderat. Ponderile notate cu w(u,v) pot fi
pstrate n matricea de adiacen A(u,v)
pentru asta e necesar adugarea unei noi
metode addEdge n clasa Graph.
Analiza algoritmilor grafuri (17)
Partea III
Proiectarea algoritmilor
191
Divide et impera este o metod de construire a algoritmilor.
Rezolvarea unei probleme prin aceast metod const n:
mprirea problemei n dou sau mai multe subprobleme de dimensiune
mai mic.
rezolvarea subproblemelor.
combinarea rezultatelor pentru obinerea soluiei problemei iniiale.
Divizarea problemei se poate face recursiv pn cnd subproblemele
devin elementare i pot fi rezolvate direct.
Forma general a algoritmului de rezolvare a problemei P de
dimensiune n cu soluia S:
DIVIZARE (P, n, S)
if nn
0
then
SOLUTIE (P, n, S)
else
SEPARARE (P, n) n (P
1
, n
1
), ..., (P
k
, n
k
)
DIVIZARE (P
1
, n
1
, S
1
)
...
DIVIZARE (P
k
, n
k
, S
k
)
COMBINARE (S
1
, ..., S
k
) n S
Proiectarea algoritmilor divide et impera (1)
192
Turnurile din Hanoi
Problema turnurilor din Hanoi a fost introdus n 1883 de
matematicianul francez douard Lucas. Problema are la baz o
legend hindus conform creia zeul Brahma a aezat n templul
din Benares o stiv de 64 de discuri din aur cu diametre diferite,
aezate n ordinea descresctoare a diametrelor. Clugrii
templului au sarcina de a muta toate discurile pe o alt tij
astfel nct:
La un moment dat doar un disc, aflat n vrful unei tije, poate fi
mutat pe o alt tij;
Nu este permis aezarea unui disc de dimensiune mai mare peste
un disc de dimensiune mai mic.
Conform legendei, lumea se va sfri atunci cnd clugrii i
vor termina treaba.
Proiectarea algoritmilor divide et impera (2)
193
Algoritmul HANOI
Algoritmul mut n discuri de pe tija A pe tija C folosind tija B.
Pentru asta, trebuie mutate n-1 discuri de pe A pe B prin C,
ultimul disc de pe A pe C i apoi n-1 discuri de pe B pe C prin A.
HANOI (n, A, C, B)
if n1 then
HANOI (n-1, A, B, C)
PRINT (A C)
HANOI (n-1, B, C, A)
Proiectarea algoritmilor divide et impera (3)
A B C A B C
194
Exemplu (n=2)
Proiectarea algoritmilor divide et impera (4)
A B C
A B C
A B C
A B C
A B
A C
B C
195
Complexitatea algoritmului HANOI
Numrul de mutri poate fi descris prin recurena
Aplicm metoda iteraiei:
Considernd condiia la limit T(0)=0, recurena se termin
pentru
Proiectarea algoritmilor divide et impera (5)
1 ) 1 ( 2 ) 1 ( 1 ) 1 ( ) ( + = + + = n T n T n T n T
( )
( )
1 1
2 3 2 2
1 2
0 1
2 ) ( 2 ) 1 ( 2
2 ) 3 ( 2 1 ) 3 ( 2 2 ) 2 ( 2
2 ) 2 ( 2 1 ) 2 ( 2 2 ) 1 ( 2
2 ) 1 ( 2 ) (

+ = +
+ = + =
+ = + =
+ =
q q q
q n T q n T
n T n T n T
n T n T n T
n T n T
n q q n = = 0
196
Am artat c la limit T(0)=0, q=n. Obinem
tim c
Rezult astfel c
Complexitatea algoritmului este O(2
n
), deci clugrii mai au
mult de lucru...

=
= + =
+ =
1
0
1
0
1
0
2 2 0 2 ) (
2 ) 0 ( 2 ) (
n
k
k
n
k
k n
n
k
k n
n T
T n T

=
+

=
n
k
n
k
x
x
x
0
1
1
1
1 2
1 2
1 2
) ( =

=
n
n
n T
Proiectarea algoritmilor divide et impera (6)
197
Aplicaii
1. Care din algoritmii prezentai anterior au la baz metoda
divide et impera?
2. S se implementeze n Java algoritmul de rezolvare a
problemei turnurilor din Hanoi.
3. Se d un tablou de valori ntregi. S se determine cel mai
mare divizor comun al valorilor din tablou prin metoda divide
et impera. Este evident c putem calcula separat cel mai
mare divizor comun pentru cele dou jumti ale tabloului,
iar soluia este cel mai mare divizor comun al celor dou.
Procesul de divizare continu pn cnd se ajunge la
subtablouri de un element.
Proiectarea algoritmilor divide et impera (7)
198
Algoritmii greedy aleg la fiecare moment cel mai bun candidat
posibil. Metoda greedy face optimizri locale, cu sperana c
acestea vor conduce la un optim global. Aceti algoritmi sunt de
obicei rapizi i furnizeaz o soluie relativ bun, dar nu
ntotdeauna cea mai bun. Forma general a unui algoritm
greedy:
GREEDY (C)
S
while C do
x BEST (C)
C C-{x}
if FEASIBLE (S U {x}) then
S S U {x}
Proiectarea algoritmilor greedy (1)
199
Problema fracionar a rucsacului
Se consider c dispunem de un rucsac cu o anumit
capacitate G (greutate maxim) i de n obiecte, definite prin
greutate g i pre p. S se umple rucsacul cu obiecte, astfel
nct valoarea total s fie maxim. Pot fi introduse i
fraciuni din obiecte.
Proiectarea algoritmilor greedy (2)
200
Algoritmul greedy pentru rezolvarea problemei fracionare a
rucsacului const n urmtorii pai:
1. v[i] p[i]/g[i], ;
2. sorteaz vectorii v, p, g n ordinea descresctoare a valorilor din v;
3. caut k astfel nct
soluia fiind
Timpul de execuie al algoritmului este O(nlgn), deoarece sortarea
se execut n O(nlgn), iar complexitatea operaiei de cutare din
pasul 3 este O(n).
Proiectarea algoritmilor greedy (3)

=
+
=
<
k
i
k
j
j i
g G g
1
1
1
n i , 1 =

+
=

=
k
i
i
i
k pentru g G
k i pentru g
1
1 ,
, 1 ,
201
Proiectarea algoritmilor greedy (4)
Coduri Huffman
Codificarea Huffman este o tehnic foarte util pentru compactarea datelor.
Algoritmul greedy propus de David Albert Huffman ofer o modalitate optim de
reprezentare a caracterelor prin coduri binare unice.
Fie un fiier cu 100 de caractere care conine doar literele a-f, cu urmtoarele
frecvene:
Dac folosim un cod binar de lungime fix, avem nevoie de trei bii pentru a
reprezenta ase caractere (a=000, b=001, ..., f=101). Aceast metod necesit
300 de bii pentru codificarea celor 100 de caractere din fiier.
O codificare cu lungime variabil, care atribuie coduri scurte caracterelor frecvente
i coduri lungi caracterelor cu frecven redus, poate codifica fiierul prin 224 de
bii (45x1+13x3+12x3+16x3+9x4+5x4), economisind 25% din spaiu.
O codificare optim pentru un fiier este reprezentat printr-un arbore binar
complet.
1100 1101 111 100 101 0 Cod cu lungime variabil
101 100 011 010 001 000 Cod cu lungime fix
5 9 16 12 13 45 Frecven
f e d c b a Caracter
202
Decodificarea
Codurile i lungimile acestora se genereaz de algoritm astfel
nct distincia simbolurilor este asigurat.
n exemplul anterior
a = 0
b = 101
c = 100
d = 111
e = 1101
f = 1100
Astfel, dac un cod ncepe cu 0 e format dintr-un singur bit i
este a. Dac ncepe cu 1, sigur e format din cel puin trei bii,
iar dac primii trei bii sunt 110 nseamn c exist i un al
patrulea bit, etc.
De exemplu, decodificnd pas cu pas secvena binar
1000110011010, vei obine cuvntul cafea.
Proiectarea algoritmilor greedy (5)
203
Construcia unui cod Huffman
Algoritmul Huffman pornete de la |C| frunze, fiecare
reprezentnd cte un caracter c C cu o frecven dat f[c].
Se realizeaz |C-1| operaii de fuzionare, pn la obinerea
arborelui final.
La fiecare pas, se aleg doi arbori (iniial frunze) cu frecvena cea
mai redus i se nlocuiesc cu arborele obinut prin fuzionarea
lor. Frecvena noului arbore este suma frecvenelor celor doi
arbori care au fuzionat.
Prin fuzionarea a doi arbori A
1
i A
2
se obine un nou arbore
binar, n care arborii A
1
i A
2
sunt fii stng respectiv drept al
rdcinii.
n arborele final frunzele sunt caracterele i interpretm codul
binar pentru un caracter ca fiind drumul de la rdacin pn la
frunza corespunztoare, unde o deplasare pe fiul stng este
reprezentat prin 0, iar o deplasare pe fiul drept prin 1.
Proiectarea algoritmilor greedy (6)
204
Construcia unui cod Huffman
Proiectarea algoritmilor greedy (7)
f:5 c:12 b:13 d:16 e:9 a:45 c:12 b:13 d:16
f:5 e:9
a:45 14
0 1
c:12 b:13
d:16
f:5 e:9
a:45 14
0 1
25
0 1
c:12 b:13 d:16
f:5 e:9
a:45
14
0 1
25
0 1
30
0 1
c:12 b:13 d:16
f:5 e:9
a:45
14
0 1
25
0 1
30
0 1
55
0 1
c:12 b:13 d:16
f:5 e:9
a:45
14
0 1
25
0 1
30
0 1
55
0 1
100
0
1
205
Algoritmul lui Huffman
HUFFMAN (C)
n |C|
Q C
for i 1 to n-1 do
z CREATENODE ()
x z.st MIN (Q)
Q Q-{x}
y z.dr MIN (Q)
Q Q-{y}
z.cheie x.cheie + y.cheie
Q.INSERT (z)
return MIN (Q)
Proiectarea algoritmilor greedy (8)
206
Complexitatea algoritmului Huffman
Presupunem implementarea structurii Q sub
forma unui heap binar.
Astfel, construirea lui Q prin reconstituire
heap, poate fi realizat n O(n).
Bucla for are n-1 iteraii n care apeleaz
operaii heap de complexitate O(lgn).
Rezult un timp total de execuie, pe o
mulime de n caractere, de O(nlgn).
Proiectarea algoritmilor greedy (9)
207
Aplicaii
1. S se ilustreze construcia arborelui Huffman pentru
urmtoarele caractere i frecvene:
C={p:100, q:17, r:2, x:58, y:80, z:5}
Decodificai apoi secvena binar 1111011001.
2. Stabilii o codificare Huffman pentru urmtoarea secven de
frecvene format din primele numere ale irului Fibonacci:
C={a:1, b:1, c:2, d:3, e:5, f:8, g:13, h:21}
3. Desenai arborele Huffman pentru cuvntul ABRACADABRA.
4. Care din algoritmii prezentai anterior au la baz strategia
greedy?
5. Implementai n Java algoritmul Huffman.
6. Implementai n Java problema fracionar a rucsacului.
Proiectarea algoritmilor greedy (10)
208
Conceptul de programare dinamic a fost introdus n
1957 de matematicianul american Richard Bellman.
Programarea dinamic, asemenea metodei divide et
impera, rezolv probleme combinnd soluiile unor
subprobleme.
Programarea dinamic este aplicabil atunci cnd
subproblemele au n comun sub-subprobleme.
Spre deosebire de metoda divide et impera, un
algoritm bazat pe programare dinamic rezolv
fiecare sub-subproblem o singur dat, memoreaz
soluia, evitnd astfel recalcularea.
Proiectarea algoritmilor programare dinamic (1)
209
Un prim exemplu: irul lui Fibonacci
irul lui Fibonacci este definit astfel:
Arborele recursiv pentru calculul F(5) este urmtorul:
n cazul implementrii recursive, termenii sunt determinai de mai multe ori: F(2)
de trei ori i F(3) de dou ori, pentru calculul F(5). Astfel, varianta recursiv are
complexitate exponenial: O(2
n
).
Varianta iterativ memoreaz tot timpul rezultatele, deci are la baz programarea
dinamic. Calculnd o singur dat termenii, complexitatea este liniar: O(n).
Proiectarea algoritmilor programare dinamic (2)

> +
=
=
=
1 ), 2 ( ) 1 (
1 , 1
0 , 0
) (
n n F n F
n
n
n F
F(5)
F(4) F(3)
F(3) F(2) F(2) F(1)
F(2) F(1) F(1) F(0) F(0) F(1)
F(1) F(0)
210
Cel mai lung subir cresctor
Fie A un ir de n numere ntregi. Se cere
determinarea subirului cresctor de lungime
maxim, nu neaprat contiguu, n irul A.
Pentru rezolvarea problemei construim vectorii:
L[i] = lungimea subirului cresctor care ncepe pe poziia i
i are ca prim element A[i].
S[i] = k, succesorul elementului A[i] n subirul cresctor, cu
L[k]=max{L[j]| j>i i A[j]>A[i]}, iar S[i]=-1 dac nu exist
un astfel de succesor.
Cel mai lung subir cresctor va ncepe pe acea
poziie i n A pentru care L[i] este maxim, iar afiarea
se poate face cu ajutorul vectorului S.
Proiectarea algoritmilor programare dinamic (3)
211
Algoritmul de determinare a subirului cresctor maximal
CMLSC (A)
imax n
for i n downto 1 do
S[i] -1
L[i] 1
for j i+1 to n do
if A[j]>A[i] and L[j]+1>L[i] then
L[i] L[j]+1
S[i] j
if L[i]>L[imax] then
imax i
i imax
while i-1 do
PRINT (A[i])
i S[i]
Proiectarea algoritmilor programare dinamic (4)
212
Proiectarea algoritmilor programare dinamic (5)
Exemplu:
Fie irul de ntregi:
A=3, 5, 76, 1, 45, 2, 68, 52, 90, 0, 4, 15
Aplicnd algoritmul CMLSC, obinem
Astfel, cel mai lung subir cresctor este:
3, 5, 45, 68, 90
-1 12 11 -1 9 9 7 7 5 9 5 2 S
1 2 3 1 2 2 3 3 4 2 4 5 L
15 4 0 90 52 68 2 45 1 76 5 3 A
1 2 3 4 5 6 7 8 9 10 11 12
213
Complexitatea algoritmului CMLSC
Operaiile din bucla for exterioar, de cost c
1
, sunt
apelate de n ori.
Numrul de apeluri ale operaiilor din bucla for interioar,
de cost c
2
, este
Operaiile din bucla while, de cost c
3
, sunt executate de
cel mult n ori.
Astfel, complexitatea algoritmului este
Proiectarea algoritmilor programare dinamic (6)
2
) 1 (
1 ... 2 1
1
1

= = + + +

=
n n
k n
n
k
) (
2
) 1 (
2 2
3 2 1
n O c bn an n c
n n
c n c = + + = +

+
214
Proiectarea algoritmilor programare dinamic (7)
Aplicaii propuse
1. Se consider un triunghi de numere, reprezentat ntr-o matrice A, ca
n exemplul de mai jos:
i o bil care cade n jos sau spre dreapta-jos. S se determine
drumul prin care bila ar strnge numrul maxim de puncte. Se va
folosi o matrice P de predecesori (-1=nu exist, 1=pas n jos, 0=pas
spre dreapta-jos) i o matrice S pentru sumele maxime.
2. Se dau poziiile de start i de final respectiv dimensiunea tablei de
ah. Se cere determinarea celui mai scurt drum al unui cal ntre cele
dou poziii. Se va folosi o matrice L care s pstreze lungimea
minim din fiecare poziie a tablei de ah i un tablou P de
predecesori.
31 9 71 32 89 65 54
23 56 87 11 90 32
15 26 52 3 41
7 35 14 2
10 6 4
81 82
10
215
Backtracking este o metod de cutare sistematic cu ncercri repetate i
reveniri n caz de nereuit.
Soluia este construit n mod progresiv, prin adugarea cte unei componente
S
k+1
la o soluie parial (S
1
,S
2
,...,S
k
) care reprezint o selecie din primele k
oferte din totalul celor n, astfel nct (S
1
,S
2
,...S
k
,S
k+1
) formeaz o nou soluie
parial.
Soluia final se obine n momentul n care selecia cuprinde toate cele n oferte,
deci k=n.
Metoda backtracking este n general ineficient, avnd complexitate
exponenial. De aceea, se folosete doar atunci cnd nu exist metode mai
eficiente de rezolvare a problemei.
Forma general a algoritmului backtracking recursiv:
BACKTRACKING (k)
for i 1 to n do
if ACCEPT (k, i) then
S[k] i
if FINAL(k) then
return S
else BACKTRACKING (k+1)
Proiectarea algoritmilor backtracking (1)
216
Problema celor n regine
Fie o tabl de ah de dimensiune n x n. Determinai toate
posibilitile de a amplasa n regine pe aceast tabl, astfel nct
ele s nu se atace reciproc. Dou regine se atac reciproc dac se
afl pe aceeai linie, coloan sau diagonal.
Prima observaie este c pe fiecare linie poate fi amplasat o
singur regin. Astfel, pentru o tabl de ah de dimensiune n x n,
problema celor n regine poate fi reprezentat printr-un tablou de n
elemente, unde S[k]=i semnific o regin amplasat pe poziia
(k,i) a tablei de ah.
Condiia ca dou regine i i j s nu fie pe aceeai coloan este
S[i]S[j].
Condiia ca dou regine i i j s nu fie pe aceeai diagonal este
|j-i||S[j]-S[i]|.
Pentru n=2 i 3 nu exist soluii, pentru n=4 sunt dou soluii, etc.
Proiectarea algoritmilor backtracking (2)
217
QUEENS (k)
for i 1 to n do
if ACCEPT(k, i) then
S[k] i
if k=n then
PRINT (S)
else QUEENS (k+1)
ACCEPT (k, i)
for j 1 to k-1 do
if S[j]=i then
return FALSE
if ABS(j-k)=ABS(S[j]-i) then
return FALSE
return TRUE
Proiectarea algoritmilor backtracking (3)
218
Aplicaii propuse
1. S se implementeze n Java algoritmul prezentat
pentru rezolvarea problemei celor n regine.
2. Fie o tabl de ah de dimensiune n x n. Determinai
toate posibilitile de a amplasa n ture pe aceast
tabl, astfel nct ele s nu se atace reciproc. Dou
ture se atac reciproc dac se afl pe aceeai linie
sau coloan.
3. Fie o tabl de ah de dimensiune n x n i poziia de
start a calului. S se determine toate drumurile
calului care s acopere toat tabla de ah i s
treac o singur dat prin toate poziiile.
Proiectarea algoritmilor backtracking (4)
219
Un algoritm genetic este o procedur iterativ de cutare global.
Algoritmul proceseaz o populaie de soluii poteniale (cromozomi) distribuite
peste ntreg spaiul de cutare.
Pentru rezolvarea unei probleme folosind un algoritm genetic este necesar
definirea unei funcii F care s evalueze performana fiecrui cromozom.
n fiecare iteraie se creeaz o nou populaie P, numit generaie. Toate
generaiile au acelai numr de indivizi. n general, noua generaie const din
indivizi mai performani.
Evoluia spre optimul global este asigurat prin recombinarea (ncruciarea) i
modificarea (mutaia) cromozomilor.
Condiia de oprire se refer, de regul, la atingerea unui anumit numr de
generaii ng.
Forma general a algoritmului genetic fundamental:
P
1
RANDOM()
for t 1 to ng do
EVALUARE (P
t
)
P = SELECTIE (P
t
)
P RECOMBINARE (P)
P
t+1
MODIFICARE (P)
Proiectarea algoritmilor algoritmi genetici (1)
220
Evaluarea populaiei de cromozomi
Selecia
Se calculeaz suma valorilor obinute n urma evalurii
Se determin probabilitile cumulative de selecie
Pentru selecia noii populaii se genereaz aleator n
c
valori
subunitare. Fiecare valoare r
i
generat aleator va selecta acel
cromozom c
k
pentru care r
i
[p
k
, p
k+1
].
Recombinarea a doi cromozomi const n interschimbarea unor
gene (bii).
Modificarea unui cromozom const n inversarea unor gene (bii).
Proiectarea algoritmilor algoritmi genetici (2)
c i i
n i c F v , 1 ), ( = =

=
=
c
n
i
i
v S
1
1 , , 1 ,
1
= = =

=
c
n c
j
i
i
j
p n j
S
v
p
221
Determinarea maximului unei funcii
Se va determina maximul unei funcii F(x), definit n exemplul nostru SIN(x).
Maximul se caut n intervalul [li, ls], deci x[li, ls].
Funcia X(v) normalizeaz valoarea v, aducnd-o n intervalul [li, ls].
Funciile GETBIT(v, i), SETBIT(v, i) i RESETBIT(v, i) preiau, seteaz respectiv
reseteaz bitul de pe poziia i din v.
Funcia INCRUCISARE(C, p1, p2) recombin biii cromozomilor p1 i p2.
Funcia MUTATIE(C, p) modific cromozomul p.
Funcia INITIALIZARE iniializeaz populaia de cromozomi cu valori generate aleator.
Funcia SELECTIE evalueaz populaia de cromozomi i genereaz o populaie nou
pstrnd doar cromozomii performani.
Funcia RECOMBINARE realizeaz o selecie n vederea ncrucirii.
Funcia MODIFICARE realizeaz operaia de mutaie a populaiei de cromozomi.
Funcia MAX reprezint algoritmul genetic n sine, care determin maximul funciei
F(x), cu x[li, ls]. Funcia folosete o populaie C de nc cromozomi. Cutarea se
termin dup ng=50 de generaii.
Proiectarea algoritmilor algoritmi genetici (3)
222
li 0
ls 2
nc 500
ng 50
pincrucisare 0.3
pmutatie 0.1
X (v)
return li+v/65535*(ls-li)
F (x)
return SIN (x)
GETBIT (v, i)
return v>>i&1
SETBIT (v, i)
return v|(1<<i)
RESETBIT (v, i)
return v&~(1<<i)
Proiectarea algoritmilor algoritmi genetici (4)
223
INCRUCISARE (C, p1, p2)
v1 C[p1]
v2 C[p2]
r RANDOM (0, 16)
for j r to 16 do
if GETBIT(v2, j)=1 then
SETBIT(C[p1], j)
else RESETBIT(C[p1], j)
if GETBIT(v1, j)=1 then
SETBIT(C[p2], j)
else RESETBIT(C[p2], j)
MUTATIE (C, p)
cp C[p]
for j 1 to 16 do
if pmutatie>RANDOM(0, 1) then
if GETBIT(cp, j)=1 then
RESETBIT(cp, j)
else SETBIT(cp, j)
if F(X(cp))>F(X(C[p])) then
C[p] cp
Proiectarea algoritmilor algoritmi genetici (5)
224
INITIALIZARE (C)
for i 1 to nc do
C[i] RANDOM(0, 65536)
xmax X(C[1])
fmax F(xmax)
SELECTIE (C)
s 0
for i 1 to nc do
V[i] F(X(C[i]))
s s+V[i]
P[1] V[1]/s
for i 2 to nc do
P[i] P[i-1]+V[i]/s
for i 1 to nc do
r RANDOM(0, 1)
for j 1 to nc do
if r>P[j] and rP[j+1] then
C[i] C[j]
for i 1 to nc do
C[i] C[i]
Proiectarea algoritmilor algoritmi genetici (6)
225
RECOMBINARE (C)
primul TRUE
for i 1 to nc do
if RANDOM(0, 1)<pincrucisare then
if primul then
primul FALSE
p1 i
else
primul TRUE
p2 i
INCRUCISARE (C, p1, p2)
MODIFICARE (C)
for i 1 to nc do
MUTATIE (C, i)
Proiectarea algoritmilor algoritmi genetici (7)
226
MAX (ng)
INITIALIZARE (C)
for t 1 to ng do
SELECTIE (C)
RECOMBINARE (C)
MODIFICARE (C)
maxiteri 1
maxiterf F(X(C[1]))
for i 2 to nc do
if F(X(C[i]))>maxiterf then
maxiteri i
maxiterf F(X(C[i]))
if maxiterf>fmax then
fmax maxiterf
xmax X(C[maxiteri])
PRINT (xmax, fmax)
Proiectarea algoritmilor algoritmi genetici (8)
227
Aplicaii propuse
1. S se implementeze n Java algoritmul genetic prezentat.
2. S se modifice algoritmul genetic prezentat astfel nct s
determine minimul unei funcii. S se implementeze
algoritmul modificat n Java.
3. S se implementeze un algoritm genetic pentru rezolvarea
problemei comis-voiajorului (traveling salesman problem). Se
consider n orae i se cunosc distanele dintre oricare dou
orae. Un comis-voiajor trebuie s treac prin toate cele n
orae. Se cere s se determine drumul minim care s
porneasc dintr-un ora oarecare, s treac o singur dat
prin toate oraele celelalte i s revin n oraul iniial.
Proiectarea algoritmilor algoritmi genetici (9)
228
Reelele neuronale sunt folosite pentru rezolvarea unor
probleme dificile, cum sunt cele de estimare, identificare i
predicie.
Exist probleme practice de mare complexitate pentru care
elaborarea unui algoritm este dificil sau chiar imposibil.
Pornind de la o mulime de exemple, reelele neuronale sunt
capabile s sintetizeze un model al problemei. Un mare avantaj
al reelelor neuronale const n capacitatea lor de a nva din
exemple i apoi s trateze cazuri similare.
Reelele neuronale sunt formate dintr-o multitudine de neuroni,
elemente simple de calcul care opereaz n paralel.
Modelul de neuron a fost propus de McCulloch i Pitts n 1943.
Hebb a introdus n 1949 un mecanism de nvare prin
modificarea conexiunilor sinaptice dintre neuroni. Rosenblatt a
propus apoi n 1957 primul model de reea neuronal numit
perceptron, care interconecteaz o mulime de neuroni.
Proiectarea algoritmilor reele neuronale (1)
229
Perceptronul multistrat
Structura perceptronului multistrat cu un singur strat ascuns este
prezentat n figura urmtoare:
Fiecare intrare x
i
ntr-un neuron are asociat o pondere w
i
. Ieirea
neuronului se obine prin nsumarea ponderat a intrrilor,
asupra creia se aplic o funcie de activare.
Proiectarea algoritmilor reele neuronale (2)
V
IN
V
HID
V
OUT
x
1
x
N
o
1
o
P

=
=
n
i
i i
x w y
1
230
Proiectarea algoritmilor reele neuronale (3)
Funcii de activare
Funcia de activare are rolul de a restrnge domeniul de variaie al
ieirii neuronului. Cele mai uzuale funcii de activare sunt urmtoarele:
Vom folosi n continuare funcia de activare
care restrnge ieirea neuronului la intervalul (-1, 1).
y
e
y f

+
=
1
1
) (
y
y
y
y
e
e
y f

=
1
1
) (
1
1
-1
y
y
e
e
y f

=
1
1
) (
231
Algoritmul de nvare backpropagation [Mit97]
Algoritmul backpropagation ajusteaz ponderile reelei neuronale astfel
nct eroarea s scad
Algoritmul de nvare backpropagation, cu funcia de activare
i intrri codificate cu -1 i 1, const n urmtorii pai:
1. Se creeaz o reea neuronal cu N intrri, M uniti ascunse i P
uniti de ieire.
2. Se iniializeaz ponderile
cu valori aleatoare mici [Mit97] din intervalul (-0.05, 0.05).
Proiectarea algoritmilor reele neuronale (4)
y
y
e
e
y f

=
1
1
) (
P k M j w
M j N i w
jk
ij
, 1 ; , 1 ;
, 1 ; , 1 ;
2
1
= =
= =
232
3. Ct timp repet
3.1. Se aplic reelei intrarea i se calculeaz ieirea
3.2. Pentru fiecare neuron din stratul de ieire
se calculeaz eroarea fa de valoarea corect t
k
Proiectarea algoritmilor reele neuronale (5)
1
X
2
O
P k net f o
P k x w net
M j net f o x
M j x w net
k k
M
j
j jk k
j j j
N
i
i ij j
..., , 1 ), (
..., , 1 ,
..., , 1 ), (
..., , 1 ,
2 2
1
2 2 2
1 1 2
1
1 1 1
= =
= =
= = =
= =

=
=
P k k , 1 , =
2
k

( ) ( ) ( )
2 2 2 2 2 2
1
2
1
) (
k k k k k k k k
o o o t net f o t =

=
( ) ( ) T o t W E
P
k
k k
> =

=1
2
2
2
1
233
3.3. Pentru fiecare neuron din stratul de ieire
se calculeaz eroarea
3.4. Se actualizeaz toate ponderile reelei neuronale
unde este rata de nvare.
Proiectarea algoritmilor reele neuronale (6)
M j j , 1 , =
1
j

( )

= =
=

=
P
k
jk k j j
P
k
j jk k j
w o o net f w
1
2 2 1 1
1
1 2 2 1
1
2
1
) (
M j N i x w w
P k M j x w w
i j ij ij
j k jk jk
, 1 , , 1 ,
, 1 , , 1 ,
1 1 1 1
2 2 2 2
= = + =
= = + =

234
Aplicaii propuse
1. S se rescrie algoritmul backpropagation pentru funcia de
activare
2. S se implementeze n Java o reea neuronal cu un strat
ascuns care, pe baza algoritmului backpropagation prezentat, s
nvee cifrele 0-9.
3. S se implementeze n Java o reea neuronal cu un strat
ascuns care, folosind algoritmul backpropagation, s nvee
literele alfabetului limbii engleze.
Proiectarea algoritmilor reele neuronale (7)
y
e
y f

+
=
1
1
) (
235
Nota final
Nota laborator (NL) = 0,2*T1 + 0,2*T2 + 0,1*A + 0,5*C
Nota final = 0,5*NL + 0,5*E
T1 = Test gril susinut din noiunile predate n cadrul
capitolului Limbajul Java;
T2 = Test susinut la laborator din aplicaiile propuse la
laborator n cadrul capitolului Limbajul Java;
A = Activitatea la laborator (teme);
C = Colocviu de laborator din aplicaiile propuse la laborator n
cadrul capitolelor Analiza algoritmilor respectiv Proiectarea
algoritmilor;
E = Examen susinut din capitolele Analiza algoritmilor i
Proiectarea algoritmilor.
236
Bibliografie
Algoritmi
[Knu00] Knuth D., Arta programrii calculatoarelor, Vol. 1 Algoritmi fundamentali, Teora, 2000.
[Knu02] Knuth D., Arta programrii calculatoarelor, Vol. 3 Sortare i cutare, Teora, 2002.
[Cor00] Cormen T., Leiserson C., Rivest R., Introducere n algoritmi, Agora, 2000.
[Giu04] Giumale C., Introducere n analiza algoritmilor, Polirom, 2004.
[Log07] Logoftu D., Algoritmi fundamentali n Java, Polirom, 2007.
[Wai01] Waite M., Lafore R., Structuri de date i algoritmi n Java, Teora, 2001.
[Cri98] Cristea V., Athanasiu I., Kalisz E., Iorga V., Tehnici de programare, Teora 1998.
[Mit97] Mitchell T., Machine Learning, McGraw-Hill, 1997.
Programare n Java
[Rob00] Roberts S., Heller P., Ernest M., Complete Java 2 Certification, Second Edition, SYBEX, USA, 2000.
[Cha01] Chan M., Griffith S., Iasi A., Java 1001 secrete pentru programatori, Teora, 2000.
[Tan07] Tanas ., Andrei ., Olaru C., Java de la 0 la expert, Polirom, 2007.
[Hun01] Hunter J., Crawford W., Java Servlet Programming, Second Edition, OReilly, USA, 2001.
[Gea01] Geary D., Advanced JavaServer Pages, Prentice Hall, USA, 2001.
[Gor98] Gordon R., Java Native Interface, Prentice Hall, USA, 1998.
237
Webliografie
[Web01] http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html
[Web02] http://www.javapassion.com/javaintro/
[Web03] http://thor.info.uaic.ro/~acf/java/curs/cursuri.html
[Web04] http://labs.cs.utt.ro/labs/sdaa/html/LabSDA.html
[Web05] http://www.personal.kent.edu/~rmuhamma/Algorithms/algorithm.html