11/57/57
10.10. TipulTipul referinreferinţţăă
CC1010 / 7.12.2012/ 7.12.2012
TipulTipul referinreferinţţăă ~ pointeripointeri..
StructuriStructuri de date de date dinamicedinamice
ListeListe îînlănnlănţţuiteuite ..
ArboriArbori binaribinari
22/57/57
10.1.10.1. TipulTipul referinreferinţţăă
Limbajul Pascal oferă posibilitatea de a lucra cu variabile:a) staticestatice
- Caracteristicile sunt bine definite, cunoscute şi fixe.- Nu se pot modifica în timpul execuţiei structura, tipul şi adresa de memorie.- Sunt referite prin numele lor o adresă de memorie. - Li se poate modifica doar valoarea, nu şi adresa.
b) dinamicedinamice- Au un tip bine precizat încă din faza de compilare însă ele pot fi alocate
dinamic (pot lua fiinţă în faza de execuţie a programului), pot fi utilizate (referite) prin adresa lor din memoria internă şi pot fi distruse (dealocate) dacă nu mai sunt utile.
- Pot fi referite printr-o variabilă de referinvariabilă de referinţţăă ce conţine adresa variabilei dinamice. Variabila de referinţă poate face referiri numai la variabile dinamice de acelaşi tip declarat, bine definit şi fix. Această legatură (corespondenţă) între variabila dinamică şi tipul de date referinţă permite cunoaşterea structurii variabilei dinamice.
-- Variabilele de tip referinVariabilele de tip referinţţăă vor conţine adreseadrese de memorie ale variabilelor dinamice referite. Datorită acestui fapt, declararea tipului referinţă poate fi făcută îînainteanaintea definirii tipului variabilei dinamice referite.
33/57/57
TipulTipul referinreferinţţăă
Definirea unui tip referinţă şi a variabilelor de tip referinţă se face astfel:TypeType Tip_ReferinTip_Referinţţă ă = = ^ ^ Tip_Var_DinamiTip_Var_Dinamicăcă;;
Tip_Var_DinamiTip_Var_Dinamicăcă = ...= ... { { poatepoate referireferi Tip_ReferinTip_Referinţţăă }}VarVar Var_Ref1,Var_Ref2,... : Tip_ReferinVar_Ref1,Var_Ref2,... : Tip_Referinţţăă;; {Vor con{Vor conţţine adrese}ine adrese}
Alocarea dinamicăAlocarea dinamică pentru variabila dinamică se realizează cu procedura:
New (Var_Ref)New (Var_Ref)care caută în memoria internă o zonă liberă pentru variabila dinamică şi furnizează adresa acestei zone în variabila de tip referinţă (Var_Ref). Această zonă este alocată variabilei dinamice, fără a fi iniţializată. Dimensiunea zonei alocate variabilei dinamice este determinată de tipul variabilei dinamice:Type Adresa=^Numar;Type Adresa=^Numar;
Numar = RecordNumar = RecordNumar_Cifre : Byte;Numar_Cifre : Byte;Sir_CifreSir_Cifre : Array [: Array [1..1001..100] of Byte] of Byte
End;End;Var n : AVar n : Adresa;dresa;BeginBegin New New (n);(n); { S{ Se alocă e alocă 101 101 octeti }octeti }
... ... {Prelucrare (n^) }{Prelucrare (n^) }End.End.
44/57/57
TipulTipul referinreferinţţăă
Referirea unei variabile dinamice se face printr-o variabilă de tip referinţă (legată de variabila dinamică). Numele variabilei referinţă urmat de caracterul ''^'^' reprezintă numele variabilei dinamice.
Eliberarea zonei de memorie ocupată de o variabila dinamică se va executa cu instrucţiunea (apelul de procedură) :
Dispose (Var_Ref) Dispose (Var_Ref)
care disponibilizează zona de la adresa conţinută în variabila Var_Ref. Dacă o variabilă referinţă nu referă nici o variabilă dinamică, atunci valoarea variabilei referinţă este NilNil .
Variabilele referinţă se pot utiliza în instrucţiuni de atribuire prin care o astfel de variabilă primeşte valoarea altei variabile de acelaşi tip sau constanta NilNil şi, de asemenea, în expresii relaţionale cu operaţorii "==" sau "<><>".
Subliniem că orice referire a variabilei dinamice P^̂ trebuie să se facă între apelurile
New (P)New (P) şi Dispose (P).Dispose (P).
55/57/57
TipulTipul referinreferinţţăă
În următorul program se adună două numere raţionale citite de la tastatură.Program Rationale; {Programul Tipul referinţă}
Type Q = ^Rational;
Rational = RecordNumarator ,Numitor : Integer
End;
Var a,b,c : Q ;Function Cmmdc (m,n:Integer) : Integer; {Gaseste c.m.m.d.c.}Var Rest:Integer; {al numerelor m şi n}Begin
While n<>0 Do BeginRest := m Mod n;m := n; n := Rest
End {while};Cmmdc := m
End; {Cmmdc}
66/57/57
TipulTipul referinreferinţţăă
Function Cmmmc (m,n:Integer) : Integer; {Calculeaza c.m.m.m.c.}Begin {al numerelor m şi n nenule}
If m*n = 0 Then Writeln('nr.nul') ElseCmmmc := m * n Div Cmmdc (m,n)
End; {Cmmmc}
Procedure Simplific (Var p:Q); {Simplifica nr.rational p }Var Divizor_comun: Integer;Begin
With p^ do BeginDivizor_comun:=Cmmdc(Numarator,Numitor);If Divizor_comun > 1 Then Begin
Numarator := Numarator Div Divizor_comun;Numitor := Numitor Div Divizor_comun End {If}
End {With}End; {Simplific}
Procedure Citeste (Var p:Q); {Citeste nr.rational in p}Begin
Write (' Numarator,numitor = '); Readln (p^.Numarator, p^.Numitor);Simplific (p)
End; {Citeste}
77/57/57
TipulTipul referinreferinţţăă
Procedure Aduna (a,b:Q; Var c:Q);Var N_comun: Integer; { Numitorul comun }Begin
N_comun := Cmmmc(a^.Numitor,b^.Numitor);c^.Numarator := a^.Numarator * (N_comun Div a^.Numitor) +
b^.Numarator * (N_comun Div b^.Numitor);c^.Numitor :=N_comun;Simplific (c)
End; {Aduna}
Procedure Tipareste (p:Q); {Tipareste nr.rational p}Begin With p^ do Write (Numarator,'/',Numitor)End;
Begin {Programul principal}New (a); Citeste (a); New (b); Citeste (b);New (c); Aduna (a,b,c);Tipareste(a); Write(' + '); Tipareste(b); Write(' = '); Tipareste (c);Dispose (a); Dispose (b); Dispose (c); Readln;
End.
88/57/57
TipulTipul referinreferinţţăă
Vom rezolva în continuare aceeaşi problemă în altă manieră, utilizând funcţiaAduna pentru suma a două numere raţionale care va da ca rezultat adresa număruluiraţional calculat:Program Rationale; {Programul 2. Tipul referinţă}Type QQ = ^̂Rational;
Rational = Record Numarator, Numitor : Integer End;Var a, b : Q ;
Function Cmmdc (m,n:Integer) : Integer; {Gaseste c.m.m.d.c.}Var Rest:Integer; {al numerelor m şi n}Begin
While n<>0 do Begin Rest := m Mod n; m := n; n := Rest End {while};Cmmdc := m
End;
Function Cmmmc (m,n:Integer): Integer; {Calculeaza c.m.m.m.c.}Begin {al numerelor m şi n nenule}
If m*n = 0 Then Writeln('nr.nul') Else Cmmmc := m * n Div Cmmdc (m,n)End;
99/57/57
TipulTipul referinreferinţţăă
Procedure Simplific (Var p:Q); { Simplifica nr.rational p }Var Divizor_comun: Integer;Begin
With p^ Do BeginDivizor_comun:=Cmmdc(Numarator,Numitor);If Divizor_comun > 1 Then Begin
Numarator := Numarator Div Divizor_comun;Numitor := Numitor Div Divizor_comun End {If}
End {With}End;
Procedure Citeste (Var p:Q); {Citeste nr.rational in p}Begin
With p^ do BeginWrite(' Numarator numitor = '); Readln (Numarator, Numitor);If Numitor=0 Then
RepeatWrite (' Numitor = 0! dati altul'); Readln (Numitor);
Until Numitor <> 0;End; {With}Simplific (p)
End;
1010/57/57
TipulTipul referinreferinţţăă
Function Function AdunaAduna ((a,b:Qa,b:Q) : Q;) : Q;Var Numit_comun: Integer; s:Q;Begin
New (s);Numit_comun := Cmmmc(a^.Numitor,b^.Numitor);s^.Numarator:= a^.Numarator * (Numit_comun Div a^.Numitor)+
b^.Numarator * (Numit_comun Div b^.Numitor);s^.Numitor :=Numit_comun;Simplific (s);Aduna:=s; Dispose(s)Dispose(s)
End;Procedure Tipareste (p:Q); {Tipareste nr.rational p}Begin
With p^̂ Do Write (Numarator,'/',Numitor)End;Begin
New (a); Citeste (a); New (b); Citeste (b);Tipareste(a); Write('+'); Tipareste(b); Write('='); TiparesteTipareste(Aduna(a,b));Dispose(a); Dispose(b);Readln;
End.
1111/57/57
TipulTipul referinreferinţţăă
În limbajul Pascal se pot utiliza variabile nelegate de un anumit tip de bază (tipulvariabilei dinamice) în scopul memorării valorilor unor variabile de tip referinţă(memorare de adrese). Acest tip referinţă nelegat, este tipul Pointer.
Operaţiile ce se pot efectua cu astfel de variabile sunt de tip atribuire astfel:
Var AdrP : PointerPointer;Adr1 : Tip_Referinţă1;Adr2 : Tip_Referinţă2;
Begin ...AdrP:=Adr1; ... AdrP^ ...... AdrP^ ... doar ... Tip_Referinţă1(AdrP)^̂ ...Adr2:=AdrP; ... Adr2^ ... sau ... Tip_Referinţă2(AdrP)^̂ ......
End.
În exemplul anterior funcţia Aduna putea avea următorul antet:
Function Aduna (a,b:Q) : PointerPointer;
fără a fi necesare alte modificări în program.
1212/57/57
TipulTipul referinreferinţţăă
În următorul exemplu ne propunem să tipărim în hexazecimal conţinutul zonei de
memorie pe care se reprezintă un număr real.
Program Numar_Real; {Prgramul Pointeri}Const Lung = 6;Type Sir_Octeti = Array[1..Lung] of Byte;Var Pointer_Real : ^̂Real;
Pointer_Byte : ^̂Sir_Octeti;Pointer_Manevra : Pointer;i : Integer;
Function Hexa (Cifra:Byte) : Char; {Tipareste o cifra}Begin {hexazecimala}
If Cifra < 10 Then Hexa := Chr(Cifra+Ord('0'))Else Hexa := Chr(Cifra+Ord('A')-10)
End;
1313/57/57
TipulTipul referinreferinţţăă
Procedure Print (Octet: Byte); {Tipareste continutul unui}
Begin {octet in hexazecimal}Write (Hexa(Octet Div 16));Write (Hexa(Octet Mod 16),' ')
End;
Begin {Programul principal}
New ( Pointer_Real);Write (' Dati un numar real : ');Readln ( Pointer_Real^ ^ );Pointer_Manevra := Pointer_Real;Pointer_Byte := Pointer_Manevra;For i:=1 to Lung do Print (Pointer_Byte^̂[i]);Dispose (Pointer_Real);Readln;
End.
1414/57/57
10.2.10.2. StructuriStructuri de date de date DinamiceDinamice
StructuriStructuri de date de date :a) Multime 0 - 0b)b) ListeListe 1 1 -- 11c)c) ArboriArbori 1 1 -- n (2 n (2 --binaribinari))d) Grafe n - n
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
ListeListe :a) Static Vectorib)b) DinamicDinamic Refer. (Refer. (StiveStive ((LiFoLiFo), ), CoziCozi ((FiFoFiFo) (c), ) (c), ……))
1515/57/57
ListeleListele pot pot fifi reprezentatereprezentate ((referitereferite) ) prinprin::
a) (Cap) (Cap,Coada la liste duble)
b) (Cap, Cursor) (Cap,cCap, Coada,cCoada) la liste duble)
iteratoriterator : Init(L), Next(L), Ultim(L), Pred(L), …
10.2.1.10.2.1.aa ListeListe îînlănnlănţţuiteuite DinamicDinamic
ListeleListele îînlănnlănţţuiteuite DinamicDinamic pot fi:
• Simple (de Puncte),• Duble (de Monoame)• Liste (de poligoane, de polinoame,…)
1616/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Prin listă se înţelege o colecţie de elemente de acelaşi tipx1, x2, ... , xn,
în care x1 este primul element, xn este ultimul element şi pentru 1 < k < n elementulxk are un unic succesor (pe xk+1) şi un unic predecesor (pe xk-1).
Asupra listelor liniare putem defini operaţii care să ne permită adăugarea unuielement în lista, extragerea unui element (cu stergerea lui) din lista, cautarea unuielement cu o anumita proprietate şi crearea unei liste vide.
Se poate stabili o corespondenţă biunivocă între elementele listei liniare şisubmulţimea numerelor naturale {1, 2, ..., n} astfel: primului element îi ataşăm 1, următorului 2 şi aşa mai departe, iar ultimului n. Numărul natural asociat unuielement din listă se numeşte poziţia elementului respectiv. Vom spune căelementul de pe poziţia i precede elementul de pe poziţia j dacă i < j .
Rezultă că pe o astfel de structură de date putem defini următoarele funcţii: Următorul, Precedentul şi Poziţia unui element, aşa cum se va vedea mai jos.
1717/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
SpecificareaSpecificarea acestor operaţii se dă în continuare:• OperaOperaţţiaia CREARE(L)CREARE(L) este:
L := lista vidă (fără nici un element);• OperaOperaţţiaia ADĂUGARE ADĂUGARE ((L,aL,a)) este: {în coada listei}
Dacă L la intrare conţine elementele :x1, x2, ... , xn,
după efectuarea operaţiei, lista L va conţine elementele :x1, x2, ... , xn, xn+1, unde xn+1 = a .
• OperaOperaţţiaia CĂUTARE CĂUTARE ((L,a,pL,a,p) este:Dacă L conţine elementele :
x1, x2, ... , xn, după efectuarea operaţiei, p primeşte o valoare între 1 şi n astfel ca xp = a, sau
valoarea n+1 în caz contrar.• OperaOperaţţiaia EXTRAGERE (EXTRAGERE (L,p,aL,p,a)) este:
Daca L conţine la intrare elementele :x1, x2, ... , xn,
după efectuarea operaţiei a primeşte valoarea xp iar lista va avea elementele :x1, x2, ... , xp-1, xp+1, ..., xn,
deci elementul xp a fost eliminat din listă.
1818/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Implementarea acestor operaţii depinde de reprezentarea listei în memoria calculatorului.
Reprezentarea unei liste liniare poate fi staticăstatică sau dinamicădinamică.Reprezentarea staticăReprezentarea statică a unei liste se realizează printr-un vector X cu
componentelex1, x2, ... , xn .
Reprezentarea este statică întrucât alocarea memoriei necesare vectorului X este făcută în timpul compilării. Deci locul în memorie al elementelor listei nu se schimbă pe timpul executiei. Elementele listei se vor afla în memorie în locaţii consecutive cu o lungime maximă (declarată) care nu poate fi depăşită şi nici schimbată în timpul executiei.
Reprezentarea dinamicăReprezentarea dinamică se realizează cu ajutorul tipului PointerPointer, alocarea memoriei făcându-se în timpul execuţiei.
Se va utiliza o structură mult mai flexibilă în care fiecare nod este legat de nodul următor al listei. Această structură o vom numi listă listă îînlannlanţţuităuită şi implementarea ei se poate realiza prin alocare dinamică a memoriei. Zona de memorie ocupată de o astfel de listă creşte sau scade după cum lista conţine mai multe sau mai puţine elemente, prin operaţii de adăugare, respectiv de ştergere.
1919/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
O listă înlănţuită o vom reprezenta grafic astfel :
Informaţie Leg Informaţie Leg Informaţie Leg Informaţie LegPrimul Ultimul
Nil
Un element din listă va conţine pe lângă informaţia propriu-zisă şi adresa (referinţa) următorului element din listă (marcată în figura de mai sus prin săgeţi). În acest fel având adresa primului element, vom putea accesa (regăsi) orice element din lista înlănţuită prin parcurgarea secvenţială a acesteia.
Ultimul element va conţine o informaţie (cod) de "santinelă" care va marca sfârşitul listei. Acest cod poate avea valoarea Nil ceea ce înseamnă că acest element nu mai este legat de un altul (nu există următorul element).
O astfel de listă, care conţine în fiecare element adresa următorului element poate fi parcursă doar secvenţial începând de la primul element până la ultimul, într-un singur sens. Această structură o vom numi listă simplu înlănţuită .
2020/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Variabilele de tip referinţă dintr-un program Pascal care utilizează o listă simplu
înlănţuită se pot declara astfel :
Type Type Tip_InfoTip_Info = ... ;= ... ;
AdrAdr = ^= ^Tip_ElemTip_Elem;;Tip_ElemTip_Elem = Record= Record
InformatieInformatie : : Tip_InfoTip_Info;;Leg : AdrLeg : Adr
End;End;
Var Primul, Element, Ultimul, Nou : Adr;Var Primul, Element, Ultimul, Nou : Adr;
O listă simplu înlănţuită, în functie de disciplina de generare a ei (prin adăugare element cu element) poate fi: lista înlănţuită înainte, lista înlănţuită înapoi şi listă înlănţuită ordonată.
2121/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Lista înlănţuită înainte este lista în care adăugarea se face în coada listei, aşa cum se poate vedea în figura următoare:
Ultimul
UltimulPrimul Nou
Informaţie Leg Informaţie Leg Informaţie Leg Informaţie Leg
NilNil
Operaţia scrisă în Pascal este următoarea :
Procedure Adaug_in_coada (Nou:Adr; Var Primul,Ultimul:Adr);Procedure Adaug_in_coada (Nou:Adr; Var Primul,Ultimul:Adr);BeginBegin Nou^.Leg:=Nil;Nou^.Leg:=Nil; If Primul If Primul=Nil =Nil Then Primul Then Primul := No:= Nouu { P{ Prima adăugare rima adăugare }}
Else Ultimul^.Leg := Nou;Else Ultimul^.Leg := Nou;Ultimul:=NouUltimul:=Nou
End;End;
2222/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Lista înlănţuită înapoi este lista în care adăugarea se face în capul listei, aşa cum se poate vedea în figura de mai jos :
Operaţia scrisă în Pascal este următoarea :
Procedure Adaug_in_cap (Nou:Adr; Var Primul:Adr);Procedure Adaug_in_cap (Nou:Adr; Var Primul:Adr);
BeginBegin
Nou^.Leg := Primul;Nou^.Leg := Primul;
Primul := NouPrimul := Nou
End;End;
Informaţie Leg Informaţie Leg Informaţie Leg Informaţie Leg
Nil
Primul
Nou Primul
2323/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Lista înlănţuită ordonată este lista în care adăugarea se face astfel încât elementele listei să fie într-o anumită ordine (crescător sau descrescător după o anumită cheie) aşa cum se poate vedea în următoarea figură :
Dacă ORDINE este o funcţie booleană care precizează ordinea dorită, atunci procedura Pascal corespunzătoare este :
Procedure Adaug_ord (Nou:Adr; Var Primul:Adr);Procedure Adaug_ord (Nou:Adr; Var Primul:Adr);Var Var Elem, Prec : Adr;Elem, Prec : Adr;Begin Elem:=Primul;Begin Elem:=Primul;
While (Elem<>Nil) and not While (Elem<>Nil) and not ORDINE(ElemORDINE(Elem, , NouNou) do Begin) do Begin { { CautaCauta locullocul }}Prec := Elem; Elem := Elem^.LegPrec := Elem; Elem := Elem^.Leg End;End; { de inserare }{ de inserare }
Nou^.Leg := Elem;Nou^.Leg := Elem; If Elem If Elem=Primul=Primul Then Primul Then Primul:= No:= Nouu { A{ Adăugare dăugare îînaintea primului element }naintea primului element }
Else Prec^.Leg := Nou;Else Prec^.Leg := Nou;End;End;
Nil
Primul Prec Elem
Informaţie LegNou
Informaţie Leg Informaţie Leg Informaţie Leg Informaţie Leg
2424/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
În exemplul următor vom genera o listă prin adăugarea elementelor în coada listei, în capătul listei sau în aşa fel încât lista sa fie ordonată după un câmp numit cheie. Disciplina de adăugare va fi aleasă de către utilizator.
Program Liste_simplu_inlantuite;Program Liste_simplu_inlantuite; {Programul Liste}{Programul Liste}Type Type
Tip_Cheie = Integer;Tip_Cheie = Integer;Tip_Date = String[20];Tip_Date = String[20];
Tip_InfoTip_Info = Record= RecordCheieCheie : : Tip_CheieTip_Cheie;;Date : Date : Tip_DateTip_DateEnd;End;
Adr = ^Tip_Elem;Adr = ^Tip_Elem;Tip_Elem = RecordTip_Elem = Record
Inf : Tip_Info;Inf : Tip_Info;Leg : AdrLeg : AdrEnd;End;
Var Lista : Adr;Var Lista : Adr; { Adresa primului element }{ Adresa primului element }Disc : Char;Disc : Char; { Tipul adaugarii }{ Tipul adaugarii }
2525/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Procedure Procedure CitescCitesc ((VarVar Element:AdrElement:Adr););BeginBegin
New (Element);New (Element);Write (' ................... Write (' ................... CheieCheie, Date : ');, Date : ');With Element^, With Element^, InfInf do do ReadlnReadln ((Cheie,DateCheie,Date))
End;End;Procedure Procedure GenerareGenerare (Var Primul:Adr; Disc:Char);(Var Primul:Adr; Disc:Char);Var Nou,Ult : Adr; Rasp : Char;Var Nou,Ult : Adr; Rasp : Char;
Procedure Procedure Adaug_in_coadaAdaug_in_coada;;BeginBegin
Nou^.LegNou^.Leg:=Nil;:=Nil;If If PrimulPrimul=Nil Then =Nil Then PrimulPrimul := := NouNou Else Else Ult^.LegUlt^.Leg := := NouNou;;UltUlt:=:=NouNou
End;End;Procedure Procedure Adaug_in_capatAdaug_in_capat;;BeginBegin
Nou^.LegNou^.Leg := := PrimulPrimul;;PrimulPrimul := := NouNou
End;End;
2626/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Procedure Procedure Inserare_ordInserare_ord; ; VarVar Elem, Elem, PrecPrec : : AdrAdr;;BeginBegin Elem:=Elem:=PrimulPrimul;;While (Elem<>Nil) and (While (Elem<>Nil) and (Elem^.Inf.CheieElem^.Inf.Cheie < < Nou^.Inf.CheieNou^.Inf.Cheie) do Begin ) do Begin
Prec := Elem; Elem := Elem^.LegPrec := Elem; Elem := Elem^.Leg End;{While}End;{While}Nou^.LegNou^.Leg := Elem;:= Elem;If Elem=If Elem=PrimulPrimul Then Then PrimulPrimul := := NouNou
Else Prec^.Leg := Nou;Else Prec^.Leg := Nou;End;End;
BeginBegin {{GenerareGenerare}}PrimulPrimul:=Nil;:=Nil;RepeatRepeat
RepeatRepeatWrite ('Adaugati(D,N):'); Readln(Rasp); Rasp:=Upcase(Rasp);Write ('Adaugati(D,N):'); Readln(Rasp); Rasp:=Upcase(Rasp);
Until Rasp in ['D','N'];Until Rasp in ['D','N'];If Rasp = 'D' ThenIf Rasp = 'D' Then BeginBegin
CitescCitesc ((NouNou););Case Disc ofCase Disc of 'F' : 'F' : Adaug_in_coadaAdaug_in_coada;;
'L' : Adaug_in_capat;'L' : Adaug_in_capat;'O' : Inserare_ord'O' : Inserare_ord
End {Case}End {Case} End {If}End {If}Until Rasp = 'N'Until Rasp = 'N'
End;End;
2727/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Procedure Procedure ParcurgereParcurgere ((Elem:AdrElem:Adr););BeginBegin
While Elem <> Nil Do With Elem^ Do BeginWhile Elem <> Nil Do With Elem^ Do BeginWith With InfInf Do Do WritelnWriteln (Cheie:5,Date);(Cheie:5,Date);Elem:=LegElem:=Leg End {With}End {With}
End;End;BeginBegin { Main}{ Main} Repeat Repeat Writeln Writeln (' (' Ce disciplina doriti la adăugare Ce disciplina doriti la adăugare ? ');? ');
Writeln (' F = in coada listei (FIFO) ');Writeln (' F = in coada listei (FIFO) ');Writeln (' L = in capul listei (LIFO) ');Writeln (' L = in capul listei (LIFO) ');Writeln (' O = lista ordonata ');Writeln (' O = lista ordonata ');Write (' Write (' OptiuneOptiune : ');: ');ReadlnReadln (Disc); Disc:=(Disc); Disc:=Upcase(DiscUpcase(Disc))
Until Disc in ['F','L','O'];Until Disc in ['F','L','O'];Generare (Lista,Disc);Generare (Lista,Disc); { Creerea listei }{ Creerea listei }For Disc:='A' to 'E' do For Disc:='A' to 'E' do WritelnWriteln;;Writeln('ElementeleWriteln('Elementele listeilistei suntsunt:');:');ParcurgereParcurgere ((ListaLista); ); ReadlnReadln { { ListareaListarea listeilistei }}
End.End.
2828/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Ştergerea unui element din listă se realizează prin modificarea legăturiielementului precedent (dacă acesta există) urmată de dealocarea zonei ocupatede elementul şters astfel
Operaţia de ştergere (scrisă în Pascal) a elementului Elem din lista L esteurmătoarea :
Procedure Procedure Stergere(VarStergere(Var Elem,Prec,LElem,Prec,L: : AdrAdr);); {{PrecPrec==precedentulprecedentul }}BeginBegin { { luilui Elem }Elem }
If L = ElemIf L = Elem { { dacădacă se se stergesterge primulprimul element }element }Then L := Then L := Elem^.LegElem^.LegElse Prec^.Leg := Elem^.Leg; Else Prec^.Leg := Elem^.Leg;
Dispose (Elem);Dispose (Elem);End;End;
Informaţie Leg Informaţie Leg Informaţie Leg Informaţie Leg
Nil
Primul Prec Elem
2929/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
În exemplul următor se poate urmări ştergerea unor elemente precizate prin cheia conţinută în informaţia propriu-zisă a elementelor .
Program Stergere_element_din_lista;Program Stergere_element_din_lista;{Creeaza o lista de elemente (cheie,string),}{Creeaza o lista de elemente (cheie,string),}{apoi sterge elemente {apoi sterge elemente şşi tipareste lista finala }i tipareste lista finala }
Type Tip_Cheie = Integer;Type Tip_Cheie = Integer;Tip_DateTip_Date = String[20];= String[20];Tip_InfoTip_Info = Record= Record
CheieCheie : : Tip_CheieTip_Cheie;;Date : Date : Tip_DateTip_DateEnd;End;
Adr = ^Tip_Elem;Adr = ^Tip_Elem;Tip_Elem = RecordTip_Elem = Record
Inf : Tip_Info; Inf : Tip_Info; Leg : AdrLeg : AdrEnd;End;
Var Lista : Adr;Var Lista : Adr; { Adresa primului element }{ Adresa primului element }
3030/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Procedure Citesc (Var Element:Adr);Procedure Citesc (Var Element:Adr); {Citeste informatia}{Citeste informatia}BeginBegin {din nodul Element}{din nodul Element}
Write (' ............ Write (' ............ CheieCheie, Date : '); , Date : '); With With Element^.InfElement^.Inf do do Readln(Cheie,DateReadln(Cheie,Date))
End;End;Procedure Generare (Var Primul:Adr);Procedure Generare (Var Primul:Adr); {Creaza lista}{Creaza lista}Var Nou : Adr; Rasp : Char;Var Nou : Adr; Rasp : Char;BeginBegin
PrimulPrimul:=Nil;:=Nil;RepeatRepeat
RepeatRepeatWrite (' Write (' AdaugatiAdaugati (D,N) : ');(D,N) : ');Readln (Rasp); Rasp:=Upcase(Rasp);Readln (Rasp); Rasp:=Upcase(Rasp);
Until Rasp in ['D','N'];Until Rasp in ['D','N'];If Rasp = 'D' Then BeginIf Rasp = 'D' Then Begin
New(Nou); Citesc (Nou);New(Nou); Citesc (Nou);Nou^.leg:=Primul; Primul:=NouNou^.leg:=Primul; Primul:=Nou
End {If}End {If}Until Rasp = 'N'Until Rasp = 'N'
End;End;
3131/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Procedure Stergere (Var Primul,Prec:Adr);Procedure Stergere (Var Primul,Prec:Adr); {Sterge succesorul}{Sterge succesorul}Var Elem:adr;Var Elem:adr; { lui Prec din lista Primul}{ lui Prec din lista Primul}BeginBegin
If (If (PrecPrec=Nil)=Nil)ThenThen BeginBegin Elem:=Elem:=PrimulPrimul; ;
Primul := Primul^.Leg Primul := Primul^.Leg EndEnd
ElseElse BeginBegin Elem:=Prec^.Leg; Elem:=Prec^.Leg; Prec^.Leg := Elem^.Leg Prec^.Leg := Elem^.Leg
End;End;Dispose (Elem)Dispose (Elem)
End;End;Procedure Cauta(Primul:adr; Cod: Tip_Cheie; Var Prec:adr);Procedure Cauta(Primul:adr; Cod: Tip_Cheie; Var Prec:adr);Var Elem:Adr;Var Elem:Adr; {Cauta in lista Primul, elementul cu cheia Cod }{Cauta in lista Primul, elementul cu cheia Cod }BeginBegin { { şşi retine in Prec predecesorul acestui element }i retine in Prec predecesorul acestui element }
Elem:=Primul; Prec := Nil;Elem:=Primul; Prec := Nil;While (Elem<>Nil) And (Elem^.Inf.Cheie<>Cod) Do BeginWhile (Elem<>Nil) And (Elem^.Inf.Cheie<>Cod) Do Begin
Prec:=Elem; Elem:=Elem^.LegPrec:=Elem; Elem:=Elem^.Leg End; {While}End; {While}If (Elem=Nil) Then If (Elem=Nil) Then WriteLNWriteLN (' Nu (' Nu existaexista elementulelementul cu cu codulcodul ',Cod)',Cod)
End;End;
3232/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Procedure Procedure StergelementeStergelemente ((VarVar Primul:AdrPrimul:Adr);); {{StergeSterge la la cererecerere}}VarVar Elem,PrecElem,Prec : : AdrAdr;; {{elementeelemente din din listalista PrimulPrimul}}
Cod : Cod : Tip_CheieTip_Cheie; Rasp : Char; ; Rasp : Char; BeginBegin
RepeatRepeatWrite ('Write ('StergSterg element ? element ? (D,N):'); Readln(Rasp); Rasp:=Upcase(Rasp);(D,N):'); Readln(Rasp); Rasp:=Upcase(Rasp);If Rasp='D' Then BeginIf Rasp='D' Then Begin
Write (' Write (' CheiaCheia elementuluielementului : '); : '); Readln(CodReadln(Cod););Cauta(Primul,Cod,Prec); Stergere(Primul,Prec)Cauta(Primul,Cod,Prec); Stergere(Primul,Prec)
End {If}End {If}Until Rasp='N'Until Rasp='N'
End;End;Procedure Parcurgere (Primul:Adr);Procedure Parcurgere (Primul:Adr); {Parcurge lista Primul}{Parcurge lista Primul}Var Elem:adr;Var Elem:adr; {si{si--i tipareste continutul}i tipareste continutul}BeginBeginWhile Elem <> Nil Do Begin With While Elem <> Nil Do Begin With Elem^.infElem^.inf do do WritelnWriteln (Cheie:5,Date);(Cheie:5,Date);
Elem:=Elem^.Leg End {While}Elem:=Elem^.Leg End {While}End;End;BeginBegin {Programul principal }{Programul principal }
Generare (Lista);Generare (Lista); { Creerea listei }{ Creerea listei }Stergelemente(Lista);Stergelemente(Lista); { Stergere elemente }{ Stergere elemente }Parcurgere (Lista);Parcurgere (Lista); ReadlnReadln { Listarea listei }{ Listarea listei }
End.End.
3333/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Lista simplu înlănţuită poate fi traversată doar într-un singur sens începând cu primul până la ultimul element, pentru că un element conţine doar adresa următorului element din listă. Dacă dorim sa traversăm lista şi invers (de la coadă la capăt) atunci va trebui să reţinem în fiecare element şi adresa elementului anterior (precedent) :
O listă care are această proprietate se numeşte lista dublu lista dublu îînlănnlănţţuităuită şi se reprezinta grafic astfel:
Leg.St. Informaţie Leg.Dr.
Primul Ultim
NilNil
LegSt Inf. LegDr.LegSt. Inf. LegDr. LegSt. Inf. LegDr. LegSt. Inf. LegDr.
3434/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Variabilele de tip referinţă dintr-un program Pascal care utilizează o listă dublu înlănţuită se pot declara astfel:
Type Type Tip_CheieTip_Cheie = ...;= ...;Tip_DateTip_Date = ...;= ...;Tip_InfoTip_Info = Record= Record
Cod : Cod : Tip_CheieTip_Cheie;;Info : Tip_DateInfo : Tip_DateEnd;End;
Adr = ^Tip_Elem;Adr = ^Tip_Elem;Tip_ElemTip_Elem = Record= Record
Leg_PrecedLeg_Preced : : AdrAdr;; {{Leg_StLeg_St}}InformatiiInformatii : : Tip_InfoTip_Info;;Leg_UrLeg_Următormător : : AdrAdr {{Leg_DrLeg_Dr}}End;End;
VarVar PrimulPrimul, , UltimUltim, Elem, , Elem, PrecPrec, , NouNou : : AdrAdr;;
3535/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Operaţia de adăugareadăugare într-o listă dublu înlănţuită se poate realiza astfel :
LegLegStSt Inf. LegDr.LegLegStSt. Inf. LegDr. LegLegStSt. Inf. LegDr. LegLegStSt. Inf. LegDr.
NilNilNilNou
LegLegStSt. Inf. LegDr.
Primul UltimUltimPrec Elem
O procedură Pascal care realizează inserarea elementului Nou în faţa elementuluiElem este următoarea:Procedure Procedure Inserare(VarInserare(Var Nou,ElemNou,Elem: : AdrAdr););BeginBegin
((Elem^.leg_st)^.Leg_drElem^.leg_st)^.Leg_dr:=:=NouNou;;NouNou^ .^ .Leg_StLeg_St:=:=Elem^.Leg_StElem^.Leg_St;;Nou^ .Leg_Dr:=Elem;Nou^ .Leg_Dr:=Elem;Elem^.Leg_St:=Nou;Elem^.Leg_St:=Nou;
End;End;
3636/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Operaţia de şştergeretergere a elementului Elem dintr-o listă dublu înlănţuită se poate schiţa astfel:
O procedură Pascal corespunzatoare acestei operaţii este următoarea:
Procedure Stergere(Var Elem : Adr);Procedure Stergere(Var Elem : Adr);BeginBegin
(Elem^.Leg_St)^.Leg_Dr:=Elem^.Leg_Dr;(Elem^.Leg_St)^.Leg_Dr:=Elem^.Leg_Dr;(Elem^.Leg_Dr)^.Leg_St:=Elem^.Leg_St;(Elem^.Leg_Dr)^.Leg_St:=Elem^.Leg_St;Dispose (Elem);Dispose (Elem);
End;End;
LegSt. Inf. LegDr.LegSt. Inf. LegDr. LegSt. Inf. LegDr. LegSt. Inf. LegDr.
NilNil
Primul UltimElem
3737/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
În exemplul următor se poate urmări generarea unei liste dublu înlănţuite urmate de parcurgerea acesteia în ambele sensuri:
Program Liste_dublu_inlantuite;Program Liste_dublu_inlantuite;
Type Type Tip_CheieTip_Cheie = Integer;= Integer;Tip_DateTip_Date = String[20];= String[20];Tip_InfoTip_Info = Record = Record CheieCheie : : Tip_CheieTip_Cheie; Date : ; Date : Tip_DateTip_Date End;End;AdrAdr = ^= ^Tip_ElemTip_Elem;;Tip_ElemTip_Elem = Record= Record
InfInf : : Tip_InfoTip_Info; ; Leg_StLeg_St, , Leg_DrLeg_Dr : : AdrAdrEnd;End;
DirectieDirectie = (= (Inainte,InapoiInainte,Inapoi););
VarVar Prim : Prim : AdrAdr;; { { AdresaAdresa primuluiprimului element }element }UltimUltim : : AdrAdr;; { { AdresaAdresa ultimuluiultimului element }element }Disc : Char;Disc : Char; { { TipulTipul adaugariiadaugarii }}
3838/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Procedure Procedure CitescCitesc ((VarVar Element:AdrElement:Adr);); {{CitesteCiteste informatiainformatia}}BeginBegin {{dintrdintr--un nod}un nod}
New (Element);New (Element);Write (' ............... Write (' ............... CheieCheie, Date : ');, Date : ');With Element^, With Element^, InfInf Do Do ReadlnReadln ((Cheie,DateCheie,Date))
End;End;
Procedure Procedure GenerareGenerare (Disc:Char; Var Primul,Ultim:Adr); (Disc:Char; Var Primul,Ultim:Adr);
{ Creaza o lista dublu { Creaza o lista dublu îînlănnlănţţuită uită }}Var Nou : Adr; Rasp : Char;Var Nou : Adr; Rasp : Char;Procedure Procedure Adaug_in_coadaAdaug_in_coada;;BeginBeginNou^.Leg_DrNou^.Leg_Dr:=Nil; :=Nil; Nou^.Leg_StNou^.Leg_St:=:=UltimUltim;;If If PrimulPrimul = Nil Then = Nil Then PrimulPrimul := := NouNou
Else Ultim^.Leg_Dr := Nou;Else Ultim^.Leg_Dr := Nou;Ultim:=NouUltim:=Nou
End;End;
3939/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
Procedure Procedure Adaug_in_capAdaug_in_cap;;BeginBegin
Nou^.Leg_DrNou^.Leg_Dr := Prim; := Prim; Nou^.Leg_StNou^.Leg_St := Nil;:= Nil;If Prim = Nil Then If Prim = Nil Then UltimUltim := := NouNou Else Else Prim^.Leg_StPrim^.Leg_St := := NouNou;;Prim := NouPrim := Nou
End;End;Procedure Inserare_ord;Procedure Inserare_ord; Var Prec,Elem : Adr;Var Prec,Elem : Adr;Begin Elem:=Begin Elem:=PrimulPrimul;;While (Elem<>Nil) and (While (Elem<>Nil) and (Elem^.Inf.CheieElem^.Inf.Cheie < < Nou^.Inf.CheieNou^.Inf.Cheie))
Do Elem := Elem^.Leg_dr;Do Elem := Elem^.Leg_dr;If Elem=Nil Then If Elem=Nil Then Adaug_in_coadaAdaug_in_coada ElseElse
If Elem=If Elem=PrimulPrimul Then Then Adaug_in_capAdaug_in_cap Else BeginElse BeginPrecPrec := := Elem^.Leg_StElem^.Leg_St;;Nou^.Leg_StNou^.Leg_St := := PrecPrec; ; Nou^.Leg_DrNou^.Leg_Dr := Elem;:= Elem;Elem^.Leg_StElem^.Leg_St:= := NouNou;;Prec^.Leg_DrPrec^.Leg_Dr:= := NouNou
End {If}End {If}End {End {inserareinserare};};
4040/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
BeginBegin {{GenerareGenerare}}PrimulPrimul:=Nil; :=Nil; UltimUltim:=Nil;:=Nil;RepeatRepeat
RepeatRepeatWrite (' Adaugati (D,N) : '); Readln (Rasp); Rasp:=Upcase(RWrite (' Adaugati (D,N) : '); Readln (Rasp); Rasp:=Upcase(Rasp);asp);
Until Rasp In ['D','N'];Until Rasp In ['D','N'];If Rasp = 'D' Then Begin If Rasp = 'D' Then Begin New(NouNew(Nou); ); CitescCitesc ((NouNou););
Case Disc ofCase Disc of'F' : Adaug_in_coada; 'L' : Adaug_in_cap; 'O' : Inserare_ord'F' : Adaug_in_coada; 'L' : Adaug_in_cap; 'O' : Inserare_ord
End {Case}End {Case}End {If}End {If}
until Rasp = 'N'until Rasp = 'N'End;End;Procedure Procedure ParcurgereParcurgere ((Elem:AdrElem:Adr; ; Sens:DirectieSens:Directie););BeginBegin
While Elem <> Nil Do BeginWhile Elem <> Nil Do BeginWith With Elem^.InfElem^.Inf do do WritelnWriteln (Cheie:5,Date);(Cheie:5,Date);If If SensSens==InainteInainte Then Elem:=Then Elem:=Elem^.Leg_DrElem^.Leg_Dr Else Elem:=Else Elem:=Elem^.Leg_StElem^.Leg_St
End {While}End {While}End;End;
4141/57/57
10.2.1.10.2.1. ListeListe îînlănnlănţţuiteuite..
BeginBeginRepeatRepeat
WritelnWriteln (' (' CeCe disciplinadisciplina doritidoriti la la adăugareadăugare ? ? ');');Writeln (' F = in coada listei (FIFO) ');Writeln (' F = in coada listei (FIFO) ');Writeln (' L = in capul listei (LIFO) ');Writeln (' L = in capul listei (LIFO) ');Writeln (' O = lista ordonata ');Writeln (' O = lista ordonata ');Write (' Write (' OptiuneOptiune : ');: ');ReadlnReadln (Disc); Disc:=(Disc); Disc:=Upcase(DiscUpcase(Disc))
Until Disc In ['F','L','O'];Until Disc In ['F','L','O'];Generare (Disc, Prim, Ultim );Generare (Disc, Prim, Ultim ); { Creerea listei }{ Creerea listei }
Writeln('Lista inainte');Writeln('Lista inainte');Parcurgere (Prim,Inainte);Parcurgere (Prim,Inainte); { Traversare inainte }{ Traversare inainte }
Writeln('Lista inapoi');Writeln('Lista inapoi');Parcurgere (Ultim ,Inapoi );Parcurgere (Ultim ,Inapoi ); { Traversare inapoi }{ Traversare inapoi }
ReadlnReadlnEnd.End.
4242/57/57
10.2.1.10.2.1. ArboriArbori BinariBinari
O colecţie de elemente are o structură de tip arborescent dacă elementelecomponente sunt în relaţie unu la mai_multe, adică un element este în relaţie cu mai multe elemente.
Elementele unei astfel de structuri se numesc noduri sau vârfuri. Ele au un unic predecesor numit părinte dar mai mulţi succesori numiţi fii.
r
ii
i iii
t t t t t
Un arbore este format din mulţimea nodurilor şi legăturile dintre acestea. Un nod al unui arbore poate fi:
• rădăcină(dacă nu are predecesor - părinte ) sau
• nod intern(are un singur părinte şi mai mulţi fii) sau
• nod terminal sau frunză( nu are nici un succesor-fiu).
4343/57/57
10.2.2.10.2.2. ArboriArbori BinariBinari
Un arbore particular este arborele binararborele binar pentru care relaţia dintre elemente este de tip unu la două, adică un element poate avea maxim doi succesori:
Rădăcina
Sub-arbore
stâng
Sub-arbore
drept
r
ii
i iii
f f f f f
Un arbore particular este arborele binararborele binar pentru care relaţia dintre elemente este de tip unu la două, adică un element poate avea maxim doi succesori:
00
11 22
1111 2121 2222
111111 211211112112 212212 222222
NilNil
NilNil
NilNil NilNil
4444/57/57
10.2.2.10.2.2. ArboriArbori BinariBinari
Deci o variabilă de tip arbore va avea tipul Arbore definit astfel:Type Type Arbore = Arbore = ^̂Tip_Elem;Tip_Elem;
Tip_Elem = RecordTip_Elem = RecordInfo Info : : Tip_InfoTip_Info;;As, Ad : As, Ad : AdrAdr
End;End;Aici Tip_Info este tipul informaţiei pastrată într-un nod, putând fi orice tip Pascal
definit anterior.
As Info AdAs Info Ad
Prin traversareatraversarea unui arbore binar vom înţelege parcurgerea tuturor vârfurilor arborelui, trecând o singură dată prin fiecare nod.
În funcţie de ordinea (disciplina) de vizitare a nodurilor unui arbore binar, traversarea poate fi îîn preordinen preordine, îîn inordinen inordine sau îîn postordinen postordine.
4545/57/57
10.2.2.10.2.2. ArboriArbori BinariBinari
Traversarea în preordinepreordine este aceea în care se parcurge mai întâi nodul rădăcină, apoi subarborele stâng şi după aceea subarborele drept. Deci se parcurge arborele în ordinea (RădăcinăRădăcină, Subarbore_stâng, Subarbore_drept, Subarbore_stâng, Subarbore_drept). Evident, definiţia este recursivă, parcurgerea unui subarbore fiind facută dupa aceaşi regulă, deci începând cu rădăcina. O procedură Pascal corespunzatoare se dă în continuare.
Procedure Preordine (R:Arbore);Procedure Preordine (R:Arbore);
BeginBeginIf R<>Nil Then With R^ do BeginIf R<>Nil Then With R^ do Begin
Prelucrare (Info);Prelucrare (Info);Preordine (As);Preordine (As);Preordine (Ad)Preordine (Ad) End {if}End {if}
End;End;
Procedura Prelucrare (Nod) poate reprezenta orice subalgoritm de prelucrare a informaţiei din nodul specificat (de exemplu tipărirea informaţilor).
4646/57/57
10.2.2.10.2.2. ArboriArbori BinariBinari
Traversarea în inordineinordine este aceea în care se parcurge mai întâi subarborele stâng, apoi nodul rădăcină şi după aceea subarborele drept. Deci se parcurge arborele în ordinea (Subarbore_stâng, Subarbore_stâng, RădăcinăRădăcină, Subarbore_drept, Subarbore_drept). În continuare este prezentată o procedură Pascal de traversarea în inordine :
Procedure Inordine (R:Arbore);Procedure Inordine (R:Arbore);BeginBegin
If R<>Nil Then With R^ do BeginIf R<>Nil Then With R^ do BeginInordine (As);Inordine (As);Prelucrare (Info);Prelucrare (Info);Inordine (Ad)Inordine (Ad) End {if}End {if}
End;End;
Traversarea în postordinepostordine este aceea în care se parcurge mai întâi subarborele stâng, apoi subarborele drept şi după aceea nodul rădăcină. Deci se parcurge arborele în ordinea (Subarbore_stâng, Subarbore_dreptSubarbore_stâng, Subarbore_drept, , RădăcinăRădăcină). Procedura Pascal corespunzătoare este următoarea :
Procedure Postordine (R:Arbore);Procedure Postordine (R:Arbore);BeginBegin
If R<>Nil Then With R^ Do BeginIf R<>Nil Then With R^ Do BeginPostordine (As);Postordine (As);Postordine (Ad);Postordine (Ad);Prelucrare (R)Prelucrare (R) End {if}End {if}
End;End;
4747/57/57
10.2.2.10.2.2. ArboriArbori BinariBinari
Pentru arborele următor, ordinea nodurilor corespunzătoare cele trei tipuri de traversări este următoarea :
a) în preordinepreordine : 16,7,5,2,10,9,13,20,19,25,21,29;16,7,5,2,10,9,13,20,19,25,21,29;b) în inordineinordine : 2,5,7,9,10,13,16,19,20,21,25,29;2,5,7,9,10,13,16,19,20,21,25,29;c) în postordinepostordine : 2,5,9,13,10,7,19,21,29,25,20,162,5,9,13,10,7,19,21,29,25,20,16.
1616
202077
1919 2525101055
22 99 1313 2121 2929
4848/57/57
10.2.2.10.2.2. ArboriArbori BinariBinari
În exemplul următor vom genera un arbore binar prin adăugări succesive de noduri după umătoarea regulă: elementele cu cheie mai mare decât cheia informaţiei din nodul rădăcină, se adaugă în subarborele stâng iar cele cu cheie mai mică în subarborele drept. Prin traversarea în inordine a arborelui astfel construit vom obţine lista nodurilor în ordine descrescatoare a cheilor.
Informaţia pastrată într-un nod se referă la un student şi conţine media acelui student (aceasta fiind cheia după care se face ordonarea) şi numele studentului.
Program Arbore_Binar_Ordonat;Program Arbore_Binar_Ordonat; { Prgramul arbore_Binar }{ Prgramul arbore_Binar }TypeType
Tip_InfoTip_Info = Record = Record MedieMedie : real; : real; nume : string[20] End;nume : string[20] End;Adr = Adr = ^̂Tip_Elem;Tip_Elem;Tip_ElemTip_Elem = = RecordRecord
Info : Info : Tip_InfoTip_Info;;As, Ad : As, Ad : AdrAdr
End;End;Var Arb:Adr;Var Arb:Adr;
4949/57/57
10.2.2.10.2.2. ArboriArbori BinariBinari
Procedure Citesc (Var InfNod:Tip_Info);Procedure Citesc (Var InfNod:Tip_Info);BeginBegin
Write (' Write (' MedieMedie(>0), (>0), Nume_StudentNume_Student : ');: ');With With InfNodInfNod Do Do ReadlnReadln ((Medie,numeMedie,nume))
End;End;Procedure Print (Procedure Print (InfNod:Tip_InfoInfNod:Tip_Info););BeginBegin
With With InfNodInfNod do do WritelnWriteln ( Medie:6:2,' ( Medie:6:2,' -- ',',numenume))End;End;Procedure Creare (Var Arb:Adr);Procedure Creare (Var Arb:Adr);Var InfNod: Tip_Info;Var InfNod: Tip_Info;
Procedure Adaug (Var Sarb:Adr);Procedure Adaug (Var Sarb:Adr);BeginBegin
If If SarbSarb<>Nil<>NilThen With Then With SarbSarb^ Do^ Do
If If InfNod.medieInfNod.medie>>Info.medieInfo.medie Then Then Adaug(AsAdaug(As) Else ) Else Adaug(AdAdaug(Ad))ElseElse BeginBegin
New (New (SarbSarb); ); Sarb^.InfoSarb^.Info:=:=InfNodInfNod; ; Sarb^.As:=Nil; Sarb^.Ad:=NilSarb^.As:=Nil; Sarb^.Ad:=Nil End {if}End {if}
End;End;
5050/57/57
10.2.2.10.2.2. ArboriArbori BinariBinari
BeginBeginArbArb:=Nil;:=Nil;RepeatRepeat CitescCitesc ((InfNodInfNod););
If If InfNod.medieInfNod.medie > 10 Then > 10 Then Writeln('medieWriteln('medie>10?') Else>10?') ElseIf If InfNod.medieInfNod.medie > 0 Then > 0 Then Adaug(ArbAdaug(Arb))
Until InfNod.medie <= 0Until InfNod.medie <= 0End;End;Procedure Traversare_Inordine (Sarb:Adr);Procedure Traversare_Inordine (Sarb:Adr);BeginBegin
If If SarbSarb <> Nil Then With <> Nil Then With SarbSarb^ Do Begin^ Do BeginTraversare_Inordine (As);Traversare_Inordine (As);Print (Info);Print (Info);Traversare_Inordine (Ad)Traversare_Inordine (Ad) EndEnd
End;End;BeginBeginWriteln('Se citesc medii Writeln('Se citesc medii şşi nume pana media=0');i nume pana media=0');Creare (Arb);Creare (Arb);Writeln('Elementele arborelui (lista studentilor dupa medie) :Writeln('Elementele arborelui (lista studentilor dupa medie) : ');');Traversare_InordineTraversare_Inordine ((ArbArb);); ReadlnReadln
End.End.
5151/57/57
10.2.2.10.2.2. ArboriArbori BinariBinari
Următorul program va construi un arbore genealogic ascendent (pentru fiecarenod se reţin informaţii despre o persoană şi legăturile de tip mamă şi tată sprenodurile respective) iar apoi se vor depune aceste informaţii într-o listă ordonatădupă anul naşterii. La parcurgerea acestei liste, persoanele vor fi tiparite în ordinea vârstei.
Program Program Arbore_GenealogicArbore_Genealogic;; {Program {Program pentrupentru strămostrămoşşiiii uneiunei persoanepersoane }}Type Type Tip_InfoTip_Info = Record= Record An_NastereAn_Nastere : Integer; : Integer; NumeNume : String[20] : String[20] End;End;
Adra= Adra= ^̂Tip_Elem_A;Tip_Elem_A;Tip_Elem_ATip_Elem_A = Record Info : = Record Info : Tip_InfoTip_Info; As, Ad : ; As, Ad : AdraAdra End;End;AdrlAdrl= ^= ^Tip_Elem_LTip_Elem_L;;Tip_Elem_LTip_Elem_L = Record Info : = Record Info : Tip_InfoTip_Info; Leg : ; Leg : AdrlAdrl End;End;
VarVar ArbArb : : AdraAdra; ; ListaLista : : AdrlAdrl; ; { { AdrAdr. . RădRăd. . arbarb.; .; AdrAdr. . primuluiprimului element }element }Procedure Procedure CitescCitesc ((VarVar Pers:Tip_InfoPers:Tip_Info);); {{CitesteCiteste in in PersPers}}BeginBegin {{informatiileinformatiile despredespre o o persoanapersoana}}
Write (' Write (' Anul_NasteriiAnul_Nasterii, , Nume_PrenumeNume_Prenume : '); : '); With With PersPers do do ReadlnReadln ((An_Nastere,numeAn_Nastere,nume))
End;End;
5252/57/57
10.2.2.10.2.2. ArboriArbori BinariBinari
Procedure Adaug_Arbore (Var Sarb:Adra);Procedure Adaug_Arbore (Var Sarb:Adra); {Depune la adresa Sarb, }{Depune la adresa Sarb, }VarVar PersPers : : Tip_InfoTip_Info;; { inf. { inf. pt.opt.o persoanapersoana }}Begin Begin CitescCitesc ((PersPers); ); {{sisi decide, decide, dacădacă e nod terminal e nod terminal sausau continua }continua }
If If Pers.An_nasterePers.An_nastere > 0> 0Then Then BeginBegin
New (New (SarbSarb); ); SarbSarb^ .Info:=^ .Info:=PersPers;;Write (' Mama ',Write (' Mama ',Pers.numePers.nume,' : '); ,' : '); Adaug_ArboreAdaug_Arbore ((SarbSarb^ .As);^ .As);Write (' Tata ',Write (' Tata ',Pers.numePers.nume,' : '); ,' : '); Adaug_ArboreAdaug_Arbore ((SarbSarb^ .Ad) End {Then}^ .Ad) End {Then}
Else Else SarbSarb:=Nil:=NilEnd;End;Procedure Print (Procedure Print (Pers:Tip_InfoPers:Tip_Info);); {{TiparesteTipareste informatiileinformatiile}}BeginBegin {{despredespre persoanapersoana PersPers}}
WritelnWriteln (Pers.An_nastere:6, (Pers.An_nastere:6, Pers.numePers.nume))End;End;Procedure Inserare_Lista_Ordonata(Pers:Tip_Info; Var Lista:Adrl)Procedure Inserare_Lista_Ordonata(Pers:Tip_Info; Var Lista:Adrl);; {Ins. }{Ins. }Var E, Prec, Nou : Adrl;Var E, Prec, Nou : Adrl; { un nou element }{ un nou element }BeginBegin {pt. Pers, in Lista ordonata }{pt. Pers, in Lista ordonata }
E:=E:=ListaLista;; {Se {Se cautacauta locullocul inserariiinserarii}}While (E<>Nil) and (While (E<>Nil) and (E^.Info.An_nastereE^.Info.An_nastere < < Pers.An_nasterePers.An_nastere) do Begin) do Begin
PrecPrec := E; E := := E; E := E^.LegE^.LegEnd;{WhileEnd;{While}}New (Nou); Nou^.Info:= Pers; Nou^.Leg := E;New (Nou); Nou^.Info:= Pers; Nou^.Leg := E; {Se creaza noul element }{Se creaza noul element }If E = Lista Then Lista := Nou If E = Lista Then Lista := Nou { { şşi se depune in lista }i se depune in lista }
Else Prec^.Leg := NouElse Prec^.Leg := NouEnd;End;
5353/57/57
10.2.2.10.2.2. ArboriArbori BinariBinari
Procedure Arbore_Lista (Sarb:Adra: Var L: Adrl);Procedure Arbore_Lista (Sarb:Adra: Var L: Adrl); {Creaza lista L prin }{Creaza lista L prin }BeginBegin { { TraversareTraversare in in InordineInordine}}
If If SarbSarb<>Nil Then With <>Nil Then With SarbSarb^ do ^ do BeginBeginInserare_Lista_Ordonata (Info, L);Inserare_Lista_Ordonata (Info, L);Arbore_Lista (As); Arbore_Lista (Ad)Arbore_Lista (As); Arbore_Lista (Ad) End {If}End {If}
End;End;
Procedure Procedure ParcurgereParcurgere ((Elem:AdrlElem:Adrl););BeginBegin
While Elem <> Nil DoWhile Elem <> Nil Do BeginBeginPrint(Elem^.Info); Elem:=Elem^.LegPrint(Elem^.Info); Elem:=Elem^.Leg End {While}End {While}
End;End;
BeginBegin {{ProgramulProgramul principal}principal}Write (' Write (' PersoanaPersoana: '); : '); Adaug_ArboreAdaug_Arbore ((ArbArb); ); WritelnWriteln;;Lista:=Nil; Arbore_Lista(Arb,Lista);Lista:=Nil; Arbore_Lista(Arb,Lista);Writeln('Persoanele in ordine cronologica:');Writeln('Persoanele in ordine cronologica:');ParcurgereParcurgere ((ListaLista); ); ReadlnReadln;; { { TiparireaTiparirea listeilistei }}
End.End.
5454/57/57
TemeTeme::
Exemplu : P(x)= 15x3-4.5x+10, Q(x)=10x2+4.5x-2, x=2; deci:
(P+Q)(x)= 15x3+10x2+8, (P+Q)(2)=168P : (15,3); (-4.5,1); (10,0); Q : (10,2); ( 4.5,1); (-2,0);
P+Q : (15,3); (10 ,2); ( 8,0);
1. Să se calculeze (P+Q)(x) utilizand iteratoriiteratori unde: P şi Q sunt douăpolinoame cu coeficienţi reali date iar x este un număr real de asemenea dat.
Polinoamele P,Q şi P+Q vor fi reprezentate sub forma unor liste simpluinălnţuite ordonate (după grad) cu elemente de forma Coeficient, Grad, Leg.
5555/57/57
TemeTeme::
Lpol
↓↓Pol1 P11,P12,…, P1n
↓↓……↓↓Polm Pm1,Pm2,…, Pmn
2. Pentru o listă de poligoane date, să se verifice dacă acestea sunt convexe
utilizand IteratoriIteratori.Lista si poligoanele sunt reprezentate sub formă de liste implementate cu
cursorcursor. Lista = (Cap, CursorCap, Cursor)..
Poligonul este dat prin lista varfurilor.
5656/57/57
TemeTeme::
Exemplu :
3. Să se creeze, să se actualizeze şi să se reprezinte grafic după fiecareoperaţie un arbore binar ordonat, apoi să se tipărească informaţiile acestuia in ordine crescătoare a cheii (campul de ordonare). Informaţiile din fiecare nod vorfi de forma : (Nume_persoaNume_persoanănă, , Anul_NaAnul_Naşşteriiterii), iar listarea se va face după varstă.
CataCata | 1955| 1955 TurcuTurcu | 1958| 1958 IliesIlies | 1960| 1960
PascuPascu | 1959| 1959RaresRares | 1956| 1956
Pop | 1957 Pop | 1957
5757/57/57. . .. . . CC1010 / 7.11.2012/ 7.11.2012
SuccesSucces!!