Documente Academic
Documente Profesional
Documente Cultură
An 2 Sem 2 - 2010 Teh Av. Programare Curs 1
An 2 Sem 2 - 2010 Teh Av. Programare Curs 1
1. Recapitulare (OOP folosind Java) 2. Programare generica (STL-C++) 3. Metode de elaborarea algoritmilor (Greedy, Programare dinamica, Divide et impera, backtracjing, Branch & Bound) 4. Programare concurenta in Java (fire de executare)
*************************************************************
fie partajat de obiectele din ierarhie, pentru fiecare obiect subprogramul ac#ion|nd conform propriilor necesit{#i. Din cele de mai sus observ{m c{ obiectele sunt mai puternice ca modulele. Obiectele pot fi privite ca ni~te capsule care limiteaz{ accesul neautorizat la datele interne ~i la anumite subprograme. Exist{ restric#ii de acces chiar ~i pentru membrii unei ierarhii. Dac{ datele unui obiect descriu starea sa, subprogramele, numite metode }n cadrul program{rii orientate spre obiecte, descriu interac#iunea unui obiect cu mediul. Prin intermediul metodelor obiectele pot comunica unele cu altele. Apelul unei metode se nume~te ~i transmitere de mesaj. O mul#ime de obiecte de acela~i fel formeaz{ o clas{ care poate fi descris{ prin modelul comun al obiectelor sale. O clas{ este similar{ no#iunii de tip de date abstract din limbajele de programare conven#ionale precum Ada ~i Modula-2. Totu~i, }n limbajele conven#ionale, nu se pot construi tipuri noi de date pornind de la tipuri existente. Clasele au diverse roluri }n programarea orientat{ obiect: furnizeaz{ mecanismul prin care se pot identifica obiecte cu acelea~i propriet{#i; reprezint{ un mecanism de structurare similar subprogramelor ~i modulelor. Exist{ o rela#ie de tip unula mai mul#i }ntre obiecte ~i clase. Mai precis, fiecare obiect apar#ine unei singure clase, dar o clas{ poate con#ine mai multe obiecte. Dac{ C este o clas{, iar x este un obiect al clasei C, se mai spune c{ x este o instan#{ a clasei C. No#iunea de obiect dateaz{ din anii 60, odat{ cu apari#ia limbajului Simula. ]n prezent exist{ at|t limbaje procedurale dezvoltate pentru a oferi posibilitatea lucrului cu obiecte (Pascal, C++, etc.) c|t ~i limbaje obiectuale pure (Smalltalk, Eiffel, Java etc.). ]n cele ce urmeaz{ continu{m prezentarea terminologiei utlizate }n cadrul program{rii orientate spre obiecte folosind limbajul Java. Se presupun cunoscute elementele de baz{ ale limbajului C.
patrat (double latura){ super(latura, latura);} double latura(){return this.latime;} } class testpatrat{ public static void main(String[] args){ patrat x = new patrat(10); System.out.println(Dimensiunile patratului sunt: ); System.out.println(x.lungime+ : +x.latime); System.out.println(sau, folosind metoda latura(): +x.latura()); System.out.println(Suprafata patratului este:); System.out.println(x.suprafata()); } } ]n exemplul de mai sus sunt definite trei clase: dreptunghi, patrat ~i testpatrat. Clasa patrat extinde clasa dreptunghi care se nume~te superclas{ a clasei patrat. Elementele clasei dreptunghi sunt: c|mpurile lungime ~i latime care definesc starea unei instan#e particulare a clasei ~i metodele: perimetrul() ~i suprafata(). Identificatorul x se refer{ la o instan#{ a clasei patrat, c|nd este declarat prin patrat x; ~i este efectiv un obiect c|nd este creat dinamic folosind operatorul new: patrat x; x = new patrat(10); sau patrat x = new patrat(10); Deoarece clasa patrat extinde clasa dreptunghi, x este un obiect compatibil cu clasa dreptunghi, el se refera la un dreptunghi particular. Are sens s{ acces{m datele obiectului x prin x.lungime, respectiv prin x.latime. Sunt definite metodele dreptunghi ~i patrat, identificatorii fiind identici cu numele clasei pentru care o metod{ este definit{. Aceste metode se numesc constructori. Constructorii sunt apela#i la crearea unui obiect (observa#i apelurile precedate de new) ~i returneaz{ un obiect (o instan#{) apar#in|nd clasei corespunz{toare. Trebuie spus c{ nu trebuie utilizat{ instruc#iunea return }n corpul unui constructor ~i nici cuv|ntul void }n antetul constructorului. Obiectul this desemneaz{ obiectul curent. La apelul x.latura() se returneaz{ valoarea stocat{ }n c|mpul latime al obiectului. O alt{ utilizare a cuv|ntului cheie this este exemplificat{ prin: public class Cerc{ public double xc,yc,r; // centrul(xc,yc) si raza r //urmeaza mai multi constructori public Cerc(double x, double y, double r) { xc=x; yc=y; this.r = r; } public Cerc(double r){ xc=0.0; yc=0.0; this.r=r;} public Cerc(Cerc a){ xc=a.xc; yc=a.yc; r=a.r;} public Cerc(){xc=0.0; yc=0.0; r=1.0;}
// metode specifice comportamentului public double lungimea(){return 2*3.14159*r:} public double suprafata(){return 3.14159*r*r;} } Dup{ cum se vede }n acest exemplu, o clas{ poate avea mai mul#i constructori. Definirea mai multor metode cu acela~i nume, dar cu argumente sau tipuri diferite se nume~te supra}nc{rcarea metodelor. Totu~i, cuv|ntul this poate fi utilizat ~i cu alt }n#eles. ]n exemplul care urmeaz{, construc#ia this() apare numai ca prima instruc#iune }n corpul unui constructor ~i desemneaz{ apelul constructorului clasei }n care apare. Se consider{ clasa Cerc definit{ mai sus ~i se descriu c|#iva constructori: public Cerc (double xc, double yc, double r){ //prima forma a lui this this.xc=xc; this.yc=yc; this.r=r; } public Cerc (double r){this(0.0, 0.0, r);}//a doua forma public Cerc (Cerc a){this(a.xc, a.yc, a.r);} public Cerc (){this(0.0, 0.0, 1.0);} S{ observ{m variabilele xc, yc ~i r care descriu starea oric{rei instan#e a clasei Cerc. Orice obiect va avea starea sa stocat{ }n aceste c|mpuri (fiecare obiect va avea o copie a variabilelor xc, yc, r). Astfel de variabile se numesc variabile instan#{. Observa#i c{ declara#ia acestora este precedat{ de cuv|ntul cheie public. De~i variabilele lungime ~i latime din primul exemplu, nu sunt precedate de public ele tot variabile instan#{ sunt. Exist{ ~i variabile specifice clasei. Acestea sunt globale tuturor instan#elor. Ele sunt precedate de cuv|ntul cheie static. Vom exemplifica, redefinind clasa Cerc astfel }nc|t s{ avem un indicator al num{rului de obiecte create. public class Cerc{ static int contor_cerc = 0; public static final double PI=3.14159265358979323846; public double xc,yc,r; public Cerc(double xc, double yc, double r){ this.xc=xc; this.yc=yc; this.r=r; contor_cerc ++;} public Cerc(double r){this(0.0, 0.0, r);} public Cerc(Cerc a){this(a.xc, a.yc, a.r);} public Cerc(){this(0.0, 0.0, 1.0);} public double lungimea(){return 2*Cerc.PI*r;} public double suprafata(){return Cerc.PI*r*r;} } public class TestMain { // Metoda main public static void main(String[] args){ Cerc c1= new Cerc(); Cerc c2= new Cerc(3.0, 3.0, 10.0); Cerc c3= new Cerc(c1); c3.r = 10; System.out.println(Au fost create + Cerc.contor_cerc+ cercuri.);} }
Deoarece variabilele statice sunt asociate clasei ~i nu obiectelor, aceste variabile sunt accesate prin intermediul identificatorului clasei: Cerc.contor_cerc. S{ observ{m prezen#a cuv|ntului cheie final care introduce o constant{ a clasei. Aceast{ definire elimin{ posibilitatea de a modifica PI prin instruc#iuni de atribuire: Cerc.PI=2;. Urm{rind exemplele de mai sus observ{m c{ declararea unei clase con#ine cuv|ntul cheie class ~i identificatorul clasei.
starea clasei sau a obiectelor. Formatul general pentru declararea unei variabile membru este: [mod_acces] [static][final][transient][volatile] tip Nume_Variabila; unde: mod_acces determin{ clasele care au acces la o variabil{ membru. Pentru a specifica modul de acces se utilizeaz{ unul dintre cuvintele rezervate: public, protected, package sau private. static - indic{ o variabil{ a clasei ~i nu o variabil{ instan#{. O modificare asupra variabilei face ca variabila s{ aib{ aceea~i valoare pentru toate instan#ele clasei (vezi variabila contor_cerc). final - define~te o constant{ care se ini#ializeaz{ }n declararea sa (vezi declararea constantei PI). transient indic{ faptul c{ variabila nu este o component{ a st{rii persistente a obiectului, iar volatile indic{ posibilitatea modific{rii variabilei din motive de optimizare. tip - indic{ tipul variabilei: byte (}ntreg pe 8 bi#i, cod direct), short (}ntreg pe 16 bi#i, complement fa#{ de doi), int (}ntreg pe 32 de bi#i, complement fa#{ de doi), long (}ntreg pe 64 de bi#i, complement fa#{ de doi), float (reprezentare IEEE754 pe 32 de bi#i), double (reprezentare IEEE 754 pe 64 de bi#i), char (caracter Unicode, pe 16 bi#i), boolean (valoare boolean{ (true sau false) pe 1 bit), tablou (declarare ca }n C, cu alocarea spa#iului folosind new), clas{ (class ca mai sus) sau interfa#{. Nume_Variabila - desemneaz{ identificatorul variabilei. ]ntr-o clas{ nu pot fi declarate mai multe variabile cu acela~i nume, dar o variabil{ membru ~i o metod{ pot avea acela~i nume.
Mod_Acces - indic{ modul de acces al altor clase la metod{. Accesul se specific{ prin utilizarea unuia dintre cuvintele cheie: public, protected, package sau private. static - indic{ o metod{ a clasei, nu o metod{ a instan#elor. ]n pachetul java.lang este definit{ clasa Math care introduce constantele matematice E ~i PI, ~i define~te metodele statice pentru calcul trigonometric, exponen#ial, logaritmic, ~i alte func#ii precum }n fi~ierul antet math.h din C. Exemplific{m descriind o metod{ care verific{ dac{ un punct este }n interiorul unui cerc: public class Cerc{ private double xc, yc, r; // constructori // alte metode public double interior(double x, double y){ double dx = x - xc; double dy = y - yc; double dist = Math.sqrt(dx*dx+dy*dy); if (dist<r) return true; else return false; } //alte metode } abstract - indic{ o metod{ abstract{ care nu are implementare; ea trebuie s{ apar#in{ unei clase abstracte. O clas{ abstract{ A poate avea subclase, aceastea sunt r{spunz{toare de implementarea metodelor definite ca abstracte }n A. ]n acest fel, o clas{ abstract{ poate fi utilizat{ pentru a defini o interfa#{ de programare complet{ (programming interface). Sintaxa unei clase abstracte este: abstract class Nume_Clasa_A { tip_1 nume_Var_1; tip_2 nume_Var_2; ........ tip_Rezultat_1 nume_Metoda_1(){ corp implementat} ........ abstract tip_Rezultat_n nume_Metoda_n(); //metoda abstracta ........ } Metoda nume_Metoda_n() va fi implementat{ diferit }n sublasele derivate din Nume_Clasa_A: class Nume_Clasa_B extends Nume_Clasa_A { ........ tip_Rezultat_n nume_Metoda_n() { corp implementat } ........} class Nume_Clasa_C extends Nume_Clasa_A { ........ tip_Rezultat_n nume_Metoda_n(){ corp implementat } ........
} final - indic{ o metod{ care nu va putea fi rescris{ }n clasele extinse (numite subclase sau clase derivate). Toate metodele declarate static ca ~i cele declarate final precum ~i toate metodele unei clase declarate cu final sunt implicit finale. native - indic{ implementarea metodei }ntr-un alt limbaj de programare (de exemplu C, C++ etc.) syncronized - indic{ posibilitatea ca metoda s{ fie utilizat{ concuren#ial. Procesele care se execut{ }n mod concurent apeleaz{ deseori metode ce opereaz{ cu acelea~i date. Aceste metode trebuie declarate syncronized pentru a asigura accesul exclusiv la informa#ie (o modalitate pentru a rezolva problema excluderii mutuale }n sisteme concurente). Tip_Rezultat - indic{ tipul datei returnate de metod{. Valoarea de retur poate fi de tip numeric (}ntregi, IEEE754, caracter, logic), structurat (tablou, clasa sau interfata) sau descris{ prin void, prin care se specific{ inexisten#a unei valori de retur. Nu este definit un tip de retur implicit ca }n alte limbaje de programare. nume_Metoda - este identificatorul metodei. Mai multe metode pot avea acela~i identificator (supra}nc{rcarea metodelor), }n acest caz este necesar ca metodele s{ difere prin num{rul parametrilor, tipul parametrilor sau tipul rezultatului returnat. ]ntr-o clas{ derivat{ (subclas{) poate fi rescris{ o metod{ a superclasei. Metoda rescris{ va avea acela~i nume, tip de retur ~i list{ a parametrilor cu metoda superclasei. Trebuie diferen#iat }ntre supra}nc{rcare (overloading) ~i rescriere (overridden). lista_parametri - descrie tipul ~i identificatorul argumentelor transmise metodei. throws lista exceptii - con#ine lista metodelor ce vor fi apelate }n cazul apari#iei unor erori (excep#ii).
tabloului con#ine un argument din linia de comand{. Declara#ia metodei main se realizeaz{ prin: public static void main (String[] argumente){ ... } Reutilizarea unei clase existente ~i extinderea claselor care nu sunt finale, at|t structural c|t ~i comportamental, se realizeaz{ prin intermediul mecanismului de mo~tenire. Rela#ia de extindere }ntre clase eviden#iaz{ dou{ categorii de clase: superclasa - o clas{ care face obiectul extinderii; subclasa - clasa extins{. Subclasele mo~tenesc toate caracteristicile superclasei prin variabilele ~i metodele acesteia, dar pot avea ~i caracteristici proprii. Elementele mo~tenite pot fi utilizate a~a cum sunt sau pot fi redefinite }n subclas{. Pentru a accesa variabila superclasei }n una dintre metodele subclasei se specific{ numele superclasei sau se utilizeaz{ nota#ia: super.NumeVariabila Exemplu: class A { int a = 1; void m1() {System.out.println(a);} } class B extends A { double a = Math.PI; // variabila redefinita void m1() {System.out.println(a);} // metoda redefinita void m2() {System.out.println(A.a);} void m3() {m1(); super.m1();} } public class TEST{ public static void main(String [ ] arg){ A obA = new A(); B obB = new B(); obA.m1(); // tipareste numarul 1 obB.m1(); // tipareste constanta PI obB.m2(); //tipareste numarul 1 obB.m3(); //tipareste: 1 (pe primul rand) si PI (pe al doilea rand.) A obC = (A)obB; //obiectul obC este obB ca apartinand superclasei System.out.println(obc.a); // tipareste valoarea 1 obC.m1(); // se refera la obB si va tipari constanta PI. }} Metodele redefinite sunt tratate diferit de variabilele redefinite atunci c|nd se folose~te operatorul cast pentru conversie (a se vedea obC.m1() in exemplul de mai sus), altfel pentru ambele tipuri de entit{#i se utilizeaz{ cuv|ntul super. Exemplu: class C1 {
double x = 2.73; double f() {return x;} } class C2 extends C1 { double x; double f() { x = Math.cos(super.x)/Math.exp(super.x); return x+super.f()*Math.atan(Math.sqrt(3)); } } Pentru referirea unei variabile a superclasei C1 redefinit{ }n clasa C2, }n loc de a utiliza super, putem folosi ~i conversia cast la tipul C1 a obiectului this: ((C1)this).x. Metodele redefinite nu pot fi apelate prin conversie, trebuie utilizat cuv|ntul super.
interfe#e poate fi implementat{ de orice clas{ ~i este o metod{ abstract{. Deci, nici una dintre metodele declarate nu este ~i implementat{. Reamintim, existen#a }n Java a claselor abstracte. O clas{ abstract{ poate avea o subclas{ (poate fi extins{) dar nu poate fi instan#iat{. Printr-o clas{ abstract{ sunt prezentate variabilele ~i metodele ce pot fi partajate de toate subclasele. O subclas{ a unei clase abstracte poate fi instan#iat{ numai dac{ redefine~te ~i implementeaz{ fiecare din metodele abstracte ale superclasei. Dac{ o subclas{ a unei clase abstracte nu implementeaz{ toate metodele abstracte mo~tenite, atunci aceast{ clas{ este tot una abstract{. Exemplu: public abstract class FiguriGeometrice { public abstract double suprafata(); public abstract double perimetru(); } public class Dreptunghi extends FiguriGeometrice { protected double l, L; public Dreptunghi(){l=0.0; L=0.0;} public Dreptunghi(double l; double L) { this.l=l; this.l=L; } public double suprafata(){return l*L;} public double perimetru(){return 2*(l+L);} public double lungime(){return L;} public double latime(){return l;} } public class Cerc extends FiguriGeometrice { protected double r; public Cerc(){r=1.0;} public Cerc(double r){this.r = r;} public double suprafata(){return Math.PI*r*r;} public double perimetru(){return 2*Math.PI*r;} public double raza(){return r;} } Trebuie re#inut c{ o clas{ abstract{ poate avea ~i metode non-abstract, dar toate metodele unei interfe#e sunt declarate abstract.
1.8. Pachete
Realizarea modular{ a unei aplica#ii Java este permis{ prin intermediul conceptului de pachet (package). Codul surs{ al unei clase Java reprezint{ unitatea de compilare. O unitate de compilare, }n mod normal, con#ine definirea unei singure clase. Pentru aplica#iile complexe, clasele pot fi grupate }n pachete. Un pachet este declarat prin specificarea }n prima linie a fi~ierului surs{ a declara#iei:
package NumePachet; dup{ care urmeaz{ clasele ~i interfe#ele. Pachetele pot fi ~i acestea organizate ierarhic, dar o clas{ nu poate apar#ine la mai multe pachete. Dac{ }ntr-un fi~ier surs{ nu este utilizat{ instruc#iunea package, atunci clasele definite apar#in unui pachet anonim ~i nu vor putea fi importate de nici un alt pachet. Specificarea importului de clase se poate realiza }n unul din urm{toarele moduri: import pachet1.pachet2. ..., pachetn - utilizarea oric{rei clase, dar ca prefix; import pachet1.pachet2. ..., pachetn.clasa - pentru importarea unei clase; import pachet1.pachet2. ..., pachetn.* - pentru importarea tuturor claselor; O clas{ poate fi utilizat{ ~i prin specificarea complet{ a numelui. Exemple: a) specificarea complet{ a numelui - nu se folose~te instruc#iunea import. class Test1 { public static void main(String [ ] args){ int xp, yp; int[] x = {10, 20, 30, 40, 50}; int[] y = {10, 5, 0, 20, 40}; java.awt.Polygon p = new java.awt.Polygon(x, y, 5); java.awt.Point q = new java.awt.Point(10, 10); xp=q.x; yp=q.y; System.out.println(q.toString());//p.toString() eronat System.out.println(x = + xp + y = + yp); p.addPoint(xp,yp); System.out.println(numarul de puncte este: + p.npoints); } } b) utilizarea numelui clasei ca prefix import java.awt; class Test2 { public static void main(String [ ] args){ int dx, dy; awt.Point p = awt.Point(10,10); awt.Point q = awt.Point(10,30); dx = q.x -p.x; dy = q.y -p.y; System.out.println(Dist= +Math.sqrt(dx*dx+dy*dy)); } }
c) importarea unei singure clase import java.awt.Polygon; import java.awt.Point; class Test3 { public static void main(String [ ] args){ int xq=20, yq=30; int[] x = {10, 20, 30, 40, 10}; int[] y = {10, 5, 0, 20, 10}; Polygon p = new Polygon(x, y, 5); Point q = new Point(xq, yq); System.out.println(q.toString()); System.out.println(x = + xq + y = + yq); System.out.println(Q este in interior? +p.inside(xq,yq)); } } d) importul tuturor claselor pachetului import java.io.*; // Tip{rirea liniilor unui fi~ier care con#in un anumit sub~ir // Sub~irul ~i numele fi~ierului se introduc }n linia de comand{ public class Test4 { public static void main(String [ ] args){ if((args.length == 0) || (args.length > 2) ) { System.out.println( Apel: java Test4 subsir [fisier]); System.exit(0); } try { DataInputStream fin; if (args.length == 2) fin = new DataInputStream(new FileInputStream(args[1])); else fin = new DataInputStream(System.in); GrepInputStream g = new GrepInputStream(fin, args[0]); String linie; for (; ; ) { linie = g.readLine(); if (linie == null) break; System.out.println(linie); } g.close(); }catch (IOException e) System.err.println(e); } } Prin acest exemplu, arat{m c{ limbajul Java permite ~i lucrul cu fi~iere. Prezentarea pachetelor Java nu face obiectul acestei lucr{ri. Enun#{m totu~i numele ~i rolul pachetelor Java: java.applet - constituit din 3 clase ~i o interfa#{ este utilizat }n realizarea unui aplet;
java. lang - gestioneaz{ tipurile ~i elementele de baz{ ale limbajului Java. Clasa r{d{cin{ este Object, din care deriv{ clase precum: 1. clase finale: Boolean, Character, Math, String, StringBuffer; 2. clase abstracte: ClassLoader, Number cu subclasele finale (Double, Float, Integer, Long), Process, SecurityManager; 3. clase f{r{ instan#iere: Class, Compiler, Runtime, System 4. clase pentru tratarea erorilor, excep#iilor ~i pentru modelarea accesului concuren#ial. java.io - include clase pentru gestiunea fluxurilor de intrare/ie~ire (fi~iere). java.util - gestioneaz{ diverse structuri de date ~i include clase utilitare precum: Vector, Hashtable, BitSet, Date, Random etc. java.awt - ofer{ o colec#ie de clase pentru realizarea interfe#elor grafice }n Java. Acestea asigur{ crearea ~i afi~area ferestrelor, utilizarea imaginilor ~i a componentelor precum: butoane, bare de derulare, bare de meniuri, zone pentru introducerea textelor etc. Aplica#iile Java realizate cu AWT (Abstract Window Toolkit) pot lucra }n acela~i mod pe toate platformele. java.net - pentru gestionarea comunic{rii }n re#ea. Pentru eliminarea obiectelor create ~i de care nu mai este nevoie, se ocup{ interpretorul Java care dispune de un colector al obiectelor inutile (garbage colector). Totu~i, acesta poate fi informat de programator c{ un anumit obiect nu mai este necesar, pentru a urgenta eliminarea acestuia din memoria intern{.
1.9 EXEMPLE
]n continuare vom prezenta c|teva aplica#ii Java care s{ eviden#ieze modul de realizare a programelor Java. Nu vom ilustra modul de realizare a applet-urilor Java ~i nici tehnicile de programare concurent{; pentru acestea cititorul poate consulta literatura specific{. Exemplul 1. (Tablouri }n Java - metoda quick-sort). Principiul ~i complexitatea algoritmului Quick Sort au fost prezentate anterior. Aici prezent{m implementarea }n Java a unei clase adecvate ~i modul de utilizare al acesteia. Se vor ilustra c|t mai multe dintre structurile de control ale limbajului si tehnica program{rii recursive }n Java. Datele de test vor fi numere pseudo-aleatoare. class TablouQs {
private double [] Tablou; private int nrelem; private int dim; public TablouQs (int dim){ Tablou = new double[dim]; nrelem = 0; this.dim=dim; } public void Insert(double x){ if (nrelem < dim) { Tablou[nrelem] = x; nrelem++; } else System.out.println(Nu pot insera!); } public void Afisare(){ System.out.println(Elementele tabloului sunt:); for (int i=0; i<nrelem; i++) System.out.print(Tablou[i]+ ); System.out.println(); } public void Quicksort(int l, int r){ // Algoritmul este de tip Divide et Impera if (r-l+1 <= 3) Sortdirect(l,r); // Sortare directa (dimensiune mica) else { int m=(l+r)/2; //divizare double t=tablou[m]; int k = Partitionare(l,r,t); // pozitionarea pivotului t la locul lui Quicksort(l,k-1); // sortarea elementelor din stanga Quicksort(k+1,l); // sortarea elementelor din dreapta } } public int Partitionare(int l, int r, double t){ int lp=l-1; int rp=r; while (true) { while (Tablou[++lp]<t); while (rp>0 && Tablou[-rp]>t); if (lp=rp) break; else eXch(lp,rp); } eXch(lp,r); return lp; } public void eXch(int p1, int p2){ double t = Tablou[p1]; Tablou[p1]=Tablou[p2]; Tablou[p2]=t; } public void Sortdir(int l, int r){ int s=r-l+1; switch(s) {
return; if (Tablou[l]>Tablou[r]) eXch(l,r);return; if (Tablou[l]>Tablou[r-1]) eXch(l, r-1); if (Tablou[l]>Tablou[r]) eXch(l,r); if (Tablou[r-1]>Tablou[r]) eXch(r-1,r);
} public Sort(){ Quicksort(0, nrelem-1);} } // sf. clasei QsTablou; class Qs { public static void main(String[] args){ int dim = 64; TablouQs x; x = new TablouQs(dim); for (int i = 0; i<dim; i++) { double t = (int) (java.lang.Math.random()*99); x.Insert(t); } x.Afisare(); x.Sort(); x.Afisare(); } } // sf. clasei principale care utilizeaza obiectele supuse sortarii.
Exemplul 2. (Implementarea unei stive folosind liste simplu }nl{n#uite). Tipurile referin#{ sunt folosite pentru a referi un obiect din interiorul unui alt obiect. Prin aceasta se pot }nl{n#ui informa#iile aflate }n memorie. Valoarea implicit{ care este atribuit{ automat oric{rei variabile de tip referin#{ care nu a fost ini#ializat{ este null. Ca ~i }n alte limbaje de programare, simpla declara#ie a unei referin#e nu duce automat la rezervarea spa#iului de memorie pentru obiectul referit. Pentru rezervare se folose~te o expresie de alocare care folose~te cuv|ntul rezervat new. ]n exemplele anterioare au fost declarate ~i folosite diferite obiecte, inclusiv referin#e c{tre tablouri. Acest exemplu ilustreaz{ }nl{n#uirea obiectelor }ntr-o list{ ~i prelucrarea listei conform disciplinei LIFO (Last In First Out). import java.io.*; class Nod { public String info; public Nod leg; public Nod(String x){ info = x; } public Afisare(){ System.out.println(info+ ); } } class Lista { // se defineste lista inlantuita private Nod capLista; public Lista(){ capLista = null; }
public boolean ListaVida() { return (capLista == null); } public void InsertStart(String x) { Nod q = new Nod(x); q.leg = capLista; capLista = q; } public String StergPrimul(){ Nod t = capLista; capLista = capLista.leg; return t.info; } public void Afisare() { Nod c = capLista; while (c != null) { c.Afisare(); c = c.leg; } System.out.println( ); }} class Stiva { private Lista s; public Stiva(){ s = new Lista(); } public Insert(String x) { s.InsertStart(x); } public String Extrage(){ return s.StergPrimul();} public boolean StivaVida(){ return s.ListaVida();} public void Afisare(){ System.out.println(Stiva de la varf la baza este:); s.Afisare(); } } // Demonstratie: crearea unei liste cu siruri de caractere si afisarea // acestora in oridine inversa introducerii. class aplicatie { public static void main(String [] args) throws IOException { String inp; Stiva s = new Stiva(); System.out.println(Introduceti elementele listei:); System.out.flush(); while (true) { inp= getString(); if (inp.equals()) break; s.Insert(inp); } System.out.println(Elementele introduse sunt:); System.out.flush(); s.Afisare(); } public static String getString() throws IOException { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader (isr); String s = br.readLine(); return s; } } // sfarsitul aplicatiei
Exemplul 3. (Arbori binari, reprezentare }nl{n#uit{, opera#ii de baz{: c{utare, inserare, ~tergere, parcurgeri). Acest exemplu reia principalele aspecte legate de prelucrarea arborilor binari (defini#ia de baz{) ~i ilustreaz{ structura clasic{ a programelor Java. import java.io.*; import java.lang.Integer; class Nod { public int cheie; public String altceva; public Nod fiust; public Nod fiudr; public void AfisareNod(){ System.out.print((); // afisarea unui caracter System.out.print(cheie); System.out.print( , ); // afisarea unui sir de caractere System.out.print() ); // afisare unui sir } } class ArboreBinar { private Nod radacina; public ArboreBinar(){ radacina = null; } public Nod Cauta(int x) { Nod c = radacina; if (c == null) return null; while (c.cheie != x) { if (x < c.cheie) c = c.fiust; else c = c.fiudr; if (c == null) break; } return c; } public void Insert(int ch, String st) { Nod q = new Nod(); q.cheie = ch; q.altceva = st; if (radacina == null) radacina = q; else { Nod c = radacina; Nod tata; while (true) { tata = c; if (ch < c.cheie) { c = c.fiust; if (c == null) { tata.fiust = q; return; } } else { c = c.fiud; if (c == null) {tata.fiudr = q; return; } }
} // sfarsit while } } public boolean Elimina(int ch) { // sterge nodul cu cheia ch Nod c = radacina; Nod tata = radacina; boolean st = true; if (c== null) return false; while (c.cheie != ch) { tata = c; if (ch < c.cheie) { st = true; c = c.fiust; } else { st = false; c = c.fiudr; } if (c == null) return null; } // nodul c trebuie sters; nodul tata este ascendentul lui c // cazul 1: Are c fii? if (c.fiust == null && c.fiudr == null) { if (c == radacina) radacina = null; else if (st) tata.fiust = null; else tata.fiudr = null; } else //Cazul 2: Nu are fiudr. Vom inlocui cu subarborele stang if (c.fiudr == null) if (c == radacina) radacina = c.fiust; else if (st) tata.fiust = c. fiust; else tata.fiudr = c.fiust; else // Cazul 3: Nu are fiust. Vom inlocui cu subarborele drept if (c.fiust == null) if (c == radacina) radacina = c.fiudr; else if (st) tata.fiust = c.fiudr; else tata.fiudr = c.fiudr; else { // are doi fii. Vom inlocui cu succesorul in traversarea inordine Nod succesor = ObtineSuccesorInordine(c); if (c == radacina) radacina = succesor; else if (st) tata.fiust = c.fiudr; else tata.fiudr = c.fiudr; succesor.fiust = c.fiust; } return true; } private Nod ObtineSuccesorInordine(Nod p) { Nod succesor = p; Nod c = p.fiudr; // treci la fiul din dreapta while (c != null) { // avans pe stanga cat se poate succesor = c; c = c.fiust; } return succesor; } public void Parcurgere(int tip) { switch (tip) { case 1: System.out.print(\n Preordine: ); preordine(radacina); break; case 2:System.out.print(\n inordine: ); inordine(radacina);
break; default:System.out.print(\n postordine: ); postordine(radacina); break; } System.out.println(); } private void preordine(Nod p) { if (p != null) { p.AfisareNod(); preordine(p.fiust); preordine(p.fiudr); } } private void inordine(Nod p) { if (p != null) { inordine(p.fiust); p.AfisareNod(); inordine(p.fiudr); } } private void postordine(Nod p) { if (p != null) { postordine(p.fiust); postordine(p.fiudr); p.AfisareNod(); } } } // terminat definirea clasei ArboreBinar. class aplicatie { public static void main(String[] args) throws IOException { int n, ch; String alt; ArboreBinar arb = new ArboreBinar(); // crearea arborelui : se introduc n perechi, n se citeste. System.out.print(Numarul nodurilor:); System.out.flush(); n=getInt(); for (int k=1; k<=n; k++) { ch = getInt(); alt = getString(); arb.Insert(ch,alt); } while (true){ putString(Introduceti:\n); putString( I - inserare\n); putString( C - cautare\n); putString( S - stergere\n); putString( P - parcurgere\n); int optiune = getchar(); switch(optiune){ case I: case i: putString(Cheia:); ch=getInt(); putString(Restul:); alt = getString();
arb.Insert(ch,alt); break; case C: case c: putString(Cheia de cautat:); ch = getInt(); Nod gasit = arb.Cauta(ch); if (gasit != null) { putString(Am gasit: ); gasit.AfisareNod(); putString(\n); } else putString(Cheia +ch+ nu este in arbore.); break; case D: case d: putString(Cheia de sters:); ch = getInt(); boolean reusit = arb.Stergere(ch); if (reusit) putString(Am sters !\n); else { putString(Cheia nu este in arbore); putString( sau arborele este vid\n); } break; case P: case p: putString(Introduceti 1-pre, 2-in, 3-post (ordine) :); ch = getInt(); arb.Parcurgere(ch); break; default: putString(Optiune eronata!); } } } public static void putString(String s) { System.out.print(s); System.out.flush(); } public static String getString() throws IOException{ InputStreamReader inputStream = new InputStreamReader(System.in); BufferedReader buffer = new BufferedReader(inputStream); String sir = bufferr.readLine(); return sir; } public static char getchar() throws IOException{ String sir=getString(); return sir.charAt(0); } public static int getInt() throws IOException { String sir = getString(); return Integer.parseInt();
} } // terminat aplicatia