TIPURI DE STRUCTURI DE DATE SI APLICATII

STRUCTURI DINAMICE DE DATE

O mare importanta în programarea si utilizarea calculatoarelor o are modul în care se face organizarea datelor. De cele mai multe ori , în aplicatii , datele se prezinta sub forma unor multimi sau colectii , iar prelucrarea lor nu poate fi conceputa fara o organizare corespunzatoare. Organizarea datelor este un proces complex în care stabilirea structurilor logice si fizice reprezinta elemente fundamentale de care depinde, în mare masura, însasi eficienta prelucrarii. O data care apare ca o entitate indivizibila, atât în raport cu informatia pe care o reprezinta, cât si în raport cu procesorul care o prelucreaza, se numeste data elementara sau scalara. O colectie de date pe care s-a definit o structura si pentru care s-au stabilit procedee de înregistrare si identificare a componentelor se numeste structura de date. Componentele unei structuri de date pot fi date elementare sau alte structuri de date care sunt identificate si selectate prin nume (identificatori), sau prin pozitia pe care o ocupa în structura. Un tip de date defineste atât o multime de valori cât si o multime de operatii ce se pot efectua cu aceste valori. Fiecarei date i se asociaza un tip unic. Astfel, datele ce pot fi prelucrate în programele scrise în limbajul Turbo Pascal pot fi clasificate astfel: 1. Tipuri de date simple ( elementare, scalare) : 1.1. Tipuri de date predefinite: 1.1.1. Întregi 1.1.2. Reale 1.1.3. Booleene 1.1.4. Caracter 1.2. Tipul de date enumerare 1.3. Tipul de date subdomeniu (interval) 2. Tipuri de date compuse (structurate) : 2.1. Tipul de date tablou (array) 2.2. Tipul de date sir de caractere (string) 2.3. Tipul de date multime (set) 2.4. Tipul de date înregistrare (record) 2.5. Tipul de date fisier (file) 3. Tipul de date pointer 4. Tipul procedural
1

Tipurile de date structurate sunt agregari ale unor tipuri deja definite, simple sau structurate, standard sau definite de utilizator. Deci, din punct de vedere al complexitatii lor, datele se pot clasifica în date elementare si date structurate. O alta clasificare a datelor poate fi facuta d.p.d.v. al alocarii memoriei. Acestea pot fi grupate în date alocate static si date alocate dinamic. Procesul de alocare dinamica a memoriei permite ca în timpul executiei programului sa poata fi create, utilizate si distruse anumite variabile numite variabile dinamice. Structurile dinamice de date sunt structuri de date al caror numar de componente se modifica în timpul executarii programului (dimensiunea programului creste si/sau descreste). Structurile dinamice sunt mult mai flexibile decât cele statice si extrem de avantajoase acolo unde este necesara aceasta flexibilitate. O structura dinamica poate avea toate elementele structurate pe un singur nivel, caz în care se numeste lista liniara, poate avea elementele structurate pe mai multe niveluri, caz în care se numeste arbore, sau poate cuprinde elemente care nu pot fi grupate pe niveluri, putând exista legaturi între oricare elemente, structura numinduse în acest caz retea sau graf.
LISTA ARBORE

GRAFURI NEORIENTATE

GRAFURI ORIENTATE

2

Am ales ca tema pentru aceasta lucrare structurile dinamice de date deoarece ele îsi gasesc utilitatea într-un mare numar de domenii. Atât listele cât si grafurile ( acestea incluzând si arborii ) sunt folosite în foarte multe aplicatii. Grigore Moisil spunea : ”Azi teoria grafurilor a devenit o disciplina majora, desi nu-si gaseste locul într-o clasificare dogmatica a capitolelor matematicii. Folosirea teoriei grafurilor în domenii variate, de la chimie la economie, de la studiul retelelor electrice la critica textelor si la politica, îi dau azi un prestigiu de care cel ce clasifica stiintele trebuie sa tina seama.” Listele sunt utilizate în mai multe domenii de activitate, folosirea lor fiind indispensabila: liste cu personalul unei întreprinderi, liste cu materiale cumparate sau produse vândute, cererile catre o anumita informatie ,într-o retea computerizata de baze de date, sunt memorate într-o lista, scanarea memoriei pentru cautarea unor virusi poate fi tratata ca si cautarea unei secvente într-o lista etc. Arborii sunt utilizati si ei în multe domenii: chimie organica, fizica etc . Astfel, ei pot fi utilizati în diverse clasificari , în sortari etc. Structurile dinamice de date ofera elevilor posibilitatea de a rezolva un mare numar de probleme cu aplicatii practice. În aceasta lucrare vor fi prezentate listele, arborii si grafurile orientate si neorientate. La Liste – vor fi date , pentru toate tipurile de liste, definitiile, reprezentarile grafice, operatiile cu liste (crearea, stergerea, parcurgerea, adaugarea), procedurile respective (pentru un exemplu dat) si aplicatii cu fiecare tip de lista. La Grafurile neorientate - se vor defini notiunile necesare în rezolvarea problemelor ce utilizeaza grafurile , se vor trata reprezentarea grafurilor neorientate, parcurgerea lor si se vor prezenta câteva aplicatii . La Arbori – se vor defini notiunile ce vor fi utilizate si se vor trata în special arborii binari si problema arborelui partial minim. La Grafurile orientate - se vor defini noile notiuni, se va trata reprezentarea grafurilor orientate si probleme de drumuri în grafuri. Se vor trate algoritmii de baza: Dijkstra, Roy-Floyd, Roy-Warshall si metoda drumului citic într-un graf de activitati. În capitolul cu aplicatii va fi prezentat si un program de desenare a arborilor binari cu un numar fixat de vârfuri.

3

tinând cont de principiile de mai sus . Una dintre cele mai importante conditii pentru reusita predarii în scoala a unei discipline o constituie structurarea. continutului cunostintelor precum si pregatirea stiintifica si metodica a profesorilor. Procesul de învatamânt este un proces formativ-educativ care influenteaza dezvoltarea personalitatii si este o cerinta actuala de pregatire a elevului în vederea integrarii sociale. O alta greseala pe care o fac frecvent elevii este confundarea operatiilor specifice fiecarui tip de lista. de a dezvolta flexibilitatea ei. In învatamântul informatic se aplica mai multe principii ale procesului de învatamânt. Acest lucru se realizeaza prin proiectarea didactica prin care vor fi stabilite obiectivele generale. posibilitatea acesteia de a structura gândirea. sa aplice tratarea diferentiata. odata cu stabilirea obiectivelor generale si specifice. Astfel de situatii pot fi însa evitate prin aplicarea de catre profesor a unor principii ale procesului de învatamânt. a afirmarii personalitatii fiecaruia. precum si utilizarea unor metode si mijloace de învatamânt adecvate. Unul dintre aceste motive se datoreaza neîntelegerii corecte a relatiei dintre variabila dinamica si variabila de tip reper (referinta) atasata variabilei dinamice. care vor fi conforme cu continutul programei scolare si a obiectivelor specifice. constientizarea si ierarhizarea unor obiective generale si specifice adaptate particularitatilor de vârsta ale elevilor. dezvoltarea motivatiei învatarii si sa realizeze prelucrarea calitativa a cunostintelor predate. Probleme apar si la însusirea metodelor de rezolvare a problemelor care necesita în modelare grafuri. Pentru aceasta el va trebui ca. profesorul trebuie sa aleaga si sa utilizeze metode de activizare a elevilor. de a forma deprinderi si atitudini conform continutului de idei. 4 .CONSIDERATII METODICE Structurile dinamice de date ridica de multe ori probleme elevilor. Profesorului de informatica îi revine misiunea de a realiza ore cu un grad mare de eficienta. sa realizeze o proiectare corecta a tuturor actiunilor si sa realizeze aplicarea lor eficienta în activitatea de predare-învatare propriu-zisa. Pentru o proiectare metodologica eficienta. printre care: Ø Principiul participarii active si constiente a elevilor la procesul de învatamânt Ø Principiul sistematizarii si continuitatii Ø Principiul accesibilitatii cunostintelor si deprinderilor Ø Principiul intuitiei Ø Principiul pasilor mici Ø Principiul progresului gradat al performantelor în pregatire Ø Principiul conexiunii inverse(feed back-ului). Profesorul de informatica trebuie sa valorifice potentialul formativ-creativ al disciplinei. Aceste probleme apar din mai multe motive.

pentru cazul lectiei de dobândire de cunostinte se pot utiliza urmatoarele: v Metode § –de comunicare Ø orale: • expunerea. asigura disciplina. -urmatoarele etape sunt.anuntarea subiectului lectiei -moment în care profesorul scrie pe tabla titlul lectiei.fixarea si consolidarea cunostintelor si indicarea temei. prin rezolvarea unor sarcini de lucru concrete. Comunicarea obiectivelor lectiei nu este importanta. care sa duca la descoperirea de catre ei însisi a noilor continuturi. fiind suficient ca aceste obiective sa fie clare pentru profesor. Se urmareste captarea atentiei elevilor. Astfel o lectie poate avea urmatorul mod de desfasurare în conformitate cu obiectivele propuse: -un moment important al lectiei este organizarea clasei . o analiza a atingerii lor. -un alt moment al lectiei este. -urmeaza. în timp ce elevii îsi pregatesc materialele si desfasoara o actiune de autoorganizare si control propriu. dupa lectie. în timp ce elevii noteaza si analizeaza. Prezentarea continutului nou este bine sa se faca prin activizarea elevilor. Sunt reactualizate notiunile necesare si se comunica noile cunostinte. • explicatia Ø conversative: • conversatia • problematizarea • discutia colectiva § de actiune ♦ ~ prin aplicatii specifice temei ~ instruire prin activitati independente Mijloace ( resurse materiale): Ø Planse didactice Ø Seturi de aplicatii Ø Fise de lucru pentru elevi Ø Culegeri de probleme Ø Proiect didactic Forma de participare este cea colectiva.moment al lectiei care are ca obiectiv operational crearea starii psihologice favorabile desfasurarii lectiei.Din ansamblul mijloacelor si metodelor de învatamânt. Se urmareste obtinerea performantei si sa se asigure feed-back-ul. 5 .procesul de predare-învatare -ce presupune comunicarea cunostintelor si dirijarea învatarii. care va face pentru sine. pregateste materialele necesare. În aceasta etapa profesorul desfasoara o activitate de natura organizatorica: noteaza absente.

♦ Obiective perfomative( operationale. stabilind: * Schematica. II. rezultate la teste.Evaluarea rezultatelor este un moment important al lectiei si consta în notare. neexistând scheme prestabilite. Întrebarile profesorului. Metodele si procedeele utilizate. ci factori variabili care intervin. Planurile de lectie . Scenariul didactic: Aceasta parte a planului de lectie poate fi: Ø Ø Ø Ø Ø Ø Ø Ø Ø Ø Volumul de cunostinte. La sfârsitul orei se poate face o evaluare sumativa pe baza unor teste orale cu întrebari . impunând variante diferite. Etapele lectiei. material didactic. ♦ Data. I. cuprinzând: Ø Etapele lectiei. ♦ Clasa. ♦ Tipul de lectie. Activitatea profesorului si a elevilor. * Detaliata . schematice sau detaliate. aprecieri ale profesorului sau autoaprecieri. Materialul didactic folosit. Exercitiile de rezolvat. Ø Problemele mai importante 6 . ♦ Bibliografie. ♦ Subiectul lectiei. Timpul acordat fiecarei secvente din lectie. Schemele care vor fi prezentate. sunt instrumente de lucru absolut necesare. cognitive si afective) ♦ Metode si procedee didactice. Date generale: ♦ Obiectul. ♦ Scopul lectiei. Prezentam un model orientativ al planului de lectie: I. imaginatia. Pregatirea riguroasa a activitatii didactice este foarte importanta pentru asigurarea eficientei orei de curs. În elaborarea unui plan de lectie se evidentiaza creativitatea. talentul pedagogic al profesorului. Modalitatea de evaluare a activitatii. ♦ Mijloace de învatamânt.

cât si obiectivele educationale (cognitive. Se va urmarii realizarea tuturor obiectivelor propuse. metode si tehnici eficiente si moderne. Evaluarea poate fi: Ø Predictiva (initiala) Ø Formativa (continua) Ø Sumativa (finala) Exista mai multe instrumente de evaluare . Evaluarea trebuie sa aiba obiective clar definite. psihomotorii si afective). Astfel sunt instrumente: 7 . metode de investigare si comunicare a rezultatelor scolare pentru fiecare elev. Evaluarea rezultatelor scolare este o activitate centrala a unui proces de instruire si învatare. sa ajute profesorii sa-si evalueze propria activitate si sa furnizeze feed-back-ul catre parinti. în functie de specificul problemei si de resursele calculatorului. O evaluare eficienta trebuie sa arate profesorilor daca au fost atinse obiectivele curriculare. respectiv grafuri orientate ♦ Cunoasterea de catre elevi a avantajelor/dezavantajelor diverselor reprezentari ale grafurilor ♦ Formarea capacitatii de a alege din mai multe metode de rezolvare a unei anumite probleme pe cea optima.Obiectivele generale pentru structurile dinamice de date ( conforme cu continutul programei scolare ) sunt urmatoarele: ♦ Fixarea notiunilor de structuri de date ♦ Fixarea notiunilor de alocare statica si alocare dinamica ♦ Formarea deprinderilor de identificare si rezolvare algoritmica a problemelor care necesita în modelare liste liniare înlantuite ♦ Formarea deprinderilor de identificare si rezolvare algoritmica a problemelor care necesita în modelare grafuri neorientate. profesorul putând alege ceea ce crede ca este mai indicat. ♦ Insusirea de catre elevi a modului de lucru cu structuri arborescente Vor fi stabilite atât obiectivele specifice fiecarui capitol în parte. De asemenea ea trebuie sa orienteze elevii în alegerea celei mai bune cai de afirmare. în cele mai bune conditii. sa-i ajute pe acestia sa faca o diagnoza a progresului elevilor si sa adapteze actiunile elevilor cu posibilitatile acestora. Ea nu poate fi saparata de instruire si de învatare. prin utilizarea unor metode si mijloace adecvate .

” 8 .” “Învatamântul are ca finalitate formarea personalitatii umane. în formarea personalitatii autonome si creative. integrala si armonioasa a individualitatii umane.v Traditionale : • probe scrise • probe orale • probe practice v Alternative: • • • • • • • • • Probe scrise Probe orale Probe practice Observarea directa a elevului în timpul activitatii Investigatia Proiectul de cercetare Portofoliul Tema pentru acasa Autoevaluare În Legea Învatamântului se precizeaza urmatoarele : “Idealul eductional al scolii românesti consta în dezvoltarea libera.

I LISTELE CONSIDERATII METODICE Listele se studiaza în clasa a X-a la obiectele: “Programarea calculatoarelor” si la “Aplicatii practice de laborator”. marind numarul componentelor . pentru rezolvarea unei probleme. una dintre cele doua implementari ale listelor. Abordarea listelor prin prisma structurilor dinamice de date este o tema noua pentru elevi si . lista candidatilor la un examen de admitere. tablouri. Deci tablourile se vor folosi pentru acele liste în care se cunoaste numarul maxim de componente. se va reaminti tipul referinta( reper) si modul cum poate fi alocata memoria pentru o variabila. avantaje . din acest motiv. elevilor trebuie sa li se reaminteasca notiuni legate de : tipul record. trebuie tratata în mod gradat. Pentru studierea acestei teme .numarul componentelor variaza. modalitatea de a alege . Pentru aceasta li se poate propune o aplicatie pe care sa o rezolve cu ajutorul tablourilor. liste cu personalul dintr-o întreprindere etc. Elevii vor descoperi astfel ideea de baza a structurilor dinamice. dar relativ mai greu de exploatat. Dupa rezolvare le complicam putin problema. în primul rând. Crearea unei liste folosind alocarea dinamica a memoriei presupune o structura mult mai flexibila. prezentând. limitata de memoria calculatorului sau spatiul pe disc(discheta). pe când structurile dinamice de date se folosesc acolo unde nu se cunoaste de la început numarul componentelor. alocare dinamica. de la notiuni mai simple spre un conglomerat de notiuni. Se va preciza ca tablourile statice permit crearea unei liste cu un numar de componente limitat de dimensiunea tabloului. 9 .CAP. Se poate începe cu o expunere despre organizarea memoriei calculatorului. dezavantaje si mijloace proprii de tratare a operatiilor specifice. trebuie explicat elevilor ca acestea pot fi implementate folosind doua modalitati relativ distincte. a memoriei calculatorului sau a spatiului de pe disc(discheta). Tema face parte din capitolul “Structuri de date înlantuite” si urmeaza dupa capitolul “Alocare dinamica”. Pentru a expune elevilor utilitatea acestei structuri de date este nevoie de a enumera unele domenii de activitate în care folosirea listelor este indispensabila: liste cu materiale . Tratarea listelor se poate face folosind tablouri statice sau structuri dinamice de date înlantuite. astfel încât sa depaseasca numarul maxim de elemente ale tabloului. Elevii trebuie sa înteleaga. Elevii trebuie sa înteleaga motivatia utilizarii structurii dinamice si avantajele pe care le ofera folosirea acestora. fiecare în parte. Referitor la construirea si exploatarea listelor.

URM . Tipul reper (referinta) se defineste astfel: TIP REPER ^ IDENTIFICATOR DE TIP -unde prin identificator de tip s-a precizat tipul variabilelor dinamice pe care le refera variabila de tipul reper respectiv. profesorul trebuie sa determine elevii sa înteleaga notiunea de lista si sa deduca modalitatea de implementare a listelor cu ajutorul structurilor de tip referinta. O variabila dinamica se apeleaza prin intermediul tipului reper corespunzator: VAR. numite . fiecare componenta mai contine si o informatie suplimentara. din acest motiv. notata p^. O variabila dinamica se aloca dinamic într-o zona speciala numita HEAP (gramada) care este eliberata la “distrugerea “ variabilei dinamice. numita informatie de legatura. Pentru a usura întelegerea modului de memorare a listei se poate folosi o reprezentare grafica a acesteia. Informatia de legatura cuprinde adresa componentei urmatoare din structura. cautarea unui element cu anumite caracteristici etc. pe lânga informatia propriu-zisa. variabile reper sau referinta.Facând apel la intuitie si prin analogii cu alte exemple din viata cotidiana. datele alocate dinamic pot fi generate sau distruse în timpul executiei programului. mentionând ca fiecare element este caracterizat de informatia utila si de adresa urmatorului element. spunem ca p refera variabila dinamica p^. Deci variabilele reper sunt alocate static si au ca valori adrese ale unor variabile dinamice de un anumit tip. DINAMICA IDENTIF. Spre deosebire de datele alocate static. parcurgerea unei liste. a caror alocare se realizeaza la început. Pentru deducerea algoritmilor se va folosi reprezentarea grafica a datelor. Folosind principiile programarii structurate vom crea functii si proceduri pentru adaugarea unui element. variabilele dinamice vor fi referite prin intermediul altor variabile. Variabilelor dinamice li se pune în corespondenta un tip referinta în mod biunivoc: variabila reper contine referiri numai la variabila dinamica careia i-a fost pusa în corespondenta (contine adresa acesteia). în timp. a noi componente care trebuie legate în structura dinamica de celelalte componente. Pentru realizarea înlantuirii datelor. inserarea / stergerea unui element dintr-o anumita pozitie. în faza de compilare si se pastreaza pe durata întrgii executii a programului. DE VAR DE TIP REPER ^ Daca variabila reper p are ca valoare adresa unei variabile dinamice. Grafic acest lucru se reprezinta astfel: p p^ 10 INF ADR. Aspectul dinamic al structurii determina aparitia . Neavând nume (nefiind declarate într-o sectiune VAR) .

Crearea unei variabile dinamice presupune: 1) alocarea unei zone de memorie în HEAP pentru variabila dinamica 2) initializarea zonei de memorie corespunzatoare ei. doua zone de adresa: una pentru elementul anterior si una pentru elementul urmator. pe lânga zona de informatie . numit vârful stivei. ea obtinându-se inchizând o lista simplu.elementul e1 care nu are predecesor si care se numeste capul listei (prim).parcurgerea ei se poate realiza în ambele sensuri. Alocarea memoriei pentru o variabila dinamica nu presupune si initializarea ei.e2. iar operatiile de adaugare si de stergere se realizeaza la un singur capat al listei . alocata prin procedura NEW se realizeaza cu procedura DISPOSE . iar fiecare element contine. v lista circulara-care poate fi simplu sau dublu înlantuita. E={e1. v lista liniara dublu înlantuita. Apelul procedurii: NEW ( p ) -unde p este o variabila de tip reper. Apelarea procedurii : DISPOSE ( p ) O lista liniara se poate defini ca o multime finita E de elemente .parcurgerea ei se face într-un singur sens de la primul spre ultimul element. prin legarea primului element al listei dupa ultimul element al ei. 3) exista un element în lista – elementul en care nu are succesor si care se numeste element terminal( ultim). v coada. adaugarea unui element se poate face numai la sfârsitul listei . iar stergerea unui element se poate realiza numai la începutul listei. Listele liniare pot fi de mai multe feluri: v lista liniara simplu înlantuita. Eliberarea zonei de memorie ocupata de o variabila dinamica . aceasta cazând în sarcina programatorului. Alocarea memoriei se realizeaza prin apelul procedurii NEW definita în unitul System. iar elementele pot fi inserate oriunde în lista. din unit-ul System. 2) exista un element în lista . sau pot fi sterse indiferent de pozitia lor în lista. Se numeste lista înlantuita o multime dinamica de structuri succesive de acelasi tip si care satisfac una sau mai multe relatii de ordine introduse prin pointeri.…. 11 . v stiva. respectiv dublu înlantuita.parcurgerea se realizeaza începând cu primul element.parcurgerea acestei liste se realizeaza începând cu ultimul element introdus.en} care satisface proprietatile: 1) exista o relatie de ordine între elementele lui E astfel încât oricare e k are un predecesor si un succesor.

♦ accesul la elementele structurii este asigurat prin intermediul adreselor de legatura. Operatiile specifice tuturor structurilor dinamice sunt: Ø adaugarea unui element în structura –care presupune: ü alocarea dinamica a memoriei pentru noul element ü initializarea noului element alocat ü legarea elementului în structura Ø parcurgerea (traversarea) elementelor structurii.este posibila numai daca structura este nevida si presupune: ü eliminarea elementului din structura prin modificarea adreselor de legatura ( stergere logica) ü eliberarea memoriei ocupate de elementul respectiv( stergerea fizica) 12 .este necesar sa se cunoasca adresa primului element al structurii (aceasta adresa va fi pastrata într-o variabila de tip reper asociata structurii).Trasaturile comune tuturor structurilor dinamice de date sunt: ♦ ele se dezvolta dinamic pornind de la o structura initial vida.Prelucrarea acestor structuri dinamice se realizeaza cu ajutorul variabilelor reper si a variabilelor dinamice.se utilizeaza o variabila de lucru de tip reper ale carei valori reprezinta adresa elementului curent al structurii. toate programele de prelucrare vor trebui sa cuprinda secvente de început prin care sa se exprime faptul ca structura dinamica este vida. Se va avea grija sa nu se distruga structura si sa nu se piarda adresa primului element al structurii. deoarece fiecare element cuprinde adresa elementului urmator. Ø stergerea unui element al structurii.

Acest dezavantaj poate fi eliminat daca lista este creata cu doua santinele. Lista circulara va fi usor înteleasa de catre elevi . deoarece apar mai multe situatii atât la adaugarea unui element în lista cât si la stergerea unui element din lista. însa deranjeaza faptul ca trebuie tratate atâtea cazuri particulare. acestea reprezentând o alta categorie speciala de liste liniare. treptat. Se poate prezenta apoi modul de tratare a listelor de tip coada cu ajutorul unei santinele. Existenta celor doua adrese de legatura simplifica atât operatiile de adaugare cât si pe cele de stergere. deoarece adaugarea si stergerea elementelor acestui tip special de lista se realizeaza la acelasi capat al listei . fapt care simplifica mult lucrurile. Pentru fiecare tip de lista se vor oferi exemple cât mai simple. pentru ca. pentru început. numit vârful stivei.Pentru o mai usoara întelegere a listelor . 13 . fiind o lista simetrica. Parcurgerea listei se poate realiza în ambele sensuri . în care elementele se pot adauga numai la sfârsitul listei. Dupa ce elevii vor întelege modul de lucru cu acest tip de lista se poate trece la tratarea listelor de tip coada. sa se rezolve probleme cu un grad din ce în ce mai mare de dificultate. În capitolul cu aplicatii se vor da exemple de probleme care folosesc în rezolvarea lor tipurile de liste studiate. Lista liniara dublu înlantuita nu ridica probleme daca elevii înteleg modul în care se leaga elementele atunci când se cunosc adresele elementului precedent si urmator ale fiecarui element din lista. daca acestia au înteles modul de lucru cu listele simplu si dublu înlantuite. Operatiile nu sunt dificil de realizat. iar stergerea lor nu se poate face decât la începutul listei. Lista liniara simplu înlantuita poate ridica unele probleme. este mai bine sa se înceapa tratarea lor cu stiva .

Reprezentarea grafica a unei stive: vârf NIL INFO INFO INFO BAZA STIVEI VARFUL STIVEI Conditia de stiva vida este: vârf=NIL Operatii cu stive : Ø Adaugarea unui element . stive de carti etc. Ei vor întelege astfel ca nu pot adauga un nou element (lemn. în care adaugarea sau scoaterea unui element se face la un singur capat al listei. Informatia de legatura a fiecarui element din stiva reprezinta adresa elementului pus anterior în stiva. carte) decât în vârful stivei si nu vor putea sa scoata din stiva un element decât daca acesta se afla în vârful stivei. farfurie.info := vârf 4. sau Readln (p^. o stiva de farfurii . numit vârful stivei. legarea elementului în vârful stivei : p^. mutarea vârfului stivei: vârf := p 14 .. Primul element introdus se numeste baza stivei. Pot fi oferite elevilor exemple de stive din viata cotidiana : o stiva de lemne . a carei informatie de legatura este NIL.info:=….info ) 3.este posibila numai în vârful stivei si presupune urmatoarele etape: alocarea memoriei pentru noul element NEW (p) initializarea zonei de informatie din variabila dinamica p^ : p^. exceptie facând baza .STIVA ( L I F O ) Stiva este o lista liniara de un tip special.

vârf : reper. Parcurgerea se realizeaza cu o variabila de tip reper p care contine adresa elementului curent : se porneste din vârful stivei : p := vârf cât timp stiva nu este vida ( vârf <> NIL) se parcurge elementul curent si se trece la urmatorul element din lista : p := p^. Text : string[10].se vor parcurge elementele listei în ordinea inversa introducerii lor. se muta vârful stivei pe elementul urmator celui ce se va sterge : vârf := vârf ^.Ø Parcurgerea unei stive. Var p. next:reper end. se salveaza adresa vârfului stivei într-o variabila reper p în vederea eliberarii memoriei: p:=vârf 2.next 3. next Ø Stergerea unui element din stiva se poate sterge numai elementul din vârful stivei (daca aceasta este nevida) : 1. se elibereaza memoria ocupata de fostul vârf : Dispose (p) Considerând urmatoarele declaratii: Type reper=^ element. element=record info:string[10]. dupa principiul : Last In – First Out. putem sa scriem urmatoarele subprograme: 15 .

Begin Vârf:=nil. Adaugarea unui element in stiva: Procedure adaug. Readln ( text). while p<>nil do begin writeln( p^.next end.Crearea stivei: Procedure creare. p^. P^. begin new(p). p:=p^.info:=text. End. 16 . vârf:=p. End. p^.info:=text.next:=vârf. readln( text ). While text<> ‘’ do Begin New(p). write(‘ introduceti informatia :’). Parcurgerea stivei: Procedure parcurg. Write (‘ introduceti informatia :’). Vârf:=p. P^. Write(‘ introduceti informatia :’).next:=vârf. Readln(text).info). begin p:=vârf. end.

read (p^. next:reper. 17 . vârf:=p end. End. Begin p:=vârf. Element=record litera:char.Stergerea unui element din stiva: Procedure sterg.next. {stiva vida} write(‘ cuvântul: ‘). end. Begin vârf:=nil. writeln end end. writeln(p^.next until p=nil. Program inversare_cuvânt. if vârf = nil then writeln (‘s-a tastat enter ‘) else begin write (‘cuvântul inversat este : ’). vârf:=p^. p:=vârf.next:=vârf.info). while not eoln do begin new(p). p : reper. repeat write(p^.litera).litera). dispose(p). O problema simpla care ilustreaza modul de lucru cu stiva este cea care inverseaza caracterele unui cuvânt citit de la tastatura dintr-o linie de intrare. Var vârf. p:=p^. Type reper=^element. p^.

Elementul curent a carui adresa este retinuta în variebila reper p. iar iesirile sau stergerile . pointerul prim va indica valoarea NIL. COADA( F I F O ) COADA reprezinta o categorie speciala de lista liniara. în care elementele se adauga la un capat (sfârsit) si se suprima la celalalt (început). Deci conditia de coada vida este : prim=nil . Variabila reper prim are ca valoare adresa primului element din lista. se realizeaza numai la începutul cozii .2. în timp ce variabila reper ultim. are ca valoare adresa ultimului element din lista. la coada . Reprezentarea grafica a unei cozi : INF INF INF NIL prim ultim Când coada este vida . adaugarile se fac numai la sfârsitul cozii (ca si asezarea unei persoane la rând).primul servit”. Operatiile specifice acestei structuri sunt: Ø Ø Ø Ø crearea listei liniare de tip coada adaugarea unui element în structura stergerea unui element din structura parcurgerea (traversarea ) elementelor structurii 18 . contine cele doua zone : -zona de informatie si -zona de legatura. Spre deosebire de stiva . Deci. spre deosebire de stiva. la care operatiile se executa doar la un capat al stivei (vârf). coada va avea doi pointeri (variabile de tip reper) : prim si ultim. Si denumirea este semnificativa : F I F O = First In – First Out – adica “primul venit. Asemanarea cu o coada care se formeaza la un magazin va usura întelegerea acestui tip de lista.

info) prim^.info:= …. Crearea listei de tip coada –presupune : . c) variabila ultim va primi ca valoare adresa primului element (acesta. b) Initializarea elementului alocat prin precizarea continutului zonei de informatie si al zonei de legatura : prim^.1.2. sau Readln( prim^..next:=nil. dupa el nemaifiind nici un element. 19 .adaugarea primului element într-o coada vida . Adaugarea unui element în coada se poate face numai la sfârsitul cozii. Adaugarea primului element presupune parcurgerea urmatoarelor etape : a) Alocarea memoriei pentru primul element: New(prim). care devine ultimul element din lista: ultim:=p. sau p^. c) legarea elementului în structura: ultim^.next:=nil.info) Adresa de legatura a elementului adaugat este NIL deoarece acesta este ultimul element din lista . Readln(p^. dupa ultimul element si presupune parcurgerea urmatoarelor etape: a) Alocarea memoriei pentru noul element : New(p) b) initializarea elementului alocat: p^. d) variabila ultim primeste ca valoare adresa elementului adaugat.info:=…. va fi si ultimul ) : ultim:=prim. 1.adaugarea elementelor la sfârsitul cozii.1. 1. fiind singurul element din lista.next:=p.

se elibereaza memoria ocupata de fostul prim element al cozii : Dispose(p) În cazul în care se sterge unicul element al listei.p :reper. variabila ultim nu exista.next sfârsit_cât_timp 3.Trebuie sa se tina seama de ordinea în care se executa operatiile. ultim. element=record info:string[10].next 3.next) pâna se ajunge la sfârsitul listei . acesta devenind noul prim element: prim:=prim^. text:string[10]. se salveaza adresa elementului ce va fi sters : p:=prim. 2. pentru a nu se pierde informatiile. se elimina din structura primul element prin memorarea în variabila reper prim a adresei elementului care urmeaza lui prim.Procedurile corespunzatoare acestor operatii. Stergerea unui element al cozii: presupune stergerea primului element al listei . de aceea nu este necesara legarea elementului în structura.Se parcurg urmatoarele etape: 1. Parcurgerea elementelor unei cozi: se realizeaza pornind de la primul element al listei (p:= prim) si trecând pe rând prin fiecare element (p:=p^. next:reper end. Legarea noului element în structura presupune existenta variabilei dinamice ultim^. coada devine vida. iar variabila prim va avea valoarea nil. vor fi urmatoarele: 20 . considerând o lista de tip coada declarata astfel: Type reper=^element. In cazul în care lista este vida. 2. Var prim. În pseudocod parcurgerea se realizeaza astfel: p:= prim cât_timp p<>nil executa *se parcurge elementul p^ p:=p^.

p:=p^.next until p=nil end end. readln(text).Crearea cozii Procedure creare. prim^. ultim^. Parcurgerea cozii: Procedure listare.info). end else {adaugare element la sfârsitul cozii} begin new(p).next:=p ultim:=p end end. begin if prim=nil {coada vida} then writeln (‘coada este vida’) else begin p:=prim. repeat writeln(p^.next:=nil. If prim=nil {coada este vida} then begin {adaugarea primului element} new(prim). prim^.info:=text. 21 . Begin Write(‘ dati informatia : ‘). p^. ultim:=prim.info:=text.next:=nil. p^.

COADA CU SANTINELA Pentru eliminarea testului de coada vida la adaugarea unui element . ultim^. dispose(p) end end. Locomotivele se identifica printr-un cod. Un exemplu clasic pentru probleme ce se rezolva utilizând liste de tip coada este problema urmatoare (a carei rezolvare se gaseste în capitolul cu aplicatii): Dispecerizare locomotive Se considera un depou de locomotive cu o singura linie de cale ferata cu o intrare si o iesire. se apeleaza la un om de ordine care supravegheaza modul de servire a consumatorilor. coada poate fi creata cu o santinela ca prim element al cozii.intrarea unei locomotive. E. Sa se scrie programul care realizeaza dispecerizarea locomotivelor din depou. fara a fi considerat consumator (fara a face parte din lista). begin if prim=nil then writeln(‘ lista este vida’ ) else begin p:=prim. se va da ca exemplu o coada formata la un magazin la care . NIL sant ultim Pentru a se întelege mai bine rolul santinelei. O coada vida va cuprinde numai santinela: New(sant).iesirea unei locomotive.Stergerea unui element din coada Procedure stergere. L-listarea locomotivelor din depou si S-pentru oprirea programului (si listarea locomotivelor existente în depou). pentru bunul mers al lucrurilor .next. ultim:=sant. 22 . prim:=prim^. prelucrând comenzi de forma: I. Santinela este o variabila dinamica a carei zona de informatie este neinitializata si care a fost introdusa ca prim element al cozii în vederea optimizarii operatiilor asupra cozii.next:=nil.

presupune parcurgerea elementelor cozii. Adaugarea presupune: 1.4 initializarea variabilei ultim cu adresa ultimului element adaugat: ultim:=p 2. initializarea elementului alocat p^.info).2 se muta santinela pe elementul care ar trebui sters sant:=sant^.3 se elibereaza memoria ocupata de fosta santinela Dispose(p).1 alocarea memoriei pentru noul element: New(p) 1. 1. Parcurgerea elementelor unei cozi cu santinela.next:=nil. sau readln(p^.Reprezentarea grafica a unei cozi cu santinela : INFO INFO NIL sant primul element ultim Operatiile corespunzatoare unei cozi cu santinela sunt: 1. nu si santinela: p:= sant^. next cât_timp p<>nil executa * se parcurge elementul p^ p:= p^.3 legarea elementului în structura ultim^. 3.2.1 se salveaza adresa santinelei: p:=sant.Stergerea primului element al unei cozi cu santinela: 3.next:=p.next sfârsit_cât_timp 3.next. Adaugarea unui element în coada-nu mai are importanta daca lista de tip coada este sau nu vida.info:=…. 23 . 1. p^. 3.

Reprezentarea grafica a unei liste liniare simplu înlantuita : INFO INFO INFO NIL prim ultim Lista vida presupune îndeplinirea conditiei prim=nil Lista cu un singur element poate fi reprezentata astfel: INFO NIL prim ultim Operatii cu liste liniare simplu înlantuite: 1. caz în care pot sa apara doua situatii: ♦ p=prim ♦ p<>prim Ø dupa elementul p^. a carui adresa se gaseste în variabila reper prim spre ultimil element. adaugarea celorlalte elemente Un element se poate adauga : Ø înaintea elementului p^ .LISTA LINIARA SIMPLU ÎNLANTUITA Lista linira simplu înlantuita este o lista ale carei elemente pot fi adaugate oriunde în cadrul listei si pot fi sterse . Se va nota cu p adresa elementului curent al listei. caz în care pot sa apara doua situatii: ♦ p=ultim ♦ p<>ultim 24 . indiferent unde s-ar afla ele. Fiecare element al listei contine o parte cu informatia propriu-zisa si o parte cu adresa urmatorului element din lista. Crearea listei presupune doua etape: 1. Deci parcurgerea listei se va realiza doar într-un sens si anume de la primul element. adaugarea primului element 2. fiecare copil stiind numele (adresa de legatura) copilului care îi urmeaza în lista. Ca exemplu de lista liniara se poate da lista copiilor care vor merge într-o excursie. a carui adresa este memorata în variabila reper ultim.

next:=prim. c) legarea noului element în structura: p^. dupa ultimul element: a) se aloca memorie pentru noul element: new(p).next:=nil. c) se leaga elementul în structura: ultim^.2.next:=q. d) elementul introdus devine ultimul element din lista ultim:=p. c) se leaga în structura elementul adaugat: p^. 25 1. adaugarea unui element : înaintea primului element: a) se aloca memorie pentru noul element : new(p).info). p^. b) se initializeaza elementul: p^. d) variabila prim va primi ca valoare adresa elementului adaugat: prim:=p.next:=p. 1. q^.next:=p^. b) se initializeaza noul element: q^.2.info:=… sau readln(p^. .info:= … sau readln(prim^.info:=… sau readln(p^.3. dupa elementul p^: a) se aloca memorie pentru noul element: new(q).info) prim^. • variabila ultim primeste ca valoare adresa elementului : ultim:=prim.2.info).info:=… sau readln(q^.2.info).1.2. adaugarea primului element presupune parcurgerea urmatoarelor etape: • alocarea memoriei pentru noul element: new(prim). b) se initializeaza elementul p^. • initializarea noului element: prim^.next:=nil. 1.1.next.1. 1.

adresa de care avem nevoie pentru a adauga un element înaintea elementului p^. prin urmare. se pierde adresa elementului care urma dupa p^ înainte de adaugarea lui q^. Avem doua solutii: a) se pastreaza adresa elementului precedent lui p^.next:=q.4.next. nu mai stim adresa elementului precedent în lista. daca se executa întâi p^.info cu valoarea care trebuie adaugata se leaga elementul p^ de q^ : p^.2. notând acest element cu q^ si folosim relatia : p:=q^.next ultim În acest fel.Ordinea celor doua operatii de legare în structura este esentiala. se initializeaza p^. se copiaza p^ în noul element notat cu q^: q^:=p^. Acest lucru se poate realiza procedând astfel: ü ü ü ü ü se aloca memorie pentru noul element : new(q). înaintea elementului p^: Fiecare element al listei contine adresa elementului urmator în lista. 1. daca am ajuns la elementul p^. NIL prim p q ultim 26 . b) elementul q^ trebuie sa apara în lista înaintea elementului p^ . daca p este ultimul element : ultim :=q. problema adaugarii înaintea elementului p^ este echivalenta cu problema adaugarii dupa q^ .next:=q . NIL prim q p=q^.

Apare necesitatea cunoasterii adresei elementului precedent.next . ü se salveaza adresa elementului care trebuie sters p:=q^.next^.next:=q^.next^. Stergerea fizica se realizeaza cu procedura Dispose. NIL prim q p =q^.next. NIL prim p q ultim 27 . Stergerea unui element din lista –pot sa apara urmatoarele situatii: Ø se sterge primul element din lista Ø se sterge ultimul element al listei Ø se sterge un element oarecare al listei p^ Stergerea logica a elementului p^ presupune eliminarea lui din structura prin legarea elementului precedent lui p^ cu urmatorul sau element.) si eliberam memoria ocupata anterior de acesta.next^: q^.next ü se elibereaza memoria ocupata de elementul sters : dispose(p) b) mutam în locul elementului care trebuie sters (p^). ü se elimina din structura q^. elementul urmator (p^.2.next ultim Se parcurg urmatoarele etape: ü se pastreaza adresa elementului precedent q^. legând q^ de p^.next^. Avem doua solutii: a) pastram adresa elementului precedent (q^) si transformam problema stergerii elementului p^ în stergerea elementului q^.

ultim:=p.next:=nil.info:=text.next:=nil. prim^.info:=text. prim^. p^.p: reper.next:=nil.next sfârsit_cât_timp Considerându-se data urmatoarea declarare a unei liste simplu înlantuite: Type reper=^element. ultim. Parcurgerea listei (afisarea elementelor listei)-se realizeaza de la primul spre ultimul element al listei . while text<>'' do begin if prim=nil then begin new(prim).readln(text). element=record info:string[10]. begin prim:=nil.next:=p.3. în cazul în care se doreste afisarea elementelor listei. se vor putea scrie urmatoarele proceduri pentru : Crearea listei : procedure creare. end. ultim:=prim end else begin new(p). p^. write('introduceti textul :'). next:reper end. text:string[10].readln(text). var prim. write('introduceti textul :'). end. 28 . În pseudocod vom avea: p:= prim cât_timp p<>nil executa * se parcurge elementul p^ p:=p^. ultim^. afisând informatia continuta de fiecare element. ultim^. end.

info:=text. readln(text). p^. ultim:=p. Adaugarea unui element dupa ultimul element: procedure adaugare_sf.info. {adaugare la sfarsitul listei} begin new(p). p^.' '). end.next. write('introduceti informatia ce se adauga la sfarsit: ').next:=prim.info:=text. writeln. ultim^. Parcurgerea elementelor unei liste: procedure afisare. begin p:=prim. p^.next:=nil.next:=p. write('introduceti informatia ce se va adauga la inceput: '). end . end. 29 . prim:=p. p:=p^. end. p^.Adaugarea unui element înaintea primului element: procedure adaugare_in. { adaugare la inceputul listei} begin new(p). readln(text). while p<>nil do begin write(p^.

end. end. 30 . write('introduceti informatia ce se va sterge: '). Pentru a înlatura dezavantajul creat de numarul mare de cazuri care pot sa apara la tratarea listelor liniare simplu înlantuite se poate crea lista liniara cu santinele.info<>text then begin q:=p^.next. dispose(p).next.next:=q^.info<>text do begin p:=q. while q^.Stergerea unui element din lista: procedure sterge. if q=ultim then ultim:=p. Existenta santinelelor elimina cazurile de lista vida. begin p:=prim.next.readln(text). q:=q^. p^. var q:reper. end else begin prim:=p^. de adaugare în fata primului element sau dupa ultimul. if p^. end. dispose(q).next.

folosind o lista liniara creata cu doua santinele: sant1 si sant2. iar adaugarea dupa ultimul element se reduce la adaugarea înaintea lui sant2. 31 .Lista oarecare cu santinele . locul lor fiind luat de doua variabile de tip reper : sant1 si sant2. sant1^. în care erau retinute adresele primului. iar în locul variabilei ultim vom avea variabila sant2.next:=sant2 sant1 sant2 Procedurile sunt asemanatoare celor de la lista liniara simplu înlantuita cu deosebirea ca. while p<>sant2 do begin write(p^. p:=p^. Conditia de lista vida devine inutila. Pentru exemplificare se poate rezolva problema stergerii elementului minim dintr-o lista de numere întregi distincte.este o lista liniara oarecare în care nu mai avem variabilele prim si ultim . când se vor parcurge numai elementele listei.info). Adaugarea înaintea primului element se transforma în adaugarea dupa sant1. O particularitate apare la parcurgerea listei . respectiv a ultimului element din lista. Rolul santinelei a fost explicat la tratarea cozii cu santinela. new(sant2). elemente care nu sunt considerate ca facând parte dintre elementele listei.next end. Reprezentarea grafica a unei liste cu santinele: sant1 p sant2 Lista vida se reprezinta ca având doar cele doua santinele: new(sant1). nu si santinelele: p:=sant1. în locul variabilei prim avem variabila sant1.

32 . Reprezentarea grafica a unei astfel de liste poate arata astfel: sant1 INF sant2 În cazul listelor dublu înlantuite cu santinele. Variabilele prim si ultim vor memora adresa primului. în locul variabilelor prim si ultim vom folosi variabilele sant1. cât si adresa elementului urmator. locatia pred contine adresa componentei anterioare. Reprezentarea grafica a unei liste dublu înlantuite: prim INF NIL INF ultim INF NIL O componenta a listei va contine trei locatii.4. sau câmpuri: locatia info contine informatia. respectiv a ultimului element din lista. LISTA DUBLU ÎNLANTUITA Lista dublu înlantuita este un tip special de lista în care informatia de legatura a fiecarui element cuprinde atât adresa elementului precedent în lista. Ca si în cazul listelor simplu înlantuite . locatia next contine adresa componentei urmatoare. si listele dublu înlantuite se pot crea cu doua santinele. respectiv sant2. Semnificatia notiunii de santinela se cunoaste de la listele anterioare. iar variabila p retine adresa elementului curent.

Crearea listei dublu înlantuita presupune scrierea în lista a primului element si adaugarea celorlalte elemente ale listei. atunci toate elementele listei vor avea un element precedent si un succesor. deci numarul de cazuri . De asemenea . Presupunând declarata urmatoarea lista: Type reper=^element. pred:reper. Ø adaugare dupa un element oarecare p^. se reduce. element=record info:string[10].ultim. Daca lista este creata cu doua santinele . Ø stergerea ultimului element al listei. existenta celor doua adrese de legatura în fiecare element al listei dublu înlantuite simplifica mult atât operatiile de adaugare cât si pe cele de stergere . var prim. text:string[10]. Ø adaugare dupa ultimul element.p:reper. Ø stergerea primului element al listei. nemaifiind o problema cunoasterea adresei anterioare elementului curent p^. cât si la stergerea unui element din lista . ü memorarea informatiei utile si a informatiei de legatura pentru noul element ü variabilele prim si ultim vor primi ca valoare adresa elementului introdus în lista 33 . Adaugarea primului element presupune: ü alocarea de spatiu pentru noul element. v parcurgerea elementelor listei. atât la adaugarea unui element . Ø stergere la dreapta lui p^. next:reper end. v adaugarea unui element în lista: Ø adaugare înaintea primului element. v stergerea unui element din lista: Ø stergere la stânga lui p^.Operatiile cu listele dublu înlantuite sunt: v crearea listei. putem scrie urmatoarele proceduri: 1. Ø adaugare înaintea unui element oarecare p^.

next:=nil. element a carui înscriere se realizeaza într-un mod diferit de a celorlalte elemente. for i:=1 to nr do {nr reprezinta nr informatiilor introduse} begin write('adaug informatia: '). end.readln(text). prim^. inf:'). unde p^ poate fi initial chiar primul element . prim^. ultim^.pred:=ultim. begin write('nr. se completeaza câmpurile de informatie si de adrese se leaga în structura noul element: ultim^next:=p elementul nou introdus devine ultimul element din lista ultim:=p procedure adaugare_dr ( p:reper ). 2.info:=text. ultim:=p end.next:=p. var nr.procedure creare. Adaugarea unui element în lista dublu înlantuita – pot sa apara urmatoarele situatii: Ø adaugarea unui element la dreapta lui p^ . new(p). begin write(‘ informatia: ‘). Prin preocedura de mai sus s-a memorat în lista primul element . 34 .next:=nil. p^. p^. prim^.info:=text. new(prim).pred:=nil. Se parcurg urmatorii pasi: ü ü ü ü se aloca memorie pentru noul element: new(p).readln(nr).i:integer. ultim:=prim end.readln(text). p^.

p^. begin new(q). Ø adaugarea unui element la începutul listei – presupune legarea noului element înaintea lui prim. q^. begin new(p). procedure adaug_st(p:reper).readln(text).info:=text.pred:=q.pred:=p^. write('adaug informatia :').readln(text). p^.pred^. end. p^. q^. var q:reper. atunci când p=ultim 35 . procedure adaug_in.caz asemanator cu adaugarea la dreapta lui p^. q^.next:=q.pred:=nil. p^.next:=p. prim^.next:=prim.Ø adaugarea unui element la stânga lui p^. Ø adaugarea la sfârsitul listei –presupune adaugarea dupa ultimul element.pred. prim:=p.pred:=p. Faptul ca avem adresa elementului anterior face ca adaugarea la stânga sa fie asemanatoare adaugarii la dreapta lui p^.se parcurg aceleasi etape ca la adaugarea la dreapta . p^. end.info:=text. write(‘introduceti informatia : ‘).

va avea ca urmator element elementul urmator lui p^. . end end.(p^.info). 4.Stergerea logica a elementului se realizeaza prin redirectionarea legaturilor astfel încât elementul precedent lui p^ . end. begin p:=prim.next).pred.3.next end.Stergerea fizica a elementului se realizeaza cu dispose(p). având adresele de legatura atât spre stânga cât si spre dreapta. b) Parcurgerea de la dreapta la stânga: procedure parcurg_dr. Lista dublu înlantuita este o lista simetrica.Parcurgerea unei liste dublu înlantuita-se poate realiza în ambele sensuri. p:=p^. begin p:=ultim. Procedura corespunzatoare va fi urmatoarea: 36 . p:=p^. while p<>nil do begin writeln(p^.( p^.pred) .va avea ca element precedent elementul anterior lui p^. Stergerea unui element : ♦ stergerea elementului oarecare p^ -presupune: . iar elementul urmator lui p^. while p<>nil do begin writeln(p^. a) Parcurgerea de la stânga la dreapta: procedure parcurg_st.info).

37 .pred. end.pred^. begin p:=prim. dispose(p).readln(text). stergerea elementului anterior lui p^ se face prin stergerea lui q^.când p=prim (stergerea primului element) presupune parcurgerea urmatorilor pasi: § se salveaza adresa elementului ce va fi sters : p:=prim. § noul prim element va avea adresa elementului precedent = NIL.next:=nil. dispose(p) end. begin p:= ultim. § se sterge fizic primul element a carui adresa a fost retinuta în p : dispose(p).next^. p^. prim:=prim^. dispose(p). end.procedure sterg.când p=ultim (stergerea ultimului element). ♦ -stergerea elementului p^ .pred:=nil.pred:=p^.pred. p^. si pastrând adresa acestuia în q . prim^. ultim^. while p^. procedure sterg_prim.next:=p^.notând cu q^ elementul anterior lui p^.info<>text do p:=p^. procedure sterg_ultim. p:=prim.next. ultim:=ultim^. a carui adresa se cunoaste.next. ♦ stergerea elementului p^ .next. begin write('inf ce va fi stearsa: ').next. § variabila prim va lua ca valoare adresa urmatorului element deoarece prin stergerea primului element cel de-al doilea va deveni prim element: prim:=prim^. ♦ stergerea elementului anterior lui p^ .

adica lista la care se leaga dupa ultimul element chiar primul element al listei. 38 .LISTA CIRCULARA Lista circulara este o lista cu proprietatea ca elementul urmator ultimului element este primul element al listei. tinând cont de faptul ca ultimului element al listei îi urmeaza primul ei element. acesta fiind câstigatorul jocului. Lista poate fi simplu sau dublu înlantuita. Se pot da exemple de astfel de liste pentru o mai buna întelegere a acestei structuri. Astfel o lista circulara dublu înlantuita va fi si ea simetrica. Dupa legarea elementelor listei nu mai stim care este primul si ultimul element al listei . Reprezentarea grafica a unei liste circulare simplu înlantuite : prim INF INF ultim … INF La listele circulare procedurile vor fi asemanatoare cu cele de la listele din care sunt create aceste liste. Algoritmul care rezolva aceasta problema este prezentat în partea de aplicatii. dupa cum este lista initiala. Un astfel de exemplu este asezarea unor copii în cerc si numararea lor prin eliminare pâna la ramânerea unui singur copil . putând fi parcursa în ambele sensuri. Un astfel de exemplu este “ Jocul lui Joseph” .având nevoie de un singur pointer pentru accesarea unui element al listei .

sociologie etc. îl împarte astfel C c a d A b e D f g B Portiunile de uscat A. Euler a rezolvat aceasta problema introducând un obiect matematic pe care l-a numit graf si care are urmatoarea forma: C c d A g e b a C D f Teoria grafurilor are numeroase aplicatii în fizica. în final revenindu-se în punctul initial. c. inginerie. economie. Problema consta în a determina daca este posibil ca . C. chimie. b. Prima lucrare care abordeaza notiunea de graf dateaza din 1736 si se datoreaza matematicianului elvetian Leonard Euler care a folosit un graf pentru a solutiona problema podurilor din Koenigsberg. B.CAP . D sunt unite între ele prin sapte poduri: a. e. d. f. II GRAFURI NEORIENTATE 1. care trece prin acest oras. Râul Pregat. g.GENERALITATI Grafurile se studiaza în clasa a X-a la obiectele: “ Bazele informaticii” si la “Aplicatii practice de laborator”. Aplicatii specifice grafurilor neorientate sunt cele în care se cere : -sa se determine lungimea minima a lanturilor dintre x si y -sa se determine un lant de lungime minima de la x la y -sa se afiseze(daca exista) un ciclu eulerian al unui graf neorientat G cu n vârfuri si m muchii 39 . plecând dintr-un punct de pe uscat sa se poata trece pe toate podurile.

A 3 B=Ô si orice muchie u a lui G are o extremitate în A si cealalalta în B. Definitie Se numeste graf neorientat o pereche ordonata de multimi ( X. iar vârfurile x si y sunt adiacente în G. U ) a.5. X=A 4 B . Un graf partial al unui graf dat se obtine pastrând aceleasi vârfuri si eliminând o parte din muchii. X fiind o multime finita si nevida de elemente numite noduri sau vârfuri. VU.V) a. 1 3 4 2 5 6 7 40 A={1. U ) este un graf G1= ( X . numite muchii. Definitie Se numeste graf complet cu n vârfuri un graf care are proprietatea ca orice doua noduri diferite sunt adiacente. adicaG1 are aceeasi multime de vârfuri ca G. U ) Daca x si y sunt extremitatile muchiei u. Y_X.6.U) se numeste graf bipartit daca exista doua multimi nevide A si B a. Graful se noteaza cu G= ( X .î.3.î. spunem ca u si x sunt incidente. la fel ca si u si y . Multimile A si B formeaza o partitie a lui X. U ). Definitie Un subgraf al unui graf G= (X. Vom spune ca subgraful H este indus sau generat de multimea de vârfuri Y. iar V contine toate muchiile din U care au ambele extremitati în Y. Un subgraf se obtine eliminând o parte din vârfuri si toate muchiile incidente cu acestea.7} .-problema existentei într-un graf oarecare a unui ciclu hamiltonian etc. 2 o K1 K2 K3 K4 K5 Definitie Un graf G=(X.U) este un graf H=(Y. iar U o multime de perechi neordonate din X. iar multimea de muchii V este . fie o submultime a acesteia. fie chiar U. Definitie Un graf partial al grafului G= ( X . Deci doua muchii care au o extremitate comuna sunt incidente.4} B={2. Propozitie Un graf complet Kn are Primele 5 grafuri complete sunt: n ( n − 1) muchii.î. Se spune ca un graf partial este indus de multimea V de muchii.

Definitie Un graf bipartit se numeste complet daca pentru orice x din A si orice y din B exista în G muchia [x,y]. 1 4 5 2 6 3 7 A={1,2,3} B={4,5,6,7}

Daca A are p elemente , iar B are q elemente, numarul total de muchii ale unui graf bipartit complet este p*q , iar graful se noteaza Kp,q . Definitie Se numeste graf regulat graful în care toate vârfurile au grade egale. Definitie Un graf K-regulat este un graf regulat în care gradul comun al vârfurilor este K. Exemple: tetraedrul, cubul,octoedrul etc.

Definitie Se numeste lant în graful G, succesiunea de vârfuri L=[x1,x2, …xk] cu proprietatea ca orice doua vârfuri consecutive din L sunt adiacente, adica [x 1,x2 ], [x2,x3],….,[ x k-1,xk] ∈ U. V â r fur il e x 1 si xk se numesc extremitatile lantului , iar numarul de muchii ce apar în L se numeste lungimea lantului. Definitie Daca vârfurile x1,x2, …xk sunt diferite doua câte doua, atunci lantul L se numeste lant elementar. În caz contrar lantul este neelementar. Un lant L poate fi interpretat ca traseul unei deplasari de la x 1 la xk pe muchiile lantului. Definitie Se numeste ciclu în G un lant L pentru care x1=xk , si toate muchiile sunt diferite doua câte doua. Definitie Se numeste ciclu elementar un ciclu care are proprietatea ca oricare doua vârfuri ale sale , cu exceptia primului si a ultimului, sunt diferite doua câte doua.
41

2. REPREZENTAREA GRAFURILOR NEORIENTATE

Exista mai multe modalitati de a reprezenta graful G=(X,U). Aceste reprezentari vor fi utilizate în prelucrarea grafurilor cu ajutorul programelor care implementeaza pe calculator algoritmii respectivi. v Se precizeaza numarul de vârfuri (n) si matricea de adiacenta A a grafului, care este o matrice patratica de ordinul n , cu elementele: 1, daca [i,j] ∈ U A[i,j ]= 0, î n caz contr ar Aceas ta m atr ice es te o m atr ice s im etr ica. D e exem pl u, pentr u gr aful ur m ator v om av ea:
1

A=
2

0 1 0 1 0 1 0 1 0

3

v Se precizeaza nr n de vârfuri si, pentru fiecare vârf i, lista Li a vecinilor sai, adica lista vârfurilor j pentru care [ i,j] ∈ U. Vâ r fi 1 2 3 Lis ta Li a v ecinil or s ai 2 1,3 2

Acest mod de reprezentare poate utiliza si alocarea dinamica a memoriei, precum si un tablou bidimensional T cu doua linii si n+2*m coloane, unde m este nr. de muchii, iar n numarul de vârfuri ale lui G.

42

T [1, i ]=i,

i=1,n

T [2, i ] reprezinta indicele coloanei din T în care este dat primul element din lista Li a vecinilor lui i ; daca I este vârf izolat, atunci T[2, i]=0; daca T[2, i ]=j, atunci T[1,j] este primul dintre vecinii lui i, iar T[2, j] este coloana în T în care apare urmatorul element din lista Li. Daca u este indicele lui T în care apare ultimul element w din Li, atunci T[1,u]=w si T[2,u]=0. Pentru graful de mai sus vom avea: i T[1,i] T[2,i] 1 2 3 4 5 6 7 1 2 3 2 1 3 2 4 5 7 0 6 0 0

v Se dau numarul n de vârfuri, numarul m de muchii, precum si doua tablouri unidimensionale e1 si e2 cu câte m componente fiecare, continând extremitatile muchiilor grafului, adica U={ [e1[1], e2[1] ] , [e1[2], e2[2]],….,[e1[m],e2[m]]}. v O varianta de implementare mai naturala ar fi aceea de a defini un tip de data ‘muchie’ utilizând tipul înregistrare, care sa contina cele doua extremitati ale unei muchii, si apoi de a defini un tablou cu n componente de acest tip: Type muchie=record x,y:byte; end; …………………………… var u:array[1..n] of muchie;

Referirea la extremitatile muchiei se face prin : u[i] .x, respectiv u[i] .y. Acest mod de reprezentare permite înglobarea natulara în tipul de date muchie si a altor informatii asociate muchiilor( cost, lungime ) si este utilizata în problemele în care muchiile se prelucreaza succesiv, eventual dupa o modificare a ordinii lor în tabloul u.

43

un ciclu care contine toate muchiile grafului. Construim un prim ciclu C parcurgând vârfuri accesibile din aproape în aproape pe muchii din graf. Construim astfel un nou ciclu C1 pe care îl concatenam cu ciclul C. Teorema : Un graf G fara vârfuri izolate este eulerian daca si numai daca este conex si gradele tuturor vârfurilor sunt numere pare. GRAFURI EULERIENE Definitie Se numeste ciclu eulerian într-un graf G. 9 44 . fiecare muchie fiind prezenta o singura data. obtinând un ciclu mai lung. un vârf al ciclului C pentru care mai exista muchii incidente cu el. pentru aceasta se vor parcurge urmatorii pasi: Pas 1. Repetam pasul 2 atâta timp cât mai exista muchii care nu au fost înca incluse în ciclul C.: 3 8 2 6 1 7 4 5 Graf eulerian Teorema de mai sus da o conditie necesara si suficienta ca un graf care nu contine vârfuri izolate sa fie eulerian.3. fie acesta vârful 1. neluate înca. Definitie Se numeste graf eulerian un graf care contine un ciclu eulerian. Pas 2. Definitie Se numeste lant eulerian un lant care contine toate muchiile grafului. micsorând corespunzator gradele vârfurilor parcurse. Alegem pentru continuare( daca aceasta mai este posibila) . Ne intereseaza algoritmul cu ajutorul caruia putem construi un ciclu eulerian într-un graf despre care stim ca este eulerian. Ex. Nu ne propunem sa demonstram aceasta teorema. Plecam dintr-un vârf oarecare.

Acest algoritm .n}. x[3]] . În partea de aplicatii se va prezenta algoritmul care determina toate ciclurile hamiltoniene existente într-un graf (care se dovedeste a fi hamiltonian).….2. 1 5 2 3 4 Graf hamiltonian 4 Ciclu hamiltonian 5 3 1 2 Teorema : Graful complet Kn este hamiltonian Teorema: Daca G=(X. x[2]] .. x[n]] χ U si [x[n].….U) este un graf cu n>=3 vârfuri. foloseste metoda backtracking. x[1]] χ U n 2 45 . GRAFURI HAMILTONIENE Definitie Se numeste ciclu hamiltonian un ciclu elementar care contine toate vârfurile grafului G. astfel încât gradul fiecarui vârf x χX satisface conditia: d(x)ƒ atunci G este hamiltonian. Ciclurile se genereaza utilizând un vector x cu n componente. Definitie hamiltonian.4.j)χ{1. [x[2]. Conditiile interne ce trebuiesc satisfacute sunt urmatoarele: x[i] ! x[j] … (i.[x[n-1]. Se numeste graf hamiltonian un graf care contine un ciclu Definitie Se numeste lant hamiltonian un lant elementar care contine toate vârfurile grafului. i!j [x[1].

sa verificam daca el a mai fost generat o data. atâta timp cât ( x[k]+1 [n ) and ( v=0 ) executa x[k]:=x[k]+1. se cere sa se determine un traseu care sa viziteze o singura data cele n orase si care sa aiba costul total minim.Pentru a nu produce de mai multe ori acelasi ciclu. {se merge la urmatoarea componenta. {se fixeaza primul vârf al ciclului} k:=2. obtinut altfel daca k<n atunci k:=k+1. din care se va deduce prima valoare posibila} O problema înrudita cu cea a gasirii într-un graf a unui ciclu hamiltonian este problema voiajorului comercial: Un voiajor comercial trebuie sprezinte în n orase produsele fabricii pe care o reprezinta. x[k]:=1.Putem evita acest lucru memorând ciclurile generate si .k-1 executa {vârfurile trebuie sa fie diferite} daca x[i]=x[k] atunci v:=0. Oricum fiecare ciclu hamiltonian este generat de doua ori. Cunoscându-se costul deplasarii între oricare doua dintre cele n orase. x[k]]=0 atunci v:=0. . {se porneste de la ideea ca pozitionarea facuta este buna si se modifica v în caz contrar} pentru i:=1. {se testeaza existenta muchiei între x[k-1] si x[k]} daca v=0 atunci k:=k-1 {se face un pas înapoi } altfel daca (k=n) and (a[x[n]. Cu alte cuvinte. de fiecare data când terminam generarea unuia. v:=1. {variabila sol numara ciclurile hamiltoniene} x[1]:=1. problema cere sa se determine un ciclu hamiltonian de cost minim în graful Kn ale carui vârfuri sunt cele n orase. diferind ordinea de parcurgere a nodurilor. vom fixa x[1]=1. Rezolvarea acestei probleme va fi prezentata în partea de aplicatii. care se initializeaza cu valoarea 1. iar costul unui ciclu reprezinta suma costurilor muchiilor sale. dupa care se întoarce în orasul din care a plecat.1]=1) atunci sol:=sol+1 scrie ciclul ham. 46 . {se pune în x[2] valoarea 1 din care se va deduce prima valoare posibila a acestei componente} Pas 2 : atâta timp cât k>1 executa v:=0. x[2]:=1. daca a[x[k-1]. Pas 1 : sol:=9.

1 2 3 4 5 6 7 8 Pentru implementarea algoritmului se utilizeaza vectorul viz si o stiva S care ne permite sa plecam în fiecare moment de la vârful curent spre primul dintre vecinii sai nevizitati. pâna este gasit un vecin al lui j nevizitat înca.î. Metode de parcurgere a grafurilor neorientate : v metoda de parcurgere DF ( Dept First ) sau parcurgerea în adâncime. daca nu. În continuare se procedeaza similar cu vârful j.2.7. 47 . trecânduse la primul dintre vecinii sai. fiecare nod accesibil din i pe muchii adiacente doua câte doua. nevizitati înca. marind si ps . poate fi aplicata atât în cazul grafurilor neorientate cât si în cel al grafurilor orientate. ps se micsoreaza cu 1. De exemplu.5. fie acesta j . pentru graful de mai jos. acesta din urma fiind plasat în vârful stivei.3.5. în cazul în care se începe cu nodul 1 si alegerea nodurilor se face în ordine crescatoare. În vectorul urm vom determina în fiecare moment urmatorul nod ce va fi vizitat dupa nodul j (atunci când acesta exista). Daca el este gasit. PARCURGEREA GRAFURILOR NEORIENTATE Prin parcurgerea unui graf neorientat se întelege examinarea în mod sistematic a nodurilor sale.4. Se parcurge linia j din A începând cu urmatorul element. sa fie atins o singura data. încercând sa continuam cu urmatorul element din stiva. Parcurgerea începe cu un vârf initial dat i si continua cu primul dintre vecinii sai nevizitati .8 . parcurgerea DF este :1. plecând dintr-un vârf dat i a. este plasat în vârful stivei . Notam cu ps pointerul de stiva.6.

S[1]:=i. Atâta timp cât ps=1 executa {stiva este nevida} j:=S[ps]. dintre toti vecinii unui vârf .d. {pune k în urm[j]} daca nu exista un astfel de k atunci ps:=ps-1 {se coboara în stiva} altfel scrie k. { scoate nodul din stiva} determina primul dintre vecinii k ai lui j. v metoda de parcurgere BF ( Breath-First) – sau parcurgerea în latime. apoi a vecinilor acestuia. Parcurgerea în latime presupune vizitarea întâi a vârfului initial i. în caz contrar 48 . Pentru j:=1. nevizitati înca urm[j]:=k.…. apoi a vecinilor nevizitati ai acestora s. ps:=1.6. pe acela nevizitat înca si care îndeplineste conditia impusa. {plasam în vârful stivei S vârful i } {pointerul de stiva ps pointeaza spre vârful stivei } Pas 3.2.m. în vederea alegerii la un moment dat.4. daca vârful j a fost vizitat viz[j]= 0. { vârful k este vizitat} viz[k]:=1.3. vom determina prima valoare posibila pentru primul nod spre care se poate pleca din vârful j} sfârsit pentru Pas 2. Pentru constructia practica a algoritmului.{se mareste ps pentru a-l S[ps]:=k.n executa viz[j]:=0. vom folosi un vector viz cu n componente. astfel: …jχ {1.Algoritmul în pseudocod este urmatorul: Pas 1.n}.2. parcurgerea BF corespunzatoare va fi: 1.a.7. stop Programul Pascal care implementeaza algoritmul va fi prezentat în partea de aplicatii. {toate vârfurile sunt nevizitate} urm[j]:=0.5. memora pe k în S} Pas 4 . 8. Pentru graful de mai sus . 1. {pornind din 0.

nevizitati înca. Atâta timp cât p[ u executa {coada este nevida} Pas 3. C[u]:=j. {vârful a fost vizitat} Pas 3.5.6. 49 . Pas 2.3. {cu p pointam la primul element al cozii iar cu u la ultimul} viz[i]:=1. La fel ca si cazul algoritmului DF. p:=p+1. V:=C[p]. Initial v este egal cu i. {se viziteaza vârful I} Pas 3. nevizitate înca. Cele mai utilizate metode de parcurgere sunt DF si BF. vârful dat. {scoate vârful urmator din coada} Pas 3. C[1].În vectorul C vom gestiona o coada în care prelucrarea unui vârf v aflat la un capat al cozii consta în introducerea în celalalt capat al ei a tuturor vârfurilor j vecine cu v. {In coada C memoram initial doar vârful i.{se trece la urmatorul element ce va fi scos din coada C} Pas 4. Evident. Aceasta se deosebeste de parcurgerea BF prin faptul ca prelucreaza mereuultimul nod la care s-a ajuns. v Metoda de parcurgere D (depth) –în cazul în care lista folosita este o stiva se obtine parcurgerea depth.=i.8. parcurgerea D se va face în ordinea : 1. Stop.} p:=1.n executa viz[j]:=0.7. 2.2.5. Programul Pascal de parcurgere a grafurilor neorientate prin metoda BF va fi prezentat în partea de aplicatii.4. {adauga vârful j în coada C} Viziteaza vârful j. 1. Algoritmul în pseudocod este urmatorul: Pas 1. Pentru toti vecinii j ai lui v. Pentru exemplul considerat. viz[j]:=1. 3. executa u:=u+1. algoritmii BF si D pot fi folositi pentru parcurgerea unui graf neorientat care nu este conex sau pentru grafuri orientate.u:=1. Pentru j:=1.

U). Aceasta reprezinta multimea de vârfuri ale componentei conexe nc . CAP . Prezentam algoritmul care verifica daca un graf este conex. Daca nu. Acest algoritm se bazeaza pe parcurgerea BF. III 50 . utilizând parcurgerea BF . reprezinta multimea tuturor vârfurilor care sunt legate prin lanturi de un vârf dat. 2 1 3 4 4 6 7 Graf conex 3 5 Graf neconex 8 5 8 1 2 6 7 Definitie Se numeste componenta conexa a grafului G=(X.6. Se determina si se afiseaza multimea vârfurilor legate de x prin lanturi. o lista a vârfurilor care. Daca toate vârfurile au fost vizitate. se precizeaza numarul total de componente conexe. se alege un vârf x înca nevizitat si se reia pasul 2. se trece la pasul 3. Se initializeaza numarul nc de componente conexe cu 0 (nc:=0_. În cazul în care graful nu este conex vom cere sa se determine numarul componentelor conexe ale grafului dat. Pas 3: Se testeaza nc. Algoritmul este urmatorul: Pas 1: Se alege un vârf x (ex> x=1 ). Daca nu. se concluzioneaza ca graful este conex. U1) conex al lui G care sa lege un vârf din X1 cu un vârf din X-X1. Pas 2: Se mareste nc cu 1 (nc:=nc+1 ). Daca nc este 1. luând x ca vârf de plecare. un subgraf C=(X1. Se stie ca în urma parcurgerii BF a unui graf obtinem . CONEXITATE Definitie Se numeste graf conex un graf cu proprietatea ca pentru oricare doua vârfuri x si y diferite ale sale exista un lant care le leaga. de fapt.

care au aceeasi formula chimica C4 H 10 pot fi reprezentate astfel: H H H H H H C C C C H H H H H H H H C C C H H C H H H H Ex. Arborele genealogic al unei persoane este un alt exemplu de structura arborescenta. Doua hidrocarburi saturate : butanul si izobutanul . GENERALITATI: În clasa grafurilor conexe. Într-o stuctura de tip arbore.ARBORI 1. Directoarele sistemului de operare sunt structurate sub forma unui arbore Hard Disc Software Comm Draw Write Programs Docs General Teaching Research Utils 3. 1. arborii reprezinta grafurile cele mai simple ca structura si cele mai frecvent utilizate în practica.2. Termenul de arbore a fost introdus de Cayley în 1857. elementele sunt structurate pe niveluri astfel: 51 . plecând de la o analogie botanica. De studiul lor s-au ocupat matematicieni si fizicieni de seama: Cayley a studiat arborii pentru aplicatiile lor în chimia organica. exemplu care îi va ajuta pe elevi sa înteleaga mai usor acest tip de structura de date. iar Kirchhoff a studiat aceasta categorie de grafuri pornind de la studiul retelelor electrice. Ex.

.Un graf conex este un graf în care pentru oricare doua vârfuri exista un lant care le leaga. se numeste element terminal sau frunza. Se vor reaminti elevilor notiunile de graf conex si de ciclu: .pe urmatorul nivel se gasesc elementele legate de radacina. În cazul în care un element nu mai are nici un fiu. Definitie Se numeste arbore partial un graf partial H al grafului G care în plus este si arbore. Nodurile care nu au descendenti se numesc frunze . de care sunt legate elementele de pe nivelul urmator (nivelul 1 ). elemente care se vor numi fii si care formeaza nivelul 1. nivelul 2 …………………….. radacina arborelui ……………………………. Fiecare nod are un singur tata .. la rândul lor pot avea fii. Corolar: Un graf G=(X. nivelul 3 Definitie : Se defineste un arbore ca fiind un graf conex si fara cicluri.pe primul nivel (nivel 0 ) exista un element unic numit radacina . . Nodurile care au acelasi tata se numesc frati.pe celelalte niveluri se gasesc elemente legate de elementele de pe nivelurile anterioare si care .Un ciclu în G este un lant pentru care ultimul element al lantului este chiar primul element al lui si toate muchiile sunt diferite doua câte doua. . acestea numindu-se fiii elementului considerat.U) contine un arbore partial daca si numai daca G este conex. cu exceptia radacinii care nu are tata. Facându-se analogia cu arborele genealogic se vor defini notiunile cu care se vehiculeaza în prelucrarea arborilor : Fiecare element se numeste tata pentru elementele de pe nivelul urmator care sunt legate de el. nivelul 1 ………. nivelul 0 ………………. . 52 .

Pentru determinarea unui APM al unui graf conex . Arborele partial de cost minim este arborele partial la care între oricare doua noduri exista un drum. iar. preturi .Reprezentarea functiilor compuse cu ajutorul arborilor binari. Definitie Un graf G care nu contine cicluri se numeste padure. Vor fi prezentati cei doi algoritmi de determinare a unui APM cunoscuti ca: Ø Algoritmul lui Kruskal Ø Algoritmul lui Prim Un mare numar de aplicatii utilizeaza în rezolvarea lor arborii binari . 53 . Astfel ei sunt utilizati pentru: . costuri. de energie electrica etc.Memorarea si regasirea rapida a unor informatii (arborele binar de cautare) .Propozitia 1. APLICATII : În diverse aplicatii (proiectarea unor retele de transport. Se poate cere astfel : sa se determine un arbore partial de cost minim. sa se determine toti arborii partiali minimi sau sa se determine numai aceia care satisfac diverse restrictii de optimizare.Arborii binari perfect echilibrati etc.Notatia poloneza a expresiilor aritmetice. .Reprezentarea arborelui genealogic (arbore oarecare) cu ajutorul unui arbore binar. . .) apare frecvent problema determinarii arborilor partiali de cost minim care sa satisfaca restrictii de conexitate si sa minimizeze (maximizeze) anumite lungimi. O problema concreta în care intervine problema determinarii arborelui partial de cost minim este cea a conectarii oraselor cu cost minim. Propozitia 2. Definitie Un graf G=(X. în plus. sunt cunoscute mai multe metode.V) cu n ƒ 2 vârfuri contine cel putin doua vârfuri terminale. de comunicatii. de alimentarii cu apa. Orice arbore cu n vârfuri are n-1 muchii.U) care nu contine cicluri se numeste graf aciclic. Orice arbore H=(X. . suma muchiilor este minima.Sortarea elementelor unui sir prin selectie arborescenta (arbori de sortare).

Urmatoarele conditii sunt echivalente: 1) G este un arbore. care. care asociaza fiecarei muchii u. Presupunem cunoscute teoremele care caracterizeaza o padure. în final orice doua orase sa fie conectate (direct sau prin intermediul altora). si o functie c : UτR. Propozitie: Pentru graful G conex. costul sau reprezinta suma costurilor muchiilor sale. adica: c(H) = u∈V ∑ c (u ) Pentru un arbore partial de cost minim folosim notatia prescurtata APM.n}. cu functia de cost c. respectiv un arbore: Teorema (caracterizarea unei paduri). în plus . exista un unic lant care le uneste. 2) Pentru oricare doua noduri distincte.î. 6) G este minimal în raport cu proprietatea de conexitate.3. egalitatea având loc când graful este un arbore. Teorema Orice graf conex contine cel putin un arbore partial.…. 5) G este maximal în raport cu proprietatea de aciclitate.m) exista relatia mƒ n-1. Problema : Sa se determine un graf partial H al lui G care sa fie conex si sa aiba costul minim. Un arbore partial conex reprezinta modalitatea ortima din punct de vedere financiar de a lega direct unele perechi de orase a. 3) G este aciclic si are n-1 muchii. un numar real pozitiv c(u). exista un graf partial H conex si de cost minim. Teorema (caracterizarea unui arbore). Graful G este o padure daca si numai daca pentru oricare doua noduri ale lui G exista cel mult un lant care le uneste. deoarece putem sa interpretam cele n vârfuri ale grafului ca fiind orase. 54 . X = {1. Aceasta problema este cunoscuta si sub numele de “problema conectarii cu cost minim a oraselor”. V) al lui G. 4) G este conex si are n-1 muchii. ARBORE PARTIAL DE COST MINIM Fie un graf G = ( X.U ) conex. Definitie pentru un graf partial H = (X. este arbore. j ] ca reprezentând costul conectarii directe a oraselor i si j.2. Fie graful G cu n noduri.2. Propozitie Pentru orice graf conex de tip (n. numit costul sau. iar costul muchiei [i .

initial se pleaca de la graful partial vid. .construirea arborelui partial optim al unui graf conex cu n noduri se sfârseste atunci când arborele construit are n-1 muchii. costρ0. c i . algoritmul construieste un arbore partial optim astfel: . 55 .la fiecare pas se alege acea muchie de cost minim din cele neselectate anterior si care nu formeaza ciclu cu cele selectate deja.2. pentru j:=1. i:=1.m executa daca L xj !Ly j {extremitatile muchiei j sunt în componente conexe diferite} atunci iρi+1 Si ρj { se adauga muchia j în arbore } cost ρ cost + cj marcaj1 ρ L xj { se unifica componentele conexe} marcaj2 ρ Ly j pentru k=1.( xi . Algoritmul lui Kruskal prezentat în pseudocod: citeste n. i:= 1. y i crescator dupa costurile c i Li ρ i . y i . ALGORITMUL LUI KRUSKAL Având la baza metoda Greedy pentru rezolvarea unei probleme de optimizare.n { se initializeaza marcajele vârfurilor} i ρ 0.n executa daca Lk=marcaj2 atunci Lkρmarcaj1 daca i=n-1 atunci scrie solutia S si costul c *oprire fortata scrie ‘ Graful initial este neconex ‘ stop. .m ) * se ordoneaza muchiile xi . Programul Pascal va fi prezentat în partea de aplicatii.m .1.

1 ). C. i2 } arb(na)ρ arb(na) 4 { j } { se testeaza daca s-a obtinut un arbore nou} j ρ0 repeat jρj+1 until arb(j) = arb(na) if j < na then na ρ na-1 stop .n {se genereaza arborele pornind de la nodul i} nod ρ Ô .n-1 jρ0 repeat j ρj+1 i1 ρ E ( j. 3. i2 sunt extremitatile muchiei } nod ρ nod 4 { i1 . i2 ρ E ( j.Si acest algoritm se încadreaza în metoda Greedy. vida. 2 ) until ( i1 χ nod ) xor ( i2 χ nod ) nod ρ nod 4 { i1.C {E. {nod-vector ce memoreaza nodurile } cost ρ 0.2.matricea muchiilor. ALGORITMUL LUI PRIM În timp ce algoritmul lui Kruskal consruieste un APM prin construirea multimii muchiilor arborelui minimal . 1 ). arb ( na )ρj { alegerea celorlalte n-2 muchii} for k=2. adaugându-i la fiecare pas muchia cu cel mai mic cost care nu formeaza cicluri cu muchiile aflate în matricea muchiilor arborelui minimal . na ρ na +1. E. Arborele se construieste treptat prin adaugarea la fiecare pas a muchiei cu cel mai mic cost care formeaza cu precedentele muchii alese un arbore. ARBORI BINARI 56 . Algoritmul lui Prim în pseudocod este: Program Prim Citeste n.m. algoritmul lui Prim construieste un arbore partial optim minim pornind cu o multime formata dintr-un singur nod si o multime de muchii. i2 ρ E{ j . 2 ) until ( i1 = i ) or ( i2 = i ) { i1.vectorul costurilor} naρ0 {contorizeaza nr APM obtinuti} for i:= 1.2. i2 } cost ρ cost + C( j ). j ρ 0 { se determina muchia de cost minim ce pleaca din i } repeat j ρ j+1 i1 ρ E( j .

care nu este terminal. Un arbore binar nevid fie se reduce la radacina . are doi fii. Ex. 57 . Deci arborele binar este o structura recursiva de date. Daca se elimina radacina si legaturile ei se obtin doi arbori binari care se numesc subarborii stâng si drept ai arborelui initial.Definitie: Un arbore binar este un arbore în care fiecare nod are cel mult doi fii: fiul stâng si fiul drept. fie cuprinde radacina si cel mult doi subarbori binari.: Se va face distinctie între fiul stâng si fiul drept al arborelui Definitie Un arbore binar complet este un arbore în care fiecare nod .

fiecare element cuprinzând . S[i]=0 sau D[i]=0 semnifica lipsa unui descendent stâng. iar D[i] descendentul drept. pe lânga informatia propriu-zisa asociata nodului. Se specifica radacina si pentru fiecare vârf se specifica descendentul stâng si cel drept. 58 . arbore= record inf : byte. pentru fiecare vârf i. INF [i] reprezinta informatia asociata nodului. st.1. var radacina : reper. Acest lucru se poate reprezenta grafic astfel: 1 2 NIL NIL 3 NIL 4 5 NIL 6 NIL NIL 7 NIL NIL 8 NIL Declararea unei structuri de tip arbore se face astfel: Type reper=^arbore. S[i] specifica descendentul stâng.3. acestea exprimând legaturile existente între arbori.dr: reper end. REPREZENTAREA ARBORILOR BINARI Ø Un arbore binar se poate implementa foarte usor cu ajutorul adreselor de înlantuire. Se folosesc doi vectori S si D. respectiv a unui descendent drept. unde . Ø O alta reprezentare se realizeaza cu ajutorul vectorilor. adresa fiului stâng si adresa fiului drept.

Ei trebuie sa stie ca alocarea statica a arborilor este posibila atunci când în problema se cunoaste numarul maxim de noduri ale arborelui. 1 ) Elevii trebuie sa stie sa aleaga acel mod de reprezentare care îi avantajeaza în rezolvarea fiecarei probleme în parte. Pentru arborele de mai sus vom avea: TATA = ( 0. 0 .0 . 3. 1. 5 ) DESC = ( 0.Ex. 1. -1. -1. 1. 3. 0. 59 . 5. 0. 0.6 .0 ) D=( 3.: Fie arborele: 1 n=7 2 3 5 RAD = 1 S=( 2. -1. 7.4 . 0 ) 7 4 6 Ø O alta reprezentare a arborilor binari se realizeaza dându-se vectorii TATA care precizeaza. 5. 1. pentru fiecare vârf i nodul TATA [ i ] si Desc care indica prin valoarea –1 sau 1 daca vârful i este descendentul stâng sau drept al parintelui sau TATA[i].0 .

var rad:reper. st. descompunând problema în trei subprobleme: 1. val:byte. nodului '. în faza de combinare a solutiilor se leaga nodul radacina de cei doi subarbori.':'). begin read(val).{gen. crearea subarborelui drept. dr.dr:=arbore. arbore:=p. prezentat în continuare. nodului '.p^. Prin combinarea solutiilor se continua constructia arborelui. CREAREA SI TRAVERSAREA UNUI ARBORE BINAR Crearea unui arbore binar se rezolva prin metoda divide et impera . {returneaza adresa radacinii} var p:reper. {adresa radacinii arborelui} function arbore:reper. În acest fel s-a construit un subarbore mai mare care reprezinta solutia unei subprobleme din descompunere. if val>0 then {subarborele este nevid} begin new(p).{generarea radacinii p^ a subarborelui} write('nodul din stg. si-l leaga de rad} end else p:=nil. crearea nodului radacina (dim=1).dr:reper end. subarb.3.val.st:=arbore. Descompunerea continua pâna se ajunge la problema crearii unui subarbore vid (dim=0) .2. 3. st. end. Rezolvarea unei probleme de dimensiune 1 (crearea unui nod radacina). Problema crearii unui subarbore vid se rezolva prin initializarea variabilei reper asociata radacinii arborelui cu constanta NIL . p^.':'). nod=record inf:byte.inf:=val. utilizeaza o functie de creare numita arbore care returneaza adresa radacinii arborelui creat: Program creare_parcurgere_arbore_binar . presupune alocarea memoriei si initializarea zonei de informatii asociate nodului. type reper=^nod.{gen. crearea subarborelui stâng. si-l leaga de rad} write('nodul din dr. Programul care creaza un arbore binar .val. 2. subarb. p^. 60 . Daca cele trei probleme de dimensiuni mici sunt rezolvate.

tot în inordine . apoi radacina. 7. nodurile subarborelui drept.î.Astfel. putem scrie urmatoarele proceduri: procedure preordine(p:reper). pentru parcurgerea în preordine . tot în preordine. Traversarea arborelui presupune vizitarea fiecarui nod o singura data. nodurile subarborelui drept . 3. 5. 1 6 7 Considerând declaratiile arborelui creat mai sus . operatie echivalenta cu o liniarizare a arborelui. 7. si apoi radacina.Parcurgerea arborilor binari consta în examinarea în mod sistematic a nodurilor sale a. Fie arborele: 1 2 3 Parcurgerea acestuia furnizeaza vârfurile în ordinea urmatoare: 4 5 preordine: 1. Descompunerea subproblemelor b) si c) continua pâna când se ajunge la subarbori vizi. se viziteaza nodurile subarborelui stâng . 7. 61 . apoi . 4 postordine: 2. 6.st). apoi acelea ale subarborelui drept. {R} preordine(p^. 1. begin if p=nil then begin write(p^. c) Traversarea în postordine : se viziteaza în postordine nodurile subarborelui stâng. Parcurgerea arborilor este o problema care se poate descompune în trei subprobleme identice. {S} preordine(p^. 5. 4. 5. apoi . fiecare nod sa fie atins o singura data. tot în postordine . 6. si apoi . 6. c) Parcurgerea subarborelui drept. 3. problema se descompune în urmatoarele subprobleme de dimensiuni mai mici: a) Parcurgerea radacinii ( un singur nod => dimensiunea=1) b) Parcurgerea subarborelui stâng. Exista trei modalitati importante de traversare a arborelui: a) Traversarea în preordine : se viziteaza radacina.dr). b) Traversarea în inordine : se viziteaza în inordine nodurile subarborelui stâng.inf:2). 2. {D} end end. 4 inordine: 2. 3.

{R} inordine(p^. postordine(p^. writeln. writeln.st). end end.dr). preordine(rad).writeln('arborele parcurs in postordine: ').procedure inordine(p:reper).dr).writeln('arborele parcurs in inordine: '). writeln.inf:2).readln end. 62 . {S} write(p^. begin if p=nil then begin inordine(p^. begin if p=nil then begin postordine(p^. writeln. rad:=arbore. write(p^. postordine(rad). inordine(rad). {D} end end. {S} {D} {R} Programul principal care apeleaza procedurile respective va fi: begin writeln('nodul radacina:'). procedure postordine(p:reper).writeln('arborele parcurs in preordine: ').st).inf:2).

begin write('nodul: ').read(p^. new(p). Ex 1 1 2 5 2 6 3 4 6 7 3 4 7 8 n=7 5 n=8 Conditia din definitia arborelui este respectata pentru un arbore cu n vârfuri daca subarborele stâng are [n / 2] vârfuri .st:=arbore(ns) else p^. iar subarborele drept are n – [n / 2 ] – 1 vârfuri.rad. APLICATII ALE ARBORILOR BINARI v ARBORE PERFECT ECHILIBRAT Definitie Se numaste arbore perfect echilibrat acel arbore care are diferenta dintre numarul vârfurilor subarborilor oricarui vârf din arbore egala cu cel mult 1. {gen. nd:=n-ns-1.3. Subprogramul de generare al unui astfel de arbore este urmatorul: function arbore (n:byte) :reper .dr:=arbore(nd) else p^.} ns:=n div 2. arbore:=p end.{returneaza radacina subarborelui creat } var p:reper. subarb.dr:=nil. {gen subarb dr cu nd noduri} if nd>0 then p^. {gen subarb st cu ns noduri} if ns>0 then p^.inf).3.nd:byte. v ARBORI DE SORTARE 63 . ns.st:=nil.

avem urmatoarea relatie: x+y=n Pe de alta parte. pornind de la arborele de sortare. dupa a carui rezolvare obtinem: x = 2* n . fie ele 2r si 2r+1 a. Vârfurile terminale sunt asociate celor n elemente ale unui sir care se doreste a fi ordonat crescator. atunci arborele de sortare corespunzator are toate vârfurile terminale pe acelasi nivel.î.2r+1 y=n–x De exemplu .Definitie Se numeste arbore de sortare un arbore binar complet care are toate vârfurile terminale pe un singur nivel sau pe doua nivele consecutive. pentru n=6 putem sa construim urmatorul arbore de sortare: 5 1 2 3 4 4 6 64 . am avea urmatoarea relatie: x + 2* y=2 r+1 Grupând relatiile de mai sus obtinem un sistem de doua ecuatii cu doua necunoscute. Arborii de sortare sunt folositi în sortarea elementelor unui sir printr-o metoda numita selectie arborescenta Daca n este o putere a lui 2 . daca . sa avem: 2r <n< 2r+1 În acest caz arborele de sortare corespunzator are vârfurile pe nivelele consecutive r si r+1. si. evident. fiecarui vârf de pe nivelul r îi asociem doi descendenti (pe nivelul r+1) am obtine un arbore binar complet cu toate vârfurile terminale pe acelasi nivel (r+1). Notând cu x numarul de vârfuri terminale de pe nivelul r+1 si cu y numarul de vârfuri terminale de pe nivelul r. altfel exista doua puteri consecutive ale lui 2.

Este important sa stim de unde vine valoarea în radacina. care merge în adâncime pâna când se identifica vârful în care urca valoarea asociata descendentului pentru care valoarea fratelui sau este eliminata din arbore în etapa curenta. În vârful radacina al arborelui se va gasi cel mai mic element din sir. în functie de nivelul pe care ne situam. Se parcurge apoi lantul spre radacina si se corecteaza valoarea asociata fiecarui vârf. adica în a[1]. Programul Pascal de sortare folosind selectia arborescenta va fi prezentat în capitolul de aplicatii. Acest lucru îl realizam folosind o procedura recursiva care va construi un nod interior sau un nod terminal. Va trebui sa calculam întâi valorile lui r . x si y . iar daca suntem pe nivelul r. Se memoreaza aceasta valoare în a[2] si se continua astfel pâna la extragerea din arbore a tuturor valorilor sale provenite din sirul initial. Pentru a implementa în Pascal acest algoritm va trebui sa construim întâi arborele de sortare. pentru a cunoaste locul în care se va introduce valoarea maxint si de unde va pleca în sus pentru completarea corecta a valorilor nodurilor interioare cu minimul valorilor celor doi descendenti. iar a nodurilor neterminale ( în numar de x/2 ) de pe nivelul r cu variabila u. Extragem din radacina valoarea minima. Scoaterea valorilor din arborele de sortare se face cu procedura recursiva cauta. În nodul parinte asociat lui z urca valoarea asociata vârfului frate al lui. punând-o pe locul sau definitiv. el determinându-se în urma a n-1 comparatii între elementele sirului. Pentru elementele ramase vom executa urmatorul pas: Fie lantul care uneste radacina cu vârful terminal din care a provenit valoarea minima.Elementele ce se vor sorta sunt plasate pe varfurile terminale de la stânga la dreapta. trebuie sa facem distinctie între cazul în care construim un nod interior. Metoda de selectie arborescenta este inspirata din organizarea unui turneu prin eliminare .Completam de jos în sus vârfurile interioare ale arborelui cu minimul valorilor asociate descendentilor. calculându-se valoarea minima dintre valorile asociate descendentilor sai. 65 . Evidenta construirii nodurilor terminale o tinem cu variabila z. În radacina va ajunge astfel elementul minim din elementele ramase în sir. parinte al unuia dintre cele x noduri terminale de pe nivelul r+1 sau un nod terminal.

a. 66 . în afara de cuvântul care reprezinta cheia de identificare a nodului si frecventa de aparitie si cele doua adrese de înlantuire.d. In capitolul cu aplicatii se exemplifica utilizarea arborilor de cautare în rezolvarea unei probleme care se numeste “ Construirea concordantelor “ . mai mic decât în cazul listelor ordonate. pâna la CTRL / Z. iar nodurile ale caror chei au valori mai mari decât v se gasesc în subarborele sau drept.în radacina se pune primul cuvânt . traversarea acestuia în inordine parcurge nodurile în ordinea crescatoare a valorilor cheilor asociate. nodurile cu chei mai mici decât valoarea cheii asociate unui anumit nod se gasesc în subarborele stâng al acestuia.v ARBORELE BINAR DE CAUTARE Definitie Se numeste arbore binar de cautare un arbore ale carui noduri cuprind o singura cheie de identificare. Daca cheile asociate unui arbore binar de cautare sunt numerice.în stânga ei se pune cuvântul urmator care-l precede alfabetic pe primul . Cautarea unei informatii identificate printr-o valoare v a cheii începe de la radacina si se termina în cel mai rau caz la unul din nodurile terminale. . Aceasta problema cere sa se afiseze cuvintele distincte si frecventa lor de aparitie stiind ca se citesc mai multe cuvinte.în dreapta se pune cuvântul urmator care-i urmeaza alfabetic s. Cuvintele citite vor fi puse într-un arbore binar de cautare astfel: . daca cuvântul este diferit de cele existente deja. Fiecare nod din arbore cuprinde. Afisarea cuvintelor se obtine în ordine alfabetica daca se traverseaza arborele de cautare în inordine. Adaugarea unui cuvânt în arbore presupune cautarea lui în structura arborescenta si legarea lui de nodul terminal corespunzator. Dispunerea nodurilor arborelui pe niveluri face ca numarul testelor la cautare sa fie . câte unul de pe o linie. în general. cautarea presupunând testarea a cel mult atâtea noduri câte niveluri are arborele binar de cautare.m.

v ARBORELE GENEALOGIC Arborele genealogic al unei persoane este un arbore oarecare . Fiind date numele a doua persoane din familie . iar ceilalti fii . nodurile neterminale ale arborelui putând avea unul sau mai multi fii. Un arbore oarecare poate fi reprezentat ca un arbore binar daca se pastreza legatura spre tata numai pentru primul fiu ( legatura stânga ). 67 . sa se afiseze cel mai apropiat stramos comun al celor doua persoane. Datele se considera corecte.: 1 tata 4 1 2 3 frati ===> 2 5 3 6 4 7 ===> 5 6 7 frati 1 2 frati 5 3 frati 6 4 7 Problema a carei rezolvare este prezentata în capitolul cu aplicatii are urmatorul enunt: Se considera un arbore genealogic care cuprinde descendentii unei persoane. Ex. fratii primului. se leaga între ei ( pe legatura dreapta ).

arborele binar asociat expresiei E2. ca subarbore stâng arborele asociat expresiei E1. pentru orice expresii aritmetice E1 si E2 Ø ( E )= E . iar E1 si E2 sunt expresii aritmetice. a-b . pentru orice expresie aritmetica 68 . Definitie Fie o expresie aritmetica . atunci arborele binar asociat lui E coincide cu arborele binar asociat lui E1. unde op este unul dintre operatorii admisi . Forma poloneza prefixata Ç a lui E se obtine astfel: Ø â =a.Unei expresii aritmetice formate dintr-un singur operand îi asociem un arbore binar format doar din nodul radacina în care punem operandul respectiv . Se poate asocia unei expresii aritmetice E un arbore binar complet astfel: . a/b . . arborele binar complet asociat are în radacina operatorul op . a^b arborii binari asociati sunt: + * / ^ a b a b a b a b a b Teorema Parcurgerea în preordine a unui arbore binar asociat unei expresii aritmetice E da forma prefixata a expresiei E. iar ca subarbore drept.v FORMA POLONEZA A EXPRESIILOR ARITMETICE Este una dintre cele mai importante aplicatii ale arborilor binari si a fost introdusa de matematicianul polonez J. pentru orice operand a care este o constanta sau o variabila Ø E1 op E2 =op E1 E2. Lukasiewicz. a*b . Ex. unde E1 este o expresie aritmetica.Daca E = (E1).Daca expresia aritmetica E este de forma E1 op E2 .: Pentru expresiile aritmetice simple : a+b .

Pentru expresia E= a*b+c/d-e. Atunci functia compusa f(f(j(x).g(y.y).Programul care construieste un arbore binar asociat unei expresii si obt. Pentru a întelega acest lucru sa luam urmatorul exemplu: Fie f si g doua functii de doua variabile si h si j doua functii de o variabila. forma poloneza prefixata asociata este: -+*ab/cde Într-adevar . v REPREZENTAREA FUNCTIILOR COMPUSE Parcurgerea în preordine a arborilor binari permite scrierea functiilor compuse fara paranteze. a*b+c/d-e=-a*b+c/de=-+a*bc/de=-+*ab/cde Obs.:Forma poloneza asociata unei expresii aritmetice nu este unica.h(z))) se poate reprezenta prin urmatorul arbore binar: f f j x y y z g h Parcurgerea în preordine a arborelui corespunde scrierii f f j x y g y h z care se realizeaza deci fara paranteze 69 . formei prefixate va fi prezentat în capitolul care contine aplicatii.

Graful se noteaza cu G= ( X . la fel ca si u si y . iar V contine toate arcele din U care au ambele extremitati în Y. iar multimea de arce V este . u7=(5.6) Definitie Un graf partial al grafului G= ( X . fie o submultime a acesteia. numite arce. spunem ca x este extremitatea initiala. fie chiar U. iar U o multime de perechi ordonate de elemente distincte din X.5). Fie graful de mai sus.2) u5=(4. u4=(4. Vom desena un graf partial al lui si un subgraf al lui: 1 1 2 3 2 3 4 5 6 4 graf partial subgraf Definitie Un subgraf al unui graf G= (X. Daca exista arcul u=(x. u3=(3. 70 .î.CAP IV GRAFURI ORIENTATE 1. spunem ca u si x sunt incidente. Un graf partial al unui graf dat se obtine pastrând aceleasi vârfuri si eliminând o parte din arce. u6=(6. VU.3). Un subgraf se obtine eliminând o parte din vârfuri si toate arcele incidente cu acestea. U ) a. U ) Daca x si y sunt extremitatile arcului u. Y_X. Vom spune ca subgraful H este indus sau generat de multimea de vârfuri Y. Ex: 1 2 4 5 6 3 u1=(1. X fiind o multime finita si nevida de elemente numite noduri sau vârfuri.4). adica G1 are aceeasi multime de vârfuri ca G. GENERALITATI: Definitie Se numeste graf orientat o pereche ordonata de multimi ( X. iar y este extremitatea finala a arcului.î. u2=(2.4). U ).U) este un graf H=(Y.V) a.1). iar vârfurile x si y sunt adiacente în G. U ) este un graf G1= ( X .y) .

(x)={u=(y.y)χ U} (multimea succesorilor lui x) Ã. u4) L2=(u1. deci C2n posibilitati de a alege 2 noduri distincte. numarul arcelor de forma (x. Ex. .numim grad exterior al unui vârf x .exista arcul de la y la x si exista ambele arce.y) / u χ U } (multimea arcelor ce ies din x) ù . iar pentru acestea exista 3 situatii ca ele sa fie adiacente. pentru un n dat sunt 3 x grafuri orientate complete cu n vârfuri.:În definirea unui lant nu se tine cont de orientarea arcelor. unde x= C2n Ex. u3. u2.y)χU (numarul arcelor care ies din x ).: Fie graful 1 u1 u2 2 u3 L1=(u1.(x). la grafurile orientate . y sunt adiacente în mai multe situatii: exista arcul de la x la y. Exista . notat cu d+ (x).numim grad interior al unui vârf x si-l notam cu d.x)χU (numarul arcelor care intra în x ). numarul arcelor de forma (y.x)χ U} (multimea predecesorilor lui x) Si cu ù +(x)={u=(x. Spre deosebire de grafurile neorientate la care exista un graf complet unic cu n vârfuri . Acest lucru decurge din faptul ca doua vârfuri x. putem construimai multe grafuri orientate având n vârfuri. rezulta ca . Obs.: pentru n=3 avem 27 de grafuri orientate complete cu 3 vârfuri 1 3 2 1 3 2 Pentru grafurile orientate sunt doua tipuri de arce incidente cu un vârf: arce care”intra” si arce care “ies” din acel vârf.Definitie Se numeste graf complet cu n vârfuri un graf care are proprietatea ca orice doua vârfuri distincte sunt adiacente. Vom nota cu: Ã+ (x)={y χ X / (x. u4) 4 u4 3 71 .x) / u χ U } (multimea arcelor ce intra în x) Definitie Se numeste lant într-un graf orientat un sir de arce cu proprietatea ca oricare doua arce vecine au o extremitate comuna. pentru un n dat. Se vor defini doua concepte diferite care sa corespunda numarului arcelor din fiecare din cele doua categorii: .(x)={y χ X / (y.

5. ….3).Definitie se numeste drum într-un graf orientat G=(X.y χ X exista un lant de extremitati x. U). 72 unde X={1. (4. 5. 4. (6. Ex. el are doua componente conexe: subgraful generat de multimea X1={1.: Fie grafurile: G=(X.U). 3} subgraful generat de multimea X2={4. 2. 6} .G=(X.Daca toate vârfurile circuitului. (1. Definitie O componenta tare conexa a unui graf G =(X.y Definitie Se numeste componenta conexa a unui graf orientat . unde X1={1.U). 2). 5)} 1 3 4 6 sau pentru oricare doua Definitie Un graf se numeste tare conex daca x =1 vârfuri x. U1) . 2. 4} si U={ (1. subgraful lui G generat de X14 {x} nu mai este conex). un subgraf conex al sau maximal în raport cu aceasta proprietate(oricare ar fi un nod din subfraf nu exista lant între acel nod si vârfurile care nu fac parte din subgraf ). circuitul se numeste circuit elementar.cu exceptia primului si ultimului nod . 3. Definitie Se numeste circuit un drum care are x1=xn si arcele sunt distincte. (3.2). 5).cu X= {x1. 1 3 4 G1=(X1.sunt distincte doua câte doua.Y1) al lui G care este tare conex si care este maximal în raport cu aceasta proprietate ( oricare ar fi x χ X \ X1. ( 3. drumul se numeste drum elementar.4)} 2 Graful G este conex El are o singura componenta conexa – graful însusi 2 5 Graful G1 nu este conex. x2. (2. 2. 3.U) este un subgraf G1=(X1. un lant în care toate arcele au aceeasi orientare . 6} si U1={(1.2). Definitie Un graf orientat se numeste graf conex daca pentru oricare doua vârfuri distincte x. y χ X exista un drum de la x la y si un drum de la y la x. 3). xn} si se noteaza cu D. Daca vârfurile drumului sunt distincte .

daca exista drum de la xi la xj în G mij= 0 . 1.j]=0 then a[I. Matricea drumurilor. unde: 1 daca xi este extremitate initiala a arcului uj bij = -1 daca xi este extremitate finala a arcului uj 0 daca xi nu este extremitate a arcului uj 1. xj )χ U daca( xi . a[k.2. Matrici asociate grafului: 1.se numeste matricea drumurilor asociata grafului G matricea M= (mij)nxm data prin: 1 . Matricea vârfuri-arce. xj ) χ U Matricea de adiacenta nu mai este obligatoriu simetrica.sau matricea de incidenta a grafului G . Acest algoritm construieste matricea drumurilor pornind de la matricea de adiacenta a grafului si consta în urmatoarele: for k=1 to n for I=1 to n (i!k) for j=1 to n (j!k) if a[I. ca în cazul grafurilor neorientate. Aceasta este un tablou bidimensional cu n linii si n coloane având elemente 0 sau 1 : 1 aij = 0 daca ( xi .2. REPREZENTAREA GRAFURILOR ORIENTATE Pentru reprezentarea unui graf orientat se folosesc: 1.1.j]:=min(a[i.este o matrice B=(bij )nxm .k]. în caz contrar Un algoritm simplu de determinare a matricii drumurilor unui graf este algoritmul Roy-Warshall.3. Matricea de adiacenta este matricea cea mai utilizata în reprezentarea unui graf orientat.j]) endif endfor endfor endfor 73 .

U) cu X={1. 74 .y:1.x.j]:3).. end end. writeln(‘dati nr. readln(n).i..1. Var a:array[1.nmax] of 0.n} este urmatorul: Program rw.k: 1. m:word.nmax.. n. Const nmax=100. procedure init.j]=0 then a[i.j]=1 deci când exista drum de la xi la xk si drum de la xk la xj.j ]=0 al matricii A devine 1 daca exista un nod k astfel încât a[i. writeln(‘matricea drumurilor este:’) for i:=1 to n do begin writeln.y)..k]=1 si a[k. i. end.nmax.j. Programul Pascal de determinare a matricii drumurilor unui graf G=(X. readln(x.k]*a[k. a[x.de noduri:’).. begin writeln(‘dati nr.. de arce:’). for k:=1 to n do for i:=1 to n do for j:=1 to n do if a[i.’:’).y]:=1.j]. begin init..readln(m). {initializeaza matricea de adiacenta} var i. end. for i:=1 to m do begin write(‘arcul ‘..1.nmax. for j:=1 to n do write(a[i.Asadar un element al matricii a[i.j]:=a[i.

2.Liste de adiacenta.n] of integer si un vector C:array[1.1. p^.next:=C[i].i]=0 2.2.indica coloana din T din care începe lista vecinilor lui i.pentru orice vârf xχ X se construieste o lista L(x) a succesorilor sai.1.i]. C[i] pointeaza la începutul listei de adiacenta a lui i.n] of integer cu urmatoarea semnificatie: § C[i].nod:=j.i] este ultimul element din lista. daca T[1. Element=record nod:1..j) presupune actualizarea new(p)... var C:array[1. 75 . Reprezentarea listelor folosind structuri dinamice de date: Se considera un vector C cu n componente de tip referinta. C[i]:=p.i] -reprezinta un vârf. T[2.i]. § T[1. § T[2.n. Reprezentarea listelor de adiacenta folosind tablouri: Se considera un tablou T:array{1.reprezinta adresa (coloana pe care se afla) urmatorul element din lista în care se afla T[1. Initial for i:=1 to n do C[i]:=nil. Existenta unui arc (i.2. next:reper end. Listele de adiacenta pot fi reprezentate folosind tablouri sau structuri dinamice de date : 2. p^..n] of reper.. p: reper. Sunt deci necesare urmatoarele declaratii: Type reper=^element.

În continuare se vor prezenta algoritmi de obtinere a unor astfel de drumuri fara a determina toate drumurile dintre vârfurile grafului. iar inexistenta arcului (xi. Se vor prezenta în continuare urmatorii algoritmi: § Algoritmul lui Dijkstra § Algoritmul lui Roy-Floyd § Metoda drumului critic În capitolul cu aplicatii vor fi prezentati algoritmi în limbajul Pascal care ilustreaza utilizarea acestor algoritmi. care asociaza fiecarui arc uχ U lungimea ( costul sau ponderea) sa cu l(u). notând ponderea cu l(u) . U) si o functie l: U τR+ .xj)χU Semnificatia acestei alegeri este urmatoarea: drumul cel mai scurt de la xi la el însusi este de lungime 0. xj) este echivalenta cu existenta unui arc de lungime infinita care nu va interveni niciodata într-un eventual drum minim de la xi la xj. § Determinarea drumurilor de lungime minima ( maxima) pornind dintr-un vârf dat la toate celelalte noduri. § Determinarea drumurilor de lungime minima ( maxima) între oricare doua vârfuri. daca i=j daca (xi. daca l(u) reprezinta costul transportului de la xi la xj problema revine la determinarea drumurilor având costul de transport minim. DRUMURI MINIME SI MAXIME ÎN GRAFURI ORIENTATE Fie un graf orientat G=(X. Pentru graful considerat se pot pune urmatoarele probleme: § Determinarea drumurilor de lungime minima ( maxima) între doua vârfuri xi. unde u=(xi. etc.xj) reprezinta durata de trecere de la xi la xj. Parcurgerea grafurilor orientate se realizeaza prin aceleasi metode care au fost prezentate la grafurile neorientate : DF si BF. Lungimea unui drum în acest graf este egala prin definitie cu suma lungimilor asociate arcelor sale.xj).3. problema revine la determinarea drumurilor de durata minima.xj)∀U l(xi. daca (xi. Daca vom considera drept noduri diferite puncte dintr-un oras. Pentru tratarea problemelor de minim vom asocia grafului G o matrice a costurilor C=(cij )nxn definita astfel: cij = 0 + . 76 . xj. Rezolvarea problemei determinarii unor drumuri de lungime minima într-un graf are multiple aplicatii practice.

precum si unul dintre drumurile minime de la x 0 la xi. n unde C este matricea costurilor. daca xi ∀ S Initial di = C(i0. Algoritmul se încheie când S contine toate nodurile pentru care exista drum de la nodul de plecare . Se considera S multimea vârfurilor xiχ X pentru care am gasit drum minim de la x0 la xj . D3=(1. Pentru a retine si drumurile minime ( nu numai lungimile lor ) vom considera un vector PREC care retine indicele precedentului fiecarui nod în drumul minim de la x0 la acel nod si care se actualizeaza la fiecare modificare dj:=dk+C(k. 4) de lungime 5 ( drumul de la 1 la 4 are lungimea 5 ).d2. D2=(1. o functie l: U τ R+ si un nod x0 . 2.dn) a. Algoritmul în Pascal este prezentat în capitolul cu aplicatii.4. Pentru a alege nodul xk ce urmeaza a fi adaugat în S vom folosi un vector d=(d1. di = lungimea drumului minim de la x0 la xi. 3. daca xj χS lungimea drumului minim de la x 0 la xi. 5 ) de lungime 2. ce foloseste numai vârfuri din S. sa se determine toate vârfurile xi pentru care exista drum de la x0 la xi . 5. 77 .1.j) PREC:=k. 2. La fiecare pas adaugam în S acel nod xk χ X \ S cu proprietatea ca drumul minim de la x0 la xk are cel mai mic cost dintre drumurile de la x0 la xp . cu xpχ X \ S. vom obtine în ordine: D1=( 1. În final vectorul d va contine costurile (lungimile) drumurilor minime de la x0 la celelalte noduri. 2 ) de lungime 1. lungimea celui mai scurt drum .….U). 3 ) de lungime 4. Algoritmul utilizeaza metoda Greedy generând drumurile minime în ordinea crescatoare a lungimilor. i) … i= 1. 5. De la 1 la 6 nu exista drum.î.: 2 1 3 1 2 10 3 1 1 1 5 3 4 6 Pentru graful considerat . dj= . ( drumul de la 1 la 2 are lungimea 1 ). ( drumul de la 1 la 5 are lungimea 2 ). Ex. D4=(1. Dupa adaugarea lui xk în S trebuie actualizate valorile lui d. daca pentru un nod x j nu exista un astfel de drum . Initial S={ x0 }. plecând din nodul 1. 2. ALGORITMUL LUI DIJKSTRA Problema: Fiind dat un graf orientat G=(X. ( drumul de la 1 la 3 are lungimea 4 ).

U) cu X={x1. cik + ckj ) endfor endfor endfor Acest algoritm poate fi privit ca o succesiune de n transformari aplicate matricii C.…. Pentru determinarea drumurilor de lungime maxima se ataseaza grafului o matrice M=(mij)nxn definita astfel: l( xi.2.4.xj) χ U . Acest algoritm de determinare a tuturor drumurilor minime între oricare doua vârfuri ale unui graf G va fi prezentat în capitolul cu aplicatii. daca i=j 78 mij = . daca (xi.. xj) . xj (i!j) lungimea minima a drumurilor de la xi la xj precum si aceste drumuri (în caz ca exista drum de la x i la xj ). Se va folosi o matrice D ( patratica . daca (xi. xn } si o functie l: UτR. Algoritmul Roy-Floyd determina lungimile minime ale drumurilor între oricare doua noduri ale grafului într-o matrice C= ( cij )nxn unde cij = 0. ALGORITMUL LUI ROY-FLOYD Problema: Fiind dat un graf G=(X. daca i=j lungimea drumului minim de la xi la xj . Simultan cu determinarea lungimilor minime ale drumurilor pot fi retinute si acestea. x2 . sa se determine pentru fiecare pereche de noduri x i .xj) ∀U si (i!j) 0 . Se porneste de la matricea costurilor C : for k=1 to n for i=1 to n (i!k) for j=1 to n (j!k) cij :=min ( cjj . daca exista drum de la xi la xj daca nu exista drum de la xi la xj Determinarea matricii C este asemanatoare algoritmului Roy-Warshall pentru obtinerea matricii drumurilor. având nxn elemente) ale carei elemente d ij sunt multimi de noduri (d ij va reprezenta în final multimea nodurilor ce pot precede pe xj în drumul minim de la xi la xj).

Fie matricea M asociata grafului .j χ {1.n} vom avea multimea nodurilor ce pot precede pe xj într-un drum maxim de la xi la xj..xj) . iar D=(dij ) nxn cu {xi} dij = Ô daca m ij > daca m ij = si (i!j) sau i=j for k=1 to n for i=1 to n (k!I) for j=1 to n (k!j) if m ij < m ik + m kj then m ij := m ik + m kj d ij := d kj else if m ij = m ik + m kj then d ij := d ij 4 d kj endif endif endfor endfor endfor În matricea M vom avea în final lungimile drumurilor maxime între oricare doua noduri. iar în d ij … I. pentru perechi de noduri xi. În capitolul cu aplicatii va fi prezentat algoritmul de determinare a tuturor drumurilor maxime între oricare doua noduri folosind acest algoritm 79 . ….Aceasta matrice este asemanatoare matricii costurilor atasata grafului pentru determinarea drumurilor minime. marcam în matrice . Algoritmii de determinare a drumurilor minime pot fi adaptati cu mici modificari pentru determinarea drumurilor maxime. xj (i !j) pentru care nu exista arcul (xi. cu diferenta ca .

momentul începerii ei este reprezentat de extremitatea initiala. activitati ce se numesc activitati critice.4.D) se desfasoara în acelasi timp cu activitatea reprezentata de arcul (B. Pentru un astfel de graf nodurile reprezinta evenimente care pot fi interpretate ca indicând realizarea unor obiective partiale ale lucrarii . Pentru o activitate. activitati). Definitie : se numeste drum critic într-un graf de activitati un drum de lungime maxima care leaga nodul initial de nodul final. 80 .D).C) si (C.C) si începerea activitatii reprezentate de arcul (C.D) etc.C) si (B. DRUM CRITIC ÎNTR-UN GRAF DE ACTIVITATI Definitie : Un graf de activitati este un graf asociat unei lucrari complexe a carei realizare presupune desfasurarea mai multor actiuni( procese.B) si începerea activitatii reprezentate de arcele (B.: C 4 2 7 1 2 A B D E Pentru graful de mai sus începerea lucrarii este reprezentata prin vârful A. iar terminarea ei prin vârful E.D). iar momentul terminarii ei de extremitatea finala a arcului respectiv. arcele reprezinta etapele sau activitatile elementare ale lucrarii. Pentru a nu avea mai multe arce paralele si de acelasi sens între doua vârfuri ale grafului se introduc evenimente si activitati fictive. Calculul timpului de realizare a evenimentului final revine la cautarea în graf a drumului cel mai lung sau a drumului critic. Atunci când construim un astfel de graf trebuie sa respectam urmatoarea regula: toate arcele care pleaca dintr-un vârf X reprezinta activitati ce nu pot începe decât dupa terminarea tuturor activitatilor reprezentate de arcele care sosesc în vârful X. iar lungimea asociata unui arc –timpul de desfasurare a activitatii asociate acelui arc. Nodul B reprezinta evenimentul ce marcheaza terminarea activitatii reprezentate de arcul (A.Programme Evaluation and Research Task si CPM. Pentru un graf dat drumul critic nu este unic Drumul critic reuneste activitati a caror întârziere duce la întârzierea întregii lucrari. nodul C este evenimentul ce marcheaza terminarea activitatii reprezentate de arcul (B. Metoda este cunoscuta sub denumirile: PERT. Ex. Activitatile reprezentate de arcele (B.Critical Path Method.

program carti. Teancuri de carti ( STIVA ): Biblioteca unui liceu primeste un numar de carti si vrea sa-i separe pe autori. autor:array[1. while not eof do begin readln(autorul). var p:reper. while p<>nil do begin writeln(p^. begin for i:=1 to 100 do top[i]:=nil..cartea:string). p^. n_ex:byte.n:byte. begin p:=top[i]. procedure listare(top:reper. var i. autorul. function indice(autorul:string):byte.’ ’. Scrieti un program care sa simuleze acesta activitate stiind ca autorii si titlurile cartilor se introduc de la tastatura pâna la CTRL\Z. CAP V APLICATII LISTE: 1.indice:=n end. n:=0.titlu:=cartea.n_ex:=1.cartea). type reper=^carte.autor[n]:=autorul.Pentru fiecare eveniment putem vorbi de o data asteptata si de o data limita de realizare a sa.titlu.next. procedure adauga(i:byte. p^.n_ex). next:reper end.i:=indice(autorul). p:=top. top:array[1.readln(cartea).next:=top[i]. p^.100] of string.cartea:string.write(’autorul:’) 81 .p^. begin writeln(’cartile ’.titlu=cartea then begin inc(p^. inc(n).autor).exit end else p:=p^. adauga(i..100] of reper. top[i]:=p end. carte=record titlu:string.n_ex).autor:string). begin for i:=1 to n do if autor[i]=autorul then begin indice:=i. while p<>nil do if p^. write(’cartea:’).exit end.write(’autorul: ’). var i:byte.next end end. new(p). var p:reper. Pentru fiecare autor se vor afisa titlurile cartilor si numarul de exemplare primit. p:=p^.

type reper =^element. prim:=prim^.cod). {stergerea primului element} begin if prim=nil then writeln(’depoul este gol’) else begin writeln(’iese locomotiva cu codul ’.prim^.end. procedure intrare. p:=prim. program depozit. p:reper. prim^. uses crt. Llistarea si S. 2.cod).next. procedure listare. prim^. procedure iesire. p:=p^. repeat writeln(p^. {adaugarea unui element} var codul:word. comanda:char.autor[i]) end.readln(codul).oprirea programului . ultim:=prim. 82 .next until p=nil end end. var prim. afisând locomotivele existente.next:=p.Sa se scrie programul care realizeaza dispecerizarea locomotivelor prelucrând comenzi de forma: I-intrarea unei locomotive. if prim=nil then {coada este vida} begin new(prim). Dispecerizare locomotive ( COADA ): Se considera un depou de locomotive cu o singura linie de cale ferata cu o intrare si o iesire. element=record cod:word. dispose(p) end end.next:=nil.cod:=codul. next:reper end. ultim:=p end end. for i:=1 to n do listare(top[i]. end else {se adauga in coada un nou element} begin new(p). p^. begin write(’codul locomotivei: ’). p^. ultim.cod:=codul. ultim^.next:=nil. E-iesirea unei loc. {traversarea cozii} begin if prim=nil then writeln(’depoul este gol’) else begin writeln(’locomotivele din depou sunt: ’). p:=prim.

prim:=nil.next:=p^.next {stergem logic elementul p^. repeat write(’comanda: ’). p^. ’S’. 3 Jocul lui Joseph ( LISTA CIRCULARA ): Un numar dat n de copii stau în cerc si numara .Fiecare al m-lea copil iese din cerc. repeat for i:=1 to m-1 do p:=p^. case comanda of ’I’:intrare.next^. comanda:=UpCase(comanda).nume). readln(p^.nume). 83 .p^.next^} until p=p^. {coada se transforma in lista liniara} {simulam jocul} p:=sant. n. ultim.i:byte.next:=sant^.readln(m). începând cu primul copil asezat în cerc si continuând în ordinea initiala în care au fost asezati .ultim:=sant. readln end. Câstiga jocul ultimul copil ramas în cerc.readln(n). program Joseph. readln(comanda). {numaram m copiii} writeln(’Iese copilul ’.p^.Sa se simuleze jocul stiind n. type adresa=^copil. {lista vida} write(’n=’).next^.next. write(’m=’). next:adresa end.next. writeln(’Copiii:’).m s numele copiilor.next:=p. p:adresa.next. ultim^. Begin new(sant). copil=record nume:string. ultim:=p end. ’E’:iesire.’L’:listare.nume). var sant. for i:=1 to n do begin new(p). readln end. end until comanda=’S’ . ultim^.Begin clrscr. writeln(’ Castiga ’.m.

n. until p=sant1. pred. until p=sant2.next:=sant2. if p=sant2 then writeln(’lista vida’) else begin repeat write(p^.new(sant2). p^. writeln end. sant2^. var sant1. c) sa se afiseze nr în ordine crescatoare. 84 .pred:=sant1. next:reper end.4. b) sa se afiseze nr în ordinea inversa citirii.next. sw:=1.next.p. program numere. p:=sant1^. ( LISTA DUBLU ÎNLANTUITA – cu santinele): Se citesc de la tastatura mai multe nr naturale nenule <=35000. mai putin ultimul element care este 0. p^. write(’numar: ’).sw:word.info:=n.readln(n). while n<>0 do begin p:=sant2. sant1^. writeln(’b)’). if p=sant1 then writeln (’lista vida’) else begin repeat write(p^.info.’ ’).sant2. sant2^.next.readln(n).next:=sant2.pred:=p. writeln end. element=record info:word. while sw=1 do begin sw:=0.info.new(sant2). p:=sant1^. write(’numar: ’). end. type reper=^element. Folosind o lista alocata dinamic : a) sa se afiseze numerele în ordinea citirii. p:=p^.pred. p:=p^. begin new(sant1).pred.q:reper. writeln(’a)’).’ ’). p:=sant2^.

next.info. ultim^. ultim:=q end. while p^. procedure adauga(nr:integer). end end.info:=p^. begin p:=prim.n:=nr. Lista se va afisa înainte si dupa stergere.next^.next^. nr:integer.next until p=sant2^. p^. write(’c)’).next:=q. 85 .info. Sa se determine valoarea minima din lista si sa se stearga elementul corespunzator. p:=sant1^. var q:reper. var prim.if p<>sant2 then begin repeat if p^. readln end.n:=p^. writeln end. q^. p^.info then begin sw:=1.info. if p=sant2 then writeln(’lista vida’) else begin repeat write(p^. 5. citite de la tastatura( pâna la CTRL\Z). type reper=^element. program min_lista.Numerele se pun în lista în ordinea citirii. p:=p^. element=record n:integer.info>p^.pred.ultim.next. p:=p^.n<>nr do p:=p^. {cautam nr in lista} if p=nil then begin new(q). until p=sant2.info:=n end.’ ’).next.next^. Stergerea elementului minim dintr-o lista ( LISTA SIMPLU ÎNLANTUITA ): Sa se creeze o lista de numere întregi distincte.p:reper. next:reper end.

min:integer. ultim:=prim. {salvam adresa elementului care se sterge} p^:=q^. writeln(’adauga numerele:’).’ ’). prim^.next^.next end. p:=p^. 5. Dispose (q) {elibereaza memoria} end.next:=nil.next^. p:=adr_ant_min. write(’primul nr este:’). var p. begin writeln(’lista:’).readln(nr).function adr_ant_min:reper. adr_ant_min:=pmin end. var q:reper. procedure listare.pmin^. p:=p^.n.next. begin min:=Maxint.n). pmin:=p end. listare. listare.n. writeln end. writeln(’minimul este ’. prim^.next end. LISTA SIMPLU ÎNLANTUITA –cu santinela: 86 .n:=nr. while not eof do begin read(nr).n<min then begin min:=p^.pmin:reper. p:=prim. p:=prim. Begin new(prim). adauga(nr) end. procedure stergere(p:reper).next^. while p<>nil do begin write(p^. while p<>nil do begin if p^. readln end. begin q:=p^.{adresa elem anterior celui minim} stergere(p).

next:=nil.p:lista.cifra.er:integer. element=record info:integer. Programul va afisa elementele listei si suma elementelor sale. var rad:reper. suma. {returneaza adresa radacinii} var p:reper. p^. while p<>nil do begin write(p^. begin clrscr.’ ’).dr:reper end.Se citeste un numar natural ce contine maxim 200 cifre. Sa se alcatuiasca un program care creeaza o lista simplu înlantuita ce contine ca elemente cifrele pare ale numarului dat. st. p^. type lista=^element.er). readln end. next:lista end.{generarea radacinii p^ a subarborelui} 87 .p^. val:byte. begin read(val). var nr:string. write(’numarul este:’). ultim:=sant. p:=p^. if val>0 then {subarborele este nevid} begin new(p).next end.suma). ultim^. for i:=1 to length(nr) do begin val(nr[i]. sant. if cifra mod 2=0 then begin suma:=suma+cifra. new(sant). writeln(’suma este: ’. p:=sant. ultim^.info:=cifra.inf:=val. type reper=^nod. suma:=0.next:=nil. nod=record inf:byte. uses crt. end end.cifra.next:=p. program lista_sant.info. ARBORI: 1.ultim. {adresa radacinii arborelui} function arbore:reper.i.readln(nr). new(p). Crearea si traversarea unui arbore binar: program parcurg_arbore.

writeln. procedure inordine(p:reper). p^.write(’nodul din stg. {R} {S} {D} {S} {R} {D} {S} {D} {R} 2. procedure preordine(p:reper). subarb. 88 . inordine(rad). postordine(p^. cuv:string[20].dr). si-l leaga de rad} write(’nodul din dr.st).writeln(’arborele parcurs in inordine: ’). begin if p=nil then begin write(p^. writeln. postordine(rad). Arbore binar de cautare: program concordante. nod=record cuvant:string[20]. arbore:=p. write(p^.’:’).dr).{gen. procedure inordine(p:reper). preordine(p^. procedure postordine(p:reper).st:=arbore. end end. end end.{gen.writeln(’arborele parcurs in postordine: ’).val. nodului ’.st). dr.dr:=arbore.inf:2).writeln(’arborele parcurs in preordine: ’). writeln. frecv:byte. nodului ’.inf:2). p^. subarb. write(p^.dr:reper end. begin if p=nil then begin inordine(p^. var rad:reper.readln end. begin writeln(’nodul radacina:’).st). type reper=^nod.inf:2).val. st. inordine(p^. preordine(p^. st. si-l leaga de rad} end else p:=nil. writeln.’:’). begin if p<>nil then begin inordine(p^. begin if p=nil then begin postordine(p^. rad:=arbore. end end. end.st).dr). preordine(rad).

dr:= nil end end else if cuv=p^.dr:reper end. with p^ do begin cuvant:=cuv. begin if p=nil then begin new(p). var p:reper. n:byte. begin rad:=nil.dr) end. begin write(’nodul: ’).cuvant then inc(p^. caut_adaug(rad).cuvant then caut_adaug(p^. end. procedure caut_adaug(var p:reper). if rad =nil then writeln(’Arbore vid’) else begin writeln(’Cuvintele cu frecventele lor: ’). inordine(rad) end. while not eof do begin readln(cuv).frecv) else if cuv<p^.dr) end end. var rad:reper.writeln(p^. inordine(p^. 89 .nd:byte.’ ’. type reper=^nod. st:=nil. function arbore(n:byte):reper. ns. readln end. frecv:=1. nod=record inf:byte. Crearea unui arbore perfect echilibrat: program creare. 3.p^.frecv). st.cuvant. writeln(’Cuvintele :’).st) else caut_adaug(p^.

90 .p. preordine(p^.readln(n). Program arbore_genealogic.read(p^.st:=nil. end else write(’. arbore:=p end. Fiind date numele a doua persoane din familie . {gen subarb dr cu nd noduri} if nd>0 then p^. sa se afiseze cel mai apropiat stramos comun al celor doua persoane.’:2). writeln(’Arborele perfect echilibrat: ’).rad.pp:reper. type reper=^nod.g2:byte.dr:=nil. subarb. Arbore genealogic Se considera un arbore genealogic care cuprinde descendentii unei persoane. st.{gen.q. begin write(’n= ’). var rad.new(p).dr).st). nume:string. preordine(rad) end else writeln(’Arbore vid’).dr:=arbore(nd) else p^. gen:byte. nd:=n-ns-1. nod=record nume:string.tata:reper end.inf). uses crt.dr. end.} ns:=n div 2. preordine(p^. procedure preordine(p:reper). begin if p<>nil then begin write(p^. end. if n>0 then begin rad:=arbore(n). g1.st:=arbore(ns) else p^. {gen subarb st cu ns noduri} if ns>0 then p^. 4.inf:3).

q:=pp. p:=pp. creare(p^. {g1=generatia pers. dec(g1) until g1=g2.tata:=tata. if g then begin gasit:=g. var g:boolean.tata:reper. write(’Fratele lui ’.tata. begin if p<>nil then if p^. repeat write(’Persoana 1: ’). until gasit(rad). write(’Primul fiu al lui ’. readln(nume). readln(nume) until gasit(rad). 91 .gen.nume.g) end end. if nume=’’ then p:=nil else begin new(p).nil.gen. creare(rad. p^. 1} g1:=q^. g1:=p^.’:’).dr.gen:=g. dec(g2) until g1=g2 else if g1>g2 then repeat p:=p^.pp:=p end else begin g:=gasit(p^.0). 2} if g1<g2 then repeat q:=q^. repeat write(’Persoana 2: ’).g:byte).p^.’:’) .p^. {g2=generatia pers.st. var nume:string.g+1). gasit:=gasit(p^. begin readln(nume).nume:=nume. function gasit(p:reper):boolean.st).tata.nume.procedure creare(var p:reper.p.nume=nume then begin gasit:=true. creare(p^.tata. Begin clrscr. write(’Stramosul: ’).dr) end else gasit:=false end.exit end.

begin if x<y then min:=x else min:=y. procedure calcul(n:integer.x.st^. end else if y<>0 then begin 92 .niv+1). nod=record inf:integer.dr:reper end. var p:reper.dk:integer). type reper=^nod.dr. r:=-1.tata.inf:=min(q^.niv+1).i:integer.v. function min(x.y:integer):integer.20] of integer. 5. creare(q^.dr^.niv+1). begin dk:=1. begin if niv<r then begin new(q).dr^.dr.niv:integer).st. creare(q^. st. r:=r+1 end end. writeln(’Stramosul comun cel mai apropiat este: ’. while dk<n do begin dk:=dk*2. a:array[1. creare(q^.q^.u. end.inf. q^.tata end.y. program arb_sortare.. creare(q^. var r.p^. readln end.inf).st. if u<=x div 2 then begin new(q).inf:=min(q^.r.inf) end else if niv=r then begin u:=u+1.q^. n. q:=q^.dk. Arbore de sortare: Sortarea unui sir de numere prin selectie arborescenta.while p<>q do begin p:=p^.st^.niv+1).inf. procedure creare(var q:reper.nume). q^.

inf<>maxint then begin if q^. 93 .r.inf:=maxint else if q^. q^.st=nil then q^.inf:=min(q^. sir:array[1. a[1]:=p^. u:=0.inf=q^. y:=dk-n.st^.inf end.inf) end end.dr). writeln(’Dati sirul’).st) else cautare(q^.st^.q^. Forma poloneza a expresiilor aritmetice: program forma_pol.i:byte. new(q).readln(n). begin c:=sir[i]. type reper=^nod.inf:=a[v].dr^.inf then cautare(q^. 6.st:=nil.dr:=nil. q^. procedure cautare(q:reper). writeln(’Sir ordonat’).inf:=a[v].dr:=nil end end else begin v:=v+1. begin write(’n=’).v:=0. st.30] of char. for i:=1 to n do write(a[i]..dk). creare(p. var n.v:=v+1. q^.0).inf.inf. q^.’ ’). for i:=2 to n do begin cautare(p). calcul(n. i:=i+1. end. end end. a[i]:=p^. for i:=1 to n do read(a[i]). q^.dr:reper end. q^. c:char. procedure getchar. x:=n-y. rad:reper. begin if q^. q^. end.st:=nil. nod=record v:char. new(q).

var p:reper. end end.’-’] do begin new(r). end end. procedure putere(var r:reper). end end. var p:reper. putere(r^. r^. termen(r^. procedure termen(var r:reper). p:=r. while c in [’+’.’/’] do begin new(r). r^.forward.st:=p. r^. while c=’^’ do begin new(r). var p:reper.v:=c.procedure factor(var r:reper).st:=p. begin 94 . p:=r. p:=r. begin termen(r). factor(r^. if i<=n then getchar.v:=c. begin putere(r).dr). r^.dr). begin factor(r).forward.st:=p.v:=c.forward. procedure termen(var r:reper). procedure putere(var r:reper). procedure factor(var r:reper). procedure exp(var r:reper). p:=r. p:=r. if i<=n then getchar. p:=r.dr). r^. r^. while c in [’*’. var p:reper.

r^.m=’). begin if r<>nil then begin write(r^.m. begin write(’n.20. writeln(’Dati expresia: ’).getchar.st:=nil. readln(n). afisare(r^. end end.exp(rad). n.20] of integer.j]:=0.v:integer.readln(n. var viz:array[1. afisare(rad). writeln(’Forma poloneza prefixata: ’).20] of 0.v). Parcurgerea BF: program parcurgere_BF. r^.20] of integer. for i:=1 to m do begin 95 .1..p. afisare(r^. A:array[1. i:=1. if c=’(’ then exp(r) else begin new(r). GRAFURI NEORIENTATE 1.u.x.. C:array[1.. for i:=1 to n do read(sir[i]).v:=c. procedure afisare(r:reper). readln end. for i:=1 to n do for j:=1 to n do A[i.1.m).j. begin write(’Lungimea expresiei=’)..i.dr). r^.y.st). end.dr:=nil end..

write(’muchia ’,i,’=’); readln(x,y); A[x,y]:=1;A[y,x]:=1; end; write(’varful de plecare : ’);readln(i); for j:=1 to n do viz[j]:=0; C[1]:=i; p:=1;u:=1; viz[i]:=1; while p<=u do {coada nu este vida} begin v:=C[p]; for j:=1 to n do if (A[v,j]=1) and (viz[j]=0) then begin u:=u+1; C[u]:=j; viz[j]:=1 end; p:=p+1 end; write(’lista varfurilor in parcurgere BF , plecand din ’,i,’ este: ’); for j:=2 to n do write(C[j],’ ’); writeln; readln end.

2. Parcurgerea DF:

program parcurger_DF; var viz:array[1..20] of 0..1; A:array[1..20,1..20] of integer; n,m,k,ps,i,j,x,y:integer; S,urm:array[1..20] of integer; begin write(’n,m=’);readln(n,m); for i:=1 to n do for j:=1 to n do A[i,j]:=0; for i:=1 to m do begin write(’muchia ’,i,’=’);readln(x,y); A[x,y]:=1;A[y,x]:=1; end; write(’varful de plecare: ’);readln(i); for j:=1 to n do begin 96

viz[j]:=0; urm[j]:=0 end; S[1]:=i;ps:=1; viz[i]:=1; write(’lista varfurilor in parcurgere DF plecand din ’,i,’ este:’); while ps>=1 do begin j:=S[ps]; k:=urm[j]+1; while(k<=n) and ((A[j,k]=0) or (A[j,k]=1) and(viz[k]=1)) do k:=k+1; urm[j]:=k; if k=n+1 then ps:=ps-1 else begin write(k,’ ’); viz[k]:=1; ps:=ps+1; S[ps]:=k; end end; readln end.

3. Grafuri euleriene ( verificarea faptului ca un graf este eulerian):

program verif; var eulerian:boolean; e,gr,c,c1:array[1..20] of integer; a:array[1..20,1..20] of integer; n,m,i,j,k,k1,x,y,l:integer; viz:array[1..20] of byte; function vf_iz :boolean; {val este true daca graful are vf izolate} var i,j,s:byte; begin vf_iz:=false; for i:=1 to n do begin s:=0; for j:=1 to n do s:=s+a[i,j]; 97

gr[i]:=s; if s=0 then begin vf_iz:=true; break; end; end; end; function grade_pare:boolean; {are val true daca gradele tuturor} var i:byte; { varfurilor sunt numere pare} begin grade_pare:=true; for i:=1 to n do if odd(gr[i]) then begin grade_pare:=false; break end; end; function conex:boolean; {are val true daca graful este conex} var b,viz:array[1..20] of byte; i,j,p,u,v:byte; begin for j:=1 to n do viz[j]:=0; b[1]:=1; p:=1;u:=1;viz[1]:=1; while p<=u do begin v:=b[p]; for j:=1 to n do if (a[v,j]=1) and (viz[j]=0) then begin u:=u+1; b[u]:=j; viz[j]:=1 end; p:=p+1; end; conex:=true; for i:=1 to n do if viz[i]=0 then begin conex:=false; break; end; end; Begin write(’n,m=’);readln(n,m); for i:=1 to n do for j:=1 to n do a[i,j]:=0; writeln(’dati muchiile grafului: ’); for i:=1 to m do begin write(’mucjia ’,i,’=’);readln(x,y); a[x,y]:=1;a[y,x]:=1; end; eulerian:=not vf_iz and grade_pare and conex; if not eulerian then writeln(’graful nu este eulerian’) else begin {se construieste in C primul ciclu} writeln(’graful este eulerian’); c[1]:=1; 98

a[j. for k:=1 to m do begin write(’muchia ’.n. for i:=1 to m+1 do write(’ ’.’= ’). m.j. gr[j]:=gr[j]-1. until c1[k1]=c1[1].n). writeln(’ciclu eulerian: ’).k. var x:array[1..p.{se depl elem in C} for j:=1 to k1-1 do c[j+l]:=c1[j+1].j]:=0 .q]:=1. readln end. k:=k+k1-1. end.k.10] of integer. 3. while k>1 do 99 . x[1]:=1. a[c[k-1]. a:array[1.. for j:=k downto l do c[j+k1-1]:=c[j]. sol:=0. repeat for j:=1 to n do if a[c[k].readln(p. gr[c1[k1-1]]:=gr[c1[k1-1]]-1.10] of integer.10.c[i]).readln(m.x[2]:=1.p]:=1 end.c[k-1]]:=0.k:=1.v.i. break.1.q:integer. end. Grafuri hamiltoniene(se determina toate ciclurile hamiltoniene dintr-un graf ): program hamiltonian. begin write(’m.sol.n=’)..j]=1 then begin k:=k+1.q). for p:=1 to n do for q:=1 to n do a[p. k:=2.a[q. c[k]:=j. a[p.q]:=0.

if sol=0 then write(’graful nu este hamiltonian’). Algoritmul lui Dijkstra.readln(n..i0.20] of word. end. break end.i0).20] of byte. writeln. end.begin v:=0. end else if k<n then begin k:=k+1. if sol=1 then writeln(’ cicluri hamiltoniene :’). if a[x[k-1]. if v=0 then k:=k-1 else if (k=n) and (a[x[n]. end. begin write(’n. end.m. {C= multimea varfurilor candidate la solutia la solutia S} vf_ant:array[1.x[1]]=1) then begin sol:=sol+1. { d[i]= lungimea minima a lanturilor de la i0 la i} C:array[1. for j:=1 to n do write (x[j]). {ALGORITMUL LUI DIJKSTRA} const inf=65535. {vf_ant[i]=anteriorul lui i pe lantul minim} i... readln. {L-lungimile muchiilor} d:array[1.lanturi minime într-un graf neorientat : program lanturi_minime.j.j.k:byte. dd:word.. LL:word. 4. var L:array[1.m. x[k]:=1.1.m:byte.i0:’).x[k]]=0 then v:=0. 100 . v:=1. var i. for i:=1 to k-1 do if x[k]=x[i] then begin v:=0.20] of word.20] of boolean.20. procedure citire. while (x[k]+1<=n) and (v=0) do begin x[k]:=x[k]+1.n..

i:=j end.LL).j]>0) then begin 101 . function d_min(var i:byte):word.j]. begin for i:=1 to n do d[i]:=inf. ’la ’. for j:=1 to n do if C[j] and (L[i.’ este:’). end.’la ’. var i:byte.j]:=LL. {i0 apartine lui S} end.j]>0 {vf_ant j este adiacent cu i0 } then begin d[j]:=L[i0. for j:=1 to n do if C[j] then if d[j]<min then begin min:=d[j].i) else begin write(’lantul minim de la ’. write(’de lungime =’.j:byte. while d_min(i)<inf do begin C[i]:=false. begin min:=inf. procedure initializari. C[i0]:=false. end. vf_ant[j]:=i0. lant_minim(i). begin if i<>i0 then lant_minim(vf_ant[i]). L[j. begin citire. for i:=1 to n do C[i]:=true. var j:byte. procedure lant_minim(i:byte). {d_min =min(d[j]) } min:word. for k:=1 to m do begin readln(i. initializari. end.i). d[i0]:=0. d_min:=min. begin for i:=1 to n do if i<>i0 then if C[i] then writeln(’Nu exista lant de la ’. write(i:3).j. procedure scriere. L[i. end end.i0.d[i]:2.i0.writeln end end.i]:=LL. for j:=1 to n do if L[i0.write(’muchiile si lungimile lor:’). var i.

j].i.’=’). for i:=2 to n do begin oras_prec:=c[i-1]. c[1]:=k.cmin:array[1..j.readln(n).k:byte.j]:=dd. readln(dd).j]<min) then begin min:=D[i. begin write(’n=’). var i:byte.n.dd:=d[i]+L[i. if dd<d[j] then begin d[j]:=dd... for i:=1 to n-1 do for j:=i+1 to n do begin write (’distanta dintre orasele ’. neales[k]:=false.maxlongint.20] of boolean. end end.i]:=dd.j]. begin min:=65535.20] of byte.oras_prec. jmin:=j end. type natural=0.oras:byte.20] of word. {D-matricea distantelor dintre orase} c. k. function oras_dist_min(i:byte):byte. end.. oras_dist_min:=jmin. D[i. 5.j. Problema comis –voiajorului: program comisv. var j. var i. dmin. for j:=1 to n do if neales[j] and (D[i. vf_ant[j]:=i end end end.1. dd:word. neales:array[1. 102 .jmin:byte.D[j.{det euristic ciclul minim care pleaca din k} begin for i:=1 to n do neales[i]:=true. dist:=0.dist:natural.’si ’. var D:array[1..min:word.20. procedure citire. function dist_ciclu(k:byte):natural. scriere end.

. s.readln end. const nmax=15. inf=maxint div 2. writeln(’si trece prin orasele :’). if dist< dmin then begin cmin:=c.nmax] of integer.i:integer.m.dmin). lungimea celui mai scurt drum precum si unul dintre drumurile minime de la x0 la xi program dijkstra. GRAFURI ORIENTATE 1. dmin:=maxlongint.nmax] of integer. end. 103 . write(’traseul minim are lungimea= ’.i.xp:integer.y.prec:array[1.nmax.oras] end.d.arc.n. 4.j. for k:=1 to n do begin dist:=dist_ciclu(k). for k:=1 to n do write(cmin[k]:3). end. dmin:=dist end.oras:=oras_dist_min(oras_prec).x.1.. Algoritmul lui Dijkstra: Sa se determine pentru toate vârfurile xi ale unui graf orientat pentru care exista drum de la x0 la xi . dist:=dist+D[oras_prec.k]. var c:array[1.. g:boolean. k. begin citire.neales[oras]:=false. dist_ciclu:=dist.z. procedure min( var k: integer). dist:=dist+D[oras. var m. writeln(cmin[1]:3). c[i]:=oras.

i]< inf then prec[i]:=xp else prec[i]:=0.i). c[x. for i:=1 to n do for j:=1 to n do c[i.readln(arc). k:=i end end.y]:=z. if (d[k]=inf) or (x=n) then g:=false else begin s[k]:=1. write(i).i.begin m:=inf*2. writeln. procedure drum(i:integer). end else writeln end. until (not g).i].j].z).i]:=0. repeat min(k). if c[xp. s[i]:=0. end.j]:=inf.’ si lungimea: ’). begin writeln(’dati nr de noduri:’).j]) then begin d[j]:=d[k]+c[k. for i:=1 to n do begin d[i]:=c[xp. end. ’la’. end. readln(x. for j:=1 to n do if(s[j]=0) and(d[j]>d[k]+c[k.readln(n). prec[j]:=k. s[xp]:=1. writeln( ’dati nr de arce: ’). read(xp). g:=true. x:=0. prec[xp]:=0. end else begin 104 . for i:=1 to n do c[i.y. begin if i<>0 then begin drum(prec[i]). for i:=1 to n do if (s[i]=0) and (d[i]<m) then begin m:=d[i]. xp. x:=x+1. end. for i:=1 to n do if i<>xp then if d[i]=inf then begin write(’nu exista drum de la ’. for i:=1 to arc do begin write(’dati arcul ’.

Algoritmul lui Roy-Floyd . procedure initd. inf=maxint div 2.. 2.1.nmax.j] then begin lg:=lg+1.j. {initializeaza matricea D} var i.c[x.z:word.readln(n).. 105 .’ la ’.m. end.i).j]:=[i] else d[i. type multime=set of 1.x. procedure drum(i. readln(x. writeln end end. c[i.y. {c-initial matricea drumurilor} d:array[1.y.i.j: integer.i. {initializeaza matricea costurilor C} var i. for i:=1 to m do begin write(’extremitatile si lungimea arcului ’. dr:array[1.j]:=inf..nmax] of multime..determinarea tuturor drumurilor minime între oricare doua vârfuri ale unui graf : program roymin.1.j:integer).k.y]:=z. write(’ dati nr de arce: ’)..readln(m). begin if i<>j then begin for k:=1 to n do if k in d[i. begin for i:=1 to n do for j:=1 to n do if (c[i.j]:=[].nmax.z). n.j]<inf)and (i<>j) then d[i. begin write(’dati nr de noduri :’).nmax] of word. drum(i).. procedure initc.i]:=0 end.writeln(’drum minim de la’. for i:=1 to n do begin for j:=1 to n do c[i.nmax] of 1.’:’). var c:array[1.lg:word. const nmax=20.nmax.xp.j.. {genereaza in vectorul dr un drum minim de la i la j pornind din nodul j} var k:word.nmax. end end.

if i<>j then begin lg:=1.k]+c[k.’este’.j]:=d[i. initd. afisare.j]=c[i. procedure afisare. end else if c[i.j]=inf then writeln(’nu exista drum intre’. {afisarea rezultatelor} begin for i:=1 to n do for j:=1 to n do begin writeln.j) end end end end. begin initc.j] then begin c[i. var i.j.k]+c[k. for k:=1 to n do for i:=1 to n do for j:=1 to n do if c[i.j].j].j:word.j]:=d[k.i.’la’. 106 .j]>c[i.j) else begin writeln(’lungimea drumurilor minime de la ’.j].k). lg:=lg-1 end. dr[1]:=j.k]+c[k.j] then d[i. end else begin writeln.’si’. drum(i. end.i.dr[lg]:=k.j]:=c[i.c[i. if c[i.j]).j]+d[k. for k:=lg downto 1 do write(dr[k]:4) end end. d[i. drum(i.

j.i]:=0 end.j] then begin lg:=lg+1. c[i. write(’ dati nr de arce: ’). end else begin writeln.nmax] of 1.nmax.3.’:’).y.i.k). dr[lg]:=k.i. Determinarea tuturor drumurilor maxime între oricare doua noduri ale unui graf orientat: program roymax.. procedure initd.j]:=inf. begin if i<>j then begin for k:=1 to n do if k in d[i.m.j. readln(x.c[x. for i:=1 to m do begin write(’extremitatile si lungimea arcului ’. dr:array[1.y]:=z. drum(i.1. end. lg:=lg-1 end.nmax] of multime.k. begin for i:=1 to n do for j:=1 to n do if (c[i. {genereaza in vectorul dr un drum minim de la i la j pornind din nodul j} var k:word.j]:=[i] else d[i.y.. inf=maxint div 2.j: integer.z:word..nmax] of word..nmax. const nmax=20.j:integer).readln(m).j]>inf)and (i<>j) then d[i.x. type multime=set of 1.z). for k:=lg downto 1 do 107 . procedure initc.nmax.j]:=[]. var c:array[1. n. begin write(’dati nr de noduri :’). {c-initial matricea drumurilor} d:array[1. end end...readln(n).. {initializeaza matricea costurilor C} var i.1. {initializeaza matricea D} var i. procedure drum(i.lg:word.nmax. for i:=1 to n do begin for j:=1 to n do c[i.

’la’. if i<>j then begin lg:=1.j.j]:=d[k.1.j]:=d[i. de activitati:’).j]=c[i.j:word. 108 . if c[i. 4.nmax.j:word. for k:=1 to n do for i:=1 to n do for j:=1 to n do if(c[i.j] then d[i. d[i. end.i.j]..tb:array[1. {in t se retin datele asteptate iar in tb datele limita de realizare a evenimentelor} n. procedure citire. end else if c[i. var i.write(dr[k]:4) end end.k]+c[k.j]:=c[i.j]).c:real._Metoda drumului critic într-un graf de activitati: program drcritic. afisare.j] then begin c[i.j]=inf then writeln(’nu exista drum intre’.i. t. initd.k]+c[k. const nmax=20.y:word. {afisarea rezultatelor} begin for i:=1 to n do for j:=1 to n do begin writeln.. drum(i.’este’.j]+d[k.’si’.i..j]<>inf)then if c[i.j) end end end end.j]. begin initc.k]+c[k.c[i. var l:array[1.nmax] of real.x.nmax] of real.j]<c[i.j]. begin writeln(’dati nr. {citeste arcele si duratele asociate acestora} var i.j) else begin writeln(’lungimea drumurilor minime de la ’.k]<>inf) and (c[k. procedure afisare. inf=maxint. dr[1]:=j.m.

j]>=0 then begin if tb[j]<0 then calctb(j).readln(n). procedure calctb(i:word). for i:=1 to n do begin t[i]:=-1.j]:=-1 end. tb[i]:=-1.j]) then writeln(’activitatea reprezentata de arcul :(’.i). begin writeln(’dati nr de evenimente ale lucrarii:’). t[i]:=max end end. {calculeaza recursiv elementul t[i]} var max: real. tb[i]:=min end end.j:word.j:word. end.i]+t[j] end. begin if i<2 then t[1]:=0 else begin max:=0. for i:=1 to m do begin writeln(’dati arcul asociat activitatii nr. end.’. procedure calct(i:word).i]>=0 then begin if t[j]<0 then calct(j). l[x.y]:=c end. writeln(’EVENIMENTELE CRITICE SUNT:’). calct(n). for i:=1 to n do for j:=1 to n do if (t[i]=tb[i])and(t[j]=tb[j])and(t[j]=t[j]+l[i. for j:=1 to n do if l[i.i.’)’). for i:=1 to n do if t[i]=tb[i] then writeln(’evenimentul ’. for j:=1 to n do if l[j.y. 109 . if max<l[j.j] then min:=tb[j]-l[i. calctb(1).i. for j:=1 to n do l[i. begin if i=n then tb[i]:=t[i] else begin min:=inf.’.{calculeaza recursiv elementul tb[i]} var min:real. end.c).j]. readln(x. writeln(’ACTIVITATILE CRITICE SUNT:’). if min>tb[j]-l[i.j.i]+t[j] then max:=l[j.readln(m).’ si durata acesteia:’).’.citire.

dr:arbore end.gd. Desenarea arborilor binari cu un numar fixat de vârfuri: program arb_bin. c:char. begin if a<>nil then begin if a^.y:integer).y+30).x-30. type arbore=^varf.i.n:integer.x-30.n2) then earb:=true else for i:=n1+3 to n2-3 do if (s[n1]=1) and earb(n1+1. function constr(n1.dr.20] of integer. begin if (n2=n1+2) and (s[n1]=1) and (s[n1+1]=2) and(s[n2]=2) 110 . var k.y+30). var i:integer. a:arbore.x+30. exit end end. if a^.y..dr<>nil then begin line(x.n2:integer):arbore.st<>nil then begin line(x.n2:integer):boolean. procedure afisare(a:arbore. varf=record st.n2-1) then earb:=true else if(s[n1]=1) and (s[n1+1]=2) and earb(n1+2.x. a:arbore. uses crt. var i:integer.graph. if(n2=n1+2) and (s[n1]=1) and (s[n1+1]=2) and (s[n2]=2) then earb:=true else if (n2>n1+2) then if (s[n1]=1) and (s[n2]=2) and earb(n1+1. function earb(n1.y+30) end end end. s:array[ 0.gm.x+30. afisare(a^.st.y+30) end.n2) then begin earb:=true.y.5. begin earb:=false. afisare(a^.i) and earb(i+1.

n2) then begin new(a). detectgraph(gd.exit end end. dec(k) end 111 .n2) then begin new(a).n2-1) then begin new(a).dr:=constr(n1+2. a^. for i:=0 to 2*n do s[i]:=0.then begin new(a). afisare(a. cleardevice.constr:=a end else if (n2>n1+2) then if (s[n1]=1) and (s[n2]=2) and earb(n1+1. a^. while k>=0 do if k=2*n then begin if earb(1.gm). constr:=a end else for i:=n1+3 to n2-3 do if (s[n1]=1) and earb(n1+1.gm. a^. c:=readkey. begin clrscr. a^.’c:\bp\bgi’). stergere(a) end.st=nil) and (a^. a^.readln(n). procedure stergere(var a:arbore).a^.n2).2*n+1).a^. initgraph(gd. begin if a<>nil then if (a^.dr:=nil.n2).k:=0.0). constr:=a end else if (s[n1]=1) and (s[n1+1]=2) and earb(n1+2.n2-1). constr:=a.300.i).st:=nil.i) and earb(i+1.a:=nil end else begin stergere(a^.dr:=constr(i+1.st:=constr(n1+1.st:=nil.st:=constr(n1+1.dr). a^. stergere(a^.dr:=nil.2*n+1) then begin a:=constr(1.st). stergere(a) end end.dr=nil) then begin dispose(a). repeat until keypressed. s[2*n+1]:=2. writeln(’numarul de varfuri :’).

readln end. BIBLIOGRAFIE 1. Doina Rancea Limbajul Pascal. inc(k) end else begin s[k+1]:=0.Mona Pruna 112 .else if s[k+1]<2 then begin inc(s[k+1]).Algoritmi fundamentali Computer Libris Agora 1999 2. Cornelia Ivasc . dec(k) end. closegraph.

Bucuresti 1995 3.Bazele informaticii. Tudor Sorin Tehnici de programare-1996 113 . Ion Vaduva Bazele Informaticii Editura Tehnica-Bucuresti. Irina Athanasiu. Bucuresti. Nicolae Mitroi Elemente de grafuri si combinatorica. Tratat de programarea calculatoarelor. Ghe. algoritmi si programe Editura ALL Bucuresti. Valentin Cristea. Metode.Bucuresti-1974 6. Barbu. Ioan Tomescu Data Structures Editura Univ. Eugenia Kalisz.Grafuri si Elemente de Combinatorica Editura Petrion .1997 8. Gheorghe Marian.1994 4.Bucuresti-1997 5.E. Valeriu Iorga Tehnici de programare Editura Teora. Octavian Patrascoiu.1997 7. Algoritmi fundamentali Editura Tehnica. Knut D.

Sign up to vote on this title
UsefulNot useful