Documente Academic
Documente Profesional
Documente Cultură
CUPRINS
1. MODELE DE CALCUL.........................................................................................................3
1.1. Legtura dintre analiza algoritmilor i dezvoltarea software...........................................4
2.1. Algoritmi recursivi i relaii de recuren......................................................................10
2.2 Analiza spaiului de memorie consumat ntr-un algoritm...............................................15
2.3. Arbori.............................................................................................................................17
2.3.1. Reprezentarea arborilor...........................................................................................18
2.3.2. Arbori binari............................................................................................................20
3. GRAFURI. TRAVERSRI PE GRAFURI..........................................................................35
4. STRUCTURI DE DATE ELEMENTARE...........................................................................38
4.1. Pointeri i adrese............................................................................................................38
4.1.1. Pointeri i argumente de funcii..................................................................................40
4.1.2. Pointeri i tablouri.......................................................................................................42
4.1.3. Aritmetica adreselor....................................................................................................44
4.1.4. Pointeri pe caractere i funcii.....................................................................................47
4.2. Tablouri..........................................................................................................................49
4.3. Liste................................................................................................................................50
4.3.1. Implementri de liste...............................................................................................51
4.3.2. Alte consideraii asupra operaiei de inserare ntr-o list nlnuit........................55
4.3.3. Stive ordonate.........................................................................................................56
4.3.4. Stive nlnuite........................................................................................................58
4.3.5. Cozi ordonate.........................................................................................................59
4.3.6. Cozi nlnuite.........................................................................................................62
4.3.7. Liste generalizate...................................................................................................64
4.4. Fiiere.............................................................................................................................74
4.4.1. Fiiere text i fiiere binare....................................................................................74
4.4.2 Accesul la fiiere.....................................................................................................75
4.4.3. Algoritmi de prelucrare a fiierelor secveniale......................................................76
5. IMPLEMENTAREA STRUCTURILOR DE DATE............................................................83
5.1. Structuri simple de date.................................................................................................83
5.2. Liste, pointeri, mulimi, arbori.......................................................................................90
5.3. Fiiere text i fiiere cu tip. Fiiere secveniale...........................................................129
1. MODELE DE CALCUL
Maina este un model de calcul constituit din Unitate Centrala (U.C.), Memorie (M),
I/O.
Exemple de modele de calcul:
Maina Von Newman (fig.1)- presupune execuia pe baz modelului de calcul cu:
U . C.
M.
I/O
Maina TURING
variabile;
identificatori;
constante;
operatori relaionali;
4
Design
Testare
Implementare
se pleac de la cerine;
se obin specificaii;
proiectarea algoritmilor;
analiza performanelor;
testarea
Ultima faz:
implementarea.
Programul rezultat se compar cu cerinele, i dac nu corespunde, se reia ciclul ori de
cte ori este nevoie.
Analiza performanelor presupune- renunnd la acuratee- estimarea timpului de lucru
i a spaiului de stocare, netiind nc limbajul care va fi folosit i calitatea programului ce se
va obine.
Presupunnd c modelul RAM de main pe care lucrm execut instruciuni
pseudocod, i ca fiecare instruciune pseudocod consum acelai timp de execuie, rezult c
timpul estimat pentru execuia unui algoritm este proporional cu numrul instruciunilor
executate de acel algoritm.
Timpul de execuie al algoritmului depinde de:
Resurse:
1. ro.wikipedia.org/wiki/Main_Turing
2. http://www.slu.edu/colleges/AS/languages/classical/ram/ram.html - exemplu free de
imlmentare a mainii RAM
3.http://facultate.regielive.ro/cursuri/electronica_calculatoare_limbaje_de_programare/structu
ri_de_date_si_algoritmi-668.html
4.http://www.cs.cmu.edu/~mihaib/articles/spatial/spatial-html.html- un exemplu de
imlpementare n hardware a programelor
2.COMPLEXITATEA ALGORITMILOR
Facem precizarea c parte din algoritmii i structurile prezentate n capitolele
urmtoare- cu precdere cele relative la pointeri i fiiere privesc sintaxa i semantica proprie
limbajului C. Unele consideraii teoretice sau practice sunt descrise n pseudocod, C ori
Pascal, scopul declarat fiind acela de a oferi cititorului o imagine ct mai clar a
mecanismelor de funcionare a algoritmilor i de reprezentare a structurilor prezentate, cu
accent mai puin pe specificitatea limbajului folosit pentru implementare.
La evaluarea (estimarea) algoritmilor se pune n eviden necesarul de timp i de
spaiu de memorare al lui.
Studierea complexitii presupune analiza complet n cadrul algoritmului a
urmtoarelor 3 puncte de vedere:
1. configuraia de date cea mai defavorabil (cazurile degenerate);
2. configuraia de date cea mai favorabil;
3. comportarea medie.
Punctul 3 presupune probabilitatea de apariie a diferitelor configuraii de date la
intrare.
Punctul 1 este cel mai studiat i este folosit, de obicei, pentru compararea algoritmului.
i n ceea ce privete timpul, se studiaz configuraia cea mai defavorabil a algoritmului.
Complexitatea unui algoritm se noteaz cu: O(f(n)).
Definiie. Fie f,g : N N dou funcii. Spunem c f O(g) i notm f = O(g) dac
i numai dac o constant c R i un numr n0 N astfel nct pentru n n0 : f(n)
cg(n).
Observaie:
f : N N este o funcie f(n) cu n - dimensiunea datelor de intrare.
f(n) reprezint timpul de lucru al algoritmului exprimat n "pai".
Lema 1. Dac f este o funcie polinomial de grad k, de forma:
f(n) = ak nk + ak-1nk-1 + ... + a1 n + a0,
atunci
f = O(nk).
Fcndu-se majorri n membrul drept, obinem rezultatul de mai sus:
f(n) < ak nk + ak-1 nk-1 + ... + a1 n + a0 < nk ( ak + ak-1 + a0 ) < nk c
pentru n > 1 f(n) < c nk, cu n0 = 1.
Concluzie: f = O(nk), i ordinul O exprim viteza de variaie a funciei, funcie de
argument.
Exemplu: Calcularea maximului unui ir
maxsir(A,n)
{
6
max = A[1]
for i= 2 to n do
if A[i] > max then
max = A[i]
return (max)
}
Exprimm:
T(n) timpul de execuie n pai al acestui algoritm;
T(n)= 1 + 2(n-1) = numrul de atribuiri i comparaii
Cazul cel mai defavorabil: situaia n care vectorul este ordonat cresctor (pentru ca de
fiecare dat se face i comparaie i atribuire).
Putem spune c T(n) = O(n), este o funcie polinomial de gradul I. Conteaz doar
ordinul polinomului, nu coeficientul termenului de grad maxim. Iar la numrarea pailor ne
concentrm asupra numrului buclelor, nu asupra pailor din interiorul buclei.
Exemplu:
Insertion Sort (algoritmul de sortare prin inserare)
Algoritmul INSERTION SORT consider c n pasul k, elementele A[1k-1] sunt
sortate, iar elementul k va fi inserat, astfel nct, dupa aceasta inserare, primele elemente
A[1k] s fie sortate.
Pentru a realiza inserarea elementului k n secvena A[1k-1], aceasta presupune:
i O ( n2 )
i 1
{
for i = 1 to n do
for j = 1 to n do
| C[i,j] = 0
|for k = 1 to n do
|_
C[i,j] = C[i,j] + A[i,k] * B[k,j]
}
Rezult complexitatea O(n3).
Exemplu: Cutarea binar (Binary Search)
Fie A, de ordin n, un vector ordonat cresctor. Se cere s se determine dac o valoare
b se afl prntre elementele vectorului. Limita inferioar se numete low, limita superioar se
numete high, iar mijlocul virtual al vectorului, mid.
low
middle
high
Binary_search(A,n,b)
{
low = 1;
high = n;
while low <= high do
| mid = [(low + high)/2];
//partea ntreaga
| if A[mid]=b then return (mid);
| else if A[mid]>b then high=mid-1; //restrng
|
//cautarea la partea stnga
|_
else low = mid+1;
//restrng cautarea la dreapta
return(0);
}
Calculul complexitii algoritmului const n determinarea numrului de ori pentru care se
execut bucla while.
Se observ c, la fiecare trecere, dimensiunea zonei cutate se njumtete. Cazul cel
mai defavorabil este ca elementul cutat s nu se gseasc n vector. Pentru simplitate se
consider n = 2k unde k este numrul de njumtiri.
Rezult k = log2 n i facnd o majorare, T(n) log2 n + 1 n, a.. 2k n < 2k+1.
Complexitatea acestui algoritm: este O(log2n). Baz logaritmului se poate ignora,
deoarece: logax = logbx logab i logab este o constant, ramne deci O(log n), adic o
funcie logaritmic.
Proprieti:
1) Fie f, g : N N.
Dac f = O(g)
| k f = O(g)
| f = O(k g) , k R constant.
2) Fie f, g, h : N N.
i:
f = O(g)
|
g = O(h)
|
f = O(h)
8
f1 = O(g1) |
| f1 + f2 = O(g1 + g2)
f2= O(g2) |
| f1 f2 = O(g1g2)
Aceasta proprietate permite ca, atunci cnd avem dou bucle imbricate (de
complexiti diferite), complexitatea total s se obin nmulindu-se cele dou complexiti.
Cele dou complexiti se adun, dac buclele sunt succesive.
Teorema.
Oricare ar fi dou constante c > 0, a > 1, i f : N N, o funcie monoton
strict cresctoare, atunci:
(f(n))c= O(af(n))
Demonstraia se bazeaz pe limita:
xp
x a x
( a , p )
lim
O(2n)
i
i 1
n
n ( n 1)
2
O(n2 )
i2
n ( n 1) ( 2 n 1)
6
i3
n2 ( n 1)2
4
i 1
n
i 1
n
O(n3 )
O(n4 )
21 2n1 - 1
i 0
i 21
i 1
Se noteaz:
G ( n)
i 21
i 1
G(n)=2G(n)-G(n)=i=1n2i2l-i=1ni2l=i=1ni2l+1-i=1ni2l=
n2n+1-2+i=2n(i-1-i)2l=n2n+1-2-i=2n2l=(n-1)2n+1+2
Prin aceeai tehnic se calculeaz suma:
n
(n 1) 21
i 1
Am vzut c:
i 2n1 2n1 2 n
i 1
cazul n=3
ti
tf
ti
tf
tm
10
Procedura Hanoi:
Hanoi(n, ti, tf, tm)
{
if(n=1) then muta (ti, tf) // deplaseaz discul superior de pe ti pe tf
else
| Hanoi(n-1, ti, tm, tf)
| muta(ti, tf)
|_ Hanoi(n-1, tm, tf, ti)
}
Pentru o problem P(1), timpul T(1) = 1, pentru o mutare.
Pentru P(n), timpul:
T ( n ) 2 T ( n 1) 1
(1)
T ( n ) 2 T ( n 1) 1 1 2 ( 2 T ( n 2 ) 1)
Asociem relaiei (1) ecuaia caracteristic: x 2 x 1; x0 1; x0 2 x0 1
T ( n ) x0 2 ( T ( n 1) x0 f ( n ) 2 f ( n 1) f ( n ) T ( n ) x0
f ( n 1) T ( n 1) x0 , cu x0 const.
f ( n ) 2 f ( n 1) 2 2 f ( n 2 ) 2 2 2 f ( n 3) 24 f ( n 4 ) ... 2n 1 f (1)
Fcnd identificarea:
2n 1 2 T ( n ) 1
f (1) x0
T(n) = 2 n 1
c)
f ( n ) t1n t2n
3.
n 1
0,
T ( n)
2T (n / 2) n, n 1
12
Considerm: n = 2k;
T(n) = 2T(n/2) + n = 2(2T(n/4) + n/2) + n = ... = 22T(n/22) + 2n
= 22 (2T(n/23) + n/22) + 2n = 23T(n/23) + 3n = ... = 2kT(n/2k) + kn
T(n) = kn = nlog2n ,
pentru c n = 2k , i, deci, k = log2n.
a bk
T ( n ) O ( n k log n ),
O ( n k ),
a bk
a bk
algoritmul Binary_Search:
a = 1 , b = 2 , k = 0 complexitatea O(n0log n) = O(log n), (situaia ak = b).
4.
Exemplu:
n 1
T (i )
i 1
T ( n ) C T ( n 1) T ( n 2 ) ... T (1)
T ( n 1) C
T (i )
- se face T ( n 1) T ( n )
i 1
pivot
A[k]=pivot
elemente
pivot
l= low; h= high;
x= A[l];
while (l <h) do
I | while (A[l] x) and (l >_high)
|
do l= l+1
II | while (A[h] >x) and (h low)
|
do h= h-1
|_ if (l <h) then interchange (A[l], A[h])
interchange (A[h], A[low])
return(h);
}
Algoritmul consider pivotul ca fiind: A[low]. Indicele l parcurge vectorul de la stnga
la dreapta, iar indicele h parcurge vectorul de la dreapta la stnga. Ei se apropie pn se
ntlnesc (l = h). Deci, l las n urma numai elemente A[i] pivot, iar h las n urm numai
elemente A[i] pivot.
Ciclul I while nseamn c nainteaz l ct timp A[l] pivot. Acest ciclu se oprete pe
condiia
A[h] pivot, fixndu-se aici.
Ciclul II while nseamn c nainteaz h ct timp A[h] pivot. Acest ciclu se oprete
pe condiia:
A[h] pivot, fixndu-se aici.
Cele dou poziii se schimb, astfel nct s se permit naintarea indicilor mai
departe.
low
Pentru aflarea complexitii, cercetm cazul cel mai defavorabil. Fie cazul n care
vectorul este ordonat descresctor. Pivotul gsit, la primul pas, este elementul maxim din
vector, rezult c trebuie plasat n ultima poziie. Pivotul va fi maximul dntre elementele
secvenei, deci, va fi plasat n ultima poziie din secven.
Problema se mparte n 2 subprobleme: P(n) P(n-1) , P(0).
Numrul de comparaii pentru funcia Partition este (n-1). Vectorul se parcurge n
dou direcii, dar o singur dat.
Rezult c timpul de funcionare al algoritmului Quick_Sort este:
T ( n ) ( n 1) T ( n 1) .
n 1
i n(n 1) / 2
i 1
n 1
T (i )
i 0
T (i )
i 0
( n 1) T ( n 1) nT ( n ) n ( n 1) n ( n 1) 2 T ( n )
( n 1) T ( n 1) 2 n ( n 2 ) T ( n )
1
care se nmulete cu:
,
( n 1)( n 2 )
T ( n 1)
2n
T (n)
n2
( n 1)( n 2 ) n 1
Notm:
T ( n)
F (n)
,
n 1
F ( n 1)
2n
F ( n ),
( n 1)( n 2 )
F ( n)
2 ( n 1)
+ F ( n - 1)
n ( n 1)
Fcnd o majorare:
F (n)
F (n)
2
F ( n 1)
n
2
2
2
2
2
2
2
2
2
2
F ( n 1)
F (n 2)
F ( n 3) ...
... F (i )
n
n n 1
n n 1 n 2
n n 1 n 2
2
F ( n ) 2 ln n 2 ln 1 F ( n ) 2 ln n
T ( n)
F ( n ) T ( n ) ( n 1) ln n 2 n ln n T ( n ) O ( n ln n )
n 1
low
high
k
high
low
k
secventa mica rezolvata recursiv
2.3. Arbori
Exemplu de structur de arbore:
a
/ \
b
/ \
d
e
/
h
c
/ \
f
g
\
\
i
j
Exemple de arbori:
poligoane
/
\
triunghi patrulatere
/ \ \
dreptunghi romb oarecare
Definiie
Se numete arbore cuplul format din V i E : T= (V,E) cu V - o mulime de noduri i
E VxV - o mulime de arce, cu proprietile:
1) nodul r V (nodul rdcin) astfel nct j V, (j, r) E
2) x V\{r} , y V unic, astfel nct (y, x) E (Cu alte cuvinte, pentru toate nodurile
care nu-s rdcin, un singur arc ce intr n nodul respeciv)
3) y V, un drum { r = x0, x1, x2, ... ,xn= y} , cu xi V i (xi, xi+1) E (sau arborele
trebuie s fie un graf conex: nu exist noduri izolate sau grupuri de noduri izolate).
Proprietate
Dac T, T= (V, E) este un arbore i r V este rdcina arborelui, atunci mulimea T\
{r}=(V',E'), cu V' = V -{r} i E' = E -{ (r, x)/(r, x) E } poate fi partiionat astfel nct s
avem mai muli arbori, a cror reuniune s fie T\{r}, i oricare ar fi doi arbori intersectai, s
dea mulimea vid:
T\{r}= T1 T2 ... Tk , Ti Tj = .
17
Definiii
1)
Dac avem (x, y) E , x
\
D
/ | \
H I J
|
M
predecesor(E) = B
succesor(C) = G
E(D) = {H, I, J}
degree(D) = 3
degree(B) = 2
degree(F) = 0
degree(T) = 3
ancestors(L) = {A, B, E}
level(L) = 4 , level(B) = 2 , level(A) = 1
depth(T) = 4
2.3.1. Reprezentarea arborilor
Reprezentarea prin liste generalizate
Se consider c nodurile terminale sunt elemente atomice, iar nodurile de grad 1
sunt subliste. Deci, fie arborele de mai sus scris sub forma:
A( B (E (K, L), F), C (G), D (H (M), I, J))
cu reprezentarea:
18
G 0
0 M
data
......
link2
k=degree(T)
link k
B
C
F
0
K
0
L
0
M
0
19
A 0
Avnd adresa unui nod, se gsesc toi predecesorii, obinndu-se o list nlanuit:
(Reprezentarea TATA):
M
A
/
B
C
\
E
A
/ \
B C
/ \ / \
D E F G
/
C
Observaie:
Arborele A este diferit de A
/ \
/ \
B vid
vid B
Structura de baz a unui arbore binar:
rad
/
/
\
\
/ \
/ SAS \
/______ \
/ \
/ SAD \
/_______\
Exemplu:
a
/ \
b
c
/ \ / \
d e f g
/ \
h i
2)
Se numete arbore binar complet un arbore binar strict pentru care y cu:
degree(y) = 0 (frunza) level(y) = depth(T)
Cu alte cuvinte, nodurile terminale aparin ultimului nivel din arbore.
Exemplu:
a
/
b
/ \
c
/ \
d
e f
g
/ \ / \ / \ / \
h i j kl mn o
2.3.2.1. Relaii ntre numrul de noduri i structura unui arbore binar
Lema 1
Numrul maxim de noduri de pe nivelul i al unui arbore binar este egal cu 2i-1.
Demonstraia se face prin inducie:
La nivelul 1 avem 20 = 1 nod = rad (rdcina A). Presupunem conform metodei P(n):
pe nivelul n avem 2n-1 noduri. Demonstrm pentru P(n+1): se observ c toate nodurile de
pe nivelul n+1 sunt noduri descendente de pe nivelul n. Notnd niv(i) numrul de noduri de
pe nivelul i rezult:
niv(n+1) 2niv(n) 22n-1 = 2n.
Lema 2
Numrul maxim de noduri ale arborelui binar de adncime h este egal cu 2h -1.
Demonstraie:
Numrul total de noduri este egal cu:
h
i 1
niv (i )
i 1
2i 1 20 21 ... 2h 1
2h 1
2h 1 (progresie geometric).
2 1
Observaie: Numrul maxim de noduri pentru arborele binar se atinge n situaia unui
arbore binar complet.
2h -1 = numrul de noduri n arborele binar complet de adncime h
Lema 3
Notm cu:
n2 - numrul de noduri de grad 2 din arborele binar;
n1 - numrul de noduri de grad 1 din arborele binar;
21
Exemplu de traversare:
a
/
b
c
\
\
e
/ \
g
preordine : A B D E G H C F
inordine : D B G E H A C F
postordine : D G H E B F C A
| print (data(t))
| preorder (lchild(t))
|_ preorder (rchild(t))
if(t 0)
| inorder (lchild(t))
| print (data(t))
|_ inorder (rchild(t))
if(t 0)
| postorder (lchild(t))
| postorder (rchild(t))
|_ print(data(t))
}
inorder(t)
{
}
postorder(t)
{
}
Binarizarea arborilor oarecare
Lema 1
Dac T este un arbore de grad k cu noduri de dimensiuni egale (k pointeri n fiecare
nod), arborele avnd n noduri reprezentarea va conine n (k - 1) + 1 pointeri cu valoare zero
(nuli).
Demonstraie: numrul total de pointeri utilizati n reprezentare este nk. Numrul total
de pointeri nenuli este egal cu numrul de arce nk - (n - 1) = n (k - 1) + 1
nr. pointeri nuli n ( k 1) 1
n 1
1
nr. total pointeri
nk
nk
23
15
/ \
10 25
/\ /
2 17 13
nu este BST.
Funcii:
1)
Search:
search(rad,k) // rad
}
Insert:
Se va crea un nod n arbore care va fi plasat la un nou nod terminal. Poziia n care
trebuie plasat acesta este unic determinat n funcie de valoarea cheii de cutare.
2)
// rad
}
Observaie:
1)
La inserarea unui atom deja existent n arbore, funcia insert nu modific structura
arborelui. Exist probleme n care este util contorizarea numrului de inserri a unui atom n
arbore.
2)
Funcia insert poate returna pointer la rdcina fcnd apeluri de forma p= insert(p,a).
3)
Delete:
delete(rad,k) // rad
delete (rchild(rad),k)
else delete_root(rad)
}
tergerea rdcinii unui BST.:
1)
rad arbore vid
2)
a) rad
sau
b) rad a) SAS
/
\
SAS
SAD
sau
b) SAD
delete_root(rad)
// rad referinta la pointer la rdcina
{
if lchild(rad)=0 then
| p= rchild(rad)
| ret_sp(rad)
|_ rad= p
else if rchild(rad)= 0 then
| p= lchild(rad)
| ret_sp(rad)
|_ rad= p
else |
p=
remove_greatest(lchild(rad))
| lchild(p)= lchild(rad)
| rchild(p)= rchild(rad)
| ret_sp(rad)
|_ rad= p
}
15
/ \
7
25
/ \ / \
2 13 17 40
/
/
9
27
/ \
26 33
Detaarea din structura arborelui BST a celui mai mare nod- (remove_greatest):
Pentru a gsi cel mai mare nod dintr-un arbore binar de cutare, se nainteaz n
adncime pe ramura dreapt pn se gsete primul nod care nu are descendent dreapta.
Acesta va fi cel mai mare.
Vom trata aceast procedur recursiv:
Caz1: rad se returneaz pointer la rdcin i arborele rezultat va fi vid.
26
( i ) O( n
i 1
Notm cu T(k) numrul de comparaii mediu pentru crearea unui BST pornind de
la o secven de k elemente la intrare. Ordinea celor k elemente se consider aleatoare.
Pentru problema T(n) avem de creat secvena (a1 a2 ... an) cu observaia ca a1 este
rdcina arborelui. Ca rezultat, n urma primei operaii de inserare pe care o facem, rezult:
a1
/ \
a1
ai
(ai<a1) (ai>a1)
27
i 1
i 1
T ( n ) ( n 1) (1 / n ) T ( i 1) (1 / n ) T ( n i )
Notm:
Ti(n) = numrul mediu de comparaii necesar pentru construirea unui BST cu n noduri
atunci cnd prima valoare inserat (a1) este mai mare dect i-1 dntre cele n valori de inserat.
Putem scrie:
Ti ( n ) ( n 1) T ( i 1) T ( n i )
n
T ( n ) (1 / n ) Ti ( n )
i 1
Deci:
n
T ( n ) (1 / n ) (( n 1) T ( i 1) T ( n i ))
i 1
i 1
i 1
( n 1) (1 / n ) T ( i 1) (1 / n ) T ( n i )
n
( n 1) ( 2 / n ) T ( i 1)
i 1
Astfel:
n 1
T ( n) n 1 (2 / n) T (i)
i 0
a
/ \
b
c
b
c
/ \ / \
/ \
\
d
e f
g
d e
f
/ \
g
h
arbore binar
arbore binar
complet echilibrat echilibrat
/
28
/ \
B T3
/ \
T1 T2
Considerm arborii T1, T2, T3 echilibrai. Insernd un nod prin rotaie simpl, rezult
structurile rotit simplu la dreapta i rotit simplu la stnga
dreapta:
A
/ \
B T3
/ \
T1 T2
Caz 2:
A
/ \
T3 B
/ \
T2 T1
rotaie dubl
la dreapta
A
/ \
T3 B
/ \
T2 T1
rotaie dubl
la stnga
29
B
// \
// A
T1
/ \\
____________T2_T3_________ pe aceeai linie
care este un BST, deci este arbore echilibrat, i are aceeai adncime (!!!) cu arborele iniial
(de dinainte de inserare). Nodurile superioare nu sunt afectate. Rationament analog pentru
imaginea oglind.
Fie cazul 2: Pentru rotaia dubla se detaliaz structura arborelui T2. Nu se poate
sparge arborele iniial ca n cazul 1.
A
/ \\
B
\\
// \
T3
// C
//
/ \
T1 T2S T2D
depth(T1) = depth(T3) = h
depth(T2S) = depth(T2D) = h - 1
n urma inserrii, unul dntre arborii T2S i T2D si mrete adncimea. Aplicam
aceeai
tehnic:
T1 < B < T2S < C < T2D < A < T3
ncepem cu C:
C
/
\
B
A
// \
/ \\
//
T2S T2D \\
____T1_________ T3_____________________
la acelasi nivel
Rezult un BST echilibrat, de aceeai adncime cu arborele iniial. Rotatiile sunt
duble, n sensul c s-a facut o rotaie simpl B la stnga cu o rotaie simpla A la dreapta.
Operaiile care trebuiesc fcute n cazul 1 (rotaie simpl la dreapta):
r pointer la nodul rdcina (A)
a pointer la rdcina
30
p = lchild(r)
b = lchild(a)
lchild(r) = rchild(p)
lchild(a) = rchild(b)
rchild(p) = r
rchild(b) = a
r=p
a=b
Operaiile care trebuiesc fcute n cazul 2 (rotaie dubl)
b = lchild(a)
c = rchild(b)
lchild(a) = rchild(c)
rchild(b) = lchild(c)
rchild(c) = a
lchild(c) = b
a = c // se schimba rdcina arborelui.
Aadar, n inserarea prin rotaie se obine un arbore echilibrat cu adncimea egal cu
adncimea arborelui de dinainte de inserare. La inserarea unui nod terminal ntr-un arbore
AVL este necesar aplicarea a cel mult o rotaie asupra unui nod. Trebuie, deci s gasim nodul
asupra cruia trebuie aplicat rotaia. Reprezentm ramura parcurs de la rdcin la nodul
inserat:
bf = 1
x
/
bf = 0
y
\
z
\
w
/
bf = 0 (bf = -1 dup inserare)
v
\
nodul
inserat
31
1.
Nodul critic va fi perfect balansat (bf = 0), dac dezechilibrul creat de nodul inserat
anuleaz dezechilibrul iniial al nodului. n acest caz nu este nevoie de rotaie (el completeaz
un gol n arbore).
2.
Factorul de balansare devine bf = 2 sau bf = -2 atunci cnd nodul inserat mareste
dezechilibrul arborelui (s-a inserat nodul n subarborele cel mai mare). n acest caz, se aplica
o rotaie n urma creia se schimb strucutra subarborelui, astfel nct noua rdcin capat bf
= 0, conservndu-se adncimea.
Concluzie: Problema conservrii proprietii de echilibrare a arborelui se rezolv aplicnd o
rotaie asupra nodului critic numai atunci cnd inserarea dezechilibreaz acest nod.
Costul suplimentar care trebuie suportat se materializeaz prin necesitatea ca n fiecare
nod s se memoreze factorul de dezechilibrare bf. Aceti factori de dezechilibrare vor fi
actualizai n urma operaiilor de rotaie i inserare. Operaia de tergere ntr-un AVL implic
mai multe rotaii.
Exemplu: Se d arborele cu urmtoarea structur:
55
/
20
/ \
10 35
/
/
5
30
\
80
\
90
\
80
\
90
15 35 80
\
/
\
7 30
90
n urma unei rotaii simple, factorii de dezechilibru implicai n rotaie devin zero.
Fie o a treia valoare de inserat 3, apoi a patra 9:
Nodul critic pentru 3 este 5, iar pentru 9 este este 10. Dup rotaia aplicat, rezult
arborele:
20
/
\
7
55
/ \
/ \
5 10 35 80
/ / \
/
\
3 9 15 30
90
La rotaia dubla, dac nodul 9 a fost inserat n subarborele T2S,
B are bf = 0 |
A are bf = -1 |
excepie fcnd nodul C nodul de inserat
La rotaia dubla, dac nodul 9 a fost inserat n subarborele T2D,
B are bf = 1 |
A are bf = 0 |
excepie fcnd nodul C nodul de inserat
2.3.2.5. Reprezentarea implicit a arborilor binari
n acest mod de reprezentare se reprezinta arborele printr-un tablou. Fie un arbore
binar complet:
a
/
/ \
d
e
/ \ / \ /
h i j
k l
/ \
f
g
\ / \
m n o
1
indici
10
11
12
13
14
15
Dac n vectorul V un nod x este reprezentat prin elementul de vector V(i), atunci:
1. left_child(x) este reprezentat n elementul de vector V [2i];
2. right_child(x) este reprezentat n elementul de vector V [2i + 1];
3. parent(x) este reprezentat n elementul de vector V [[i/2]]
cu observaia c paranteza ptrat interioar este partea ntreg.
Demonstratie:
Se face inducie dup i:
Pentru i = 1 V[1] rdcina
V[2] left_child(rad)
V[3] right_child(rad)
Presupunem adevrat lema pentru elementul
V[i] V[2i] left_child
V[2i + 1] right_child
Elementul V[i + 1] este nodul urmto*r (de pe acelasi nivel sau de pe nivelul
urmto*r) ntr-o parcurgere binar.
V[i + 1] left_child n V[2i + 2] = V[2(i + 1)]
right_child n V[2i + 3] = V[2(i + 1) + 1]
Dac avem un arbore binar care nu este complet, reprezentarea lui implicit se obine
completndu-se structura arborelui cu noduri ficive pn la obinerea unui arbore binar
complet.
2.3.2.6. Arbori heap (heap
grmad)
Definiie:
Se numete arbore heap un arbore binar T = (V, E) cu urmtoarele proprieti:
1)
funcia key : V R care asociaz fiecarui nod o cheie.
2)
un nod v V cu degree(v) > 0 (nu este nod terminal), atunci:
key(v) > key(left_child(v)), dac left_child(v)
key(v) > key(right_child(v)), dac right_child(v)
(pentru fiecare nod din arbore, cheia nodului este mai mare dect cheile descendentilor).
Exemplu:
99
/ \
50
30
/ \ / \
45 20 25 23
Observaie: De obicei funcia cheie reprezint selecia unui subcmp din cmpul de date
memorate n nod.
Aplicaii ale arborilor heap
Coada cu prioritate;
Algoritmul Heap_Sort
Resurse:
1. http://www.cs.cmu.edu/~mihaib/articles/algoritmi/algoritmi-html.html - complexitatea
algoritmilor i noiuni conexe
2.http://thor.info.uaic.ro/~adiftene/Scoala/PA/PA%20-%20Seminar01%20-%20Complexitatea
%20Algoritmilor.pdf seminarii de proiectarea algoritmilor, cu exemple de calcul i exerciii
3. http://www.cs.utt.ro/%7Emarius/curs/upc/curs16.pdf - despre algoritmii de sortare
34
35
i, j - adiacente;
Definiie
Se numete drum orientat ntr-un graf de la x la y secvena de noduri D = (i1 = x,
i2, ... , in = y),
(ik, ik+1) E, k 1, n .
Drumul D este neorientat, dac (ik, ik+1) E sau (ik+1, ik) E
Definiie
Se numete graf conex graful pentru care dounoduri (x, y) V, D un drum de la
x la y.
Un graf este complet dac fiecare nod este conectat cu oricare din celelalte noduri: E
= VV \ {(i, i), i V}
Definiie
Fie G = (V, E) un graf. Se numete subgraf al grafului G, un graf G' = (V', E'), astfel
nct V' V, E' (V'V') E
Reprezentri
1)
Matrice de adiacen
Fie G = (V, E) ,V = n. Se determin matricea de adiacen
astfel:
M n n , M (i , j )
1 (i , j ) E
0 (i , j ) E
36
0 (i , j ), (i , j ) E
,
(i , j ) E
Complexitate:
1)
O(1), (i, j) E
O(n), Ei, E'i, indegree(i), outdegree(i)
O(n2), spaiu
Definiie
Fie G = (V, E) un graf, V = n , V = {1, 2, ... , n}. Se numete list de adiacen
asociat acestui graf o colecie de n pointeri (1, 2, ... , n), fiecare pointer coninnd adresa
unei liste dup regula urmtoare: L(i) da adresa listei nlanuite care conine toti succesorii lui
i.
L(i) Ei
Exemplu:
2
2)
3)
}
bfs(G, i)
{
ext o coada q
isempty,
// a= pop(p), put(q) ext
procesare(i)
mark(i) = 1
put(q, i)
while(is Empty(q) = N0)) do
| k = pop(q)
| for fiecare j V , (k,j) E
|
| if(mark(j)=0)
|
|
| procesare(j)
|
|
| mark(j) = 1
|_
|_
|_ put(q,j)
}
1)
Matrice adiacen
dfs(M, i)
{
procesare(i)
mark(i) = 1
for k = 1 to n
| if (M(i,k) = 1)
|
| if mark(k) = 0
|_
|_ dfs(k)
}
2)
mark(i) = 1
p = P(i)
while p 0
| if mark(data(p)) 0
| dfs(data(p))
|_ p = link(p)
}
Arbori de acoperire pe grafuri
Fie G(V, E) un graf.
Se numete arbore de acoperire un arbore T = (V, E') , cu E' E
Observaie: Algoritmii dfs, bfs produc arbori de acoperire.
Resurse:
1. www.cwu.edu/~andonie/Cartea%20de%20algoritmi/cap9.htm - 87k- explorri n grafuri
2. http://inf.ucv.ro/~bazavan/courses/CB1103/tutorial3.pdf- similar ca mai sus, inclusiv arbori
px=&x
asigneaz variabilei px adresa lui x acum, px nseamn "pointeaz pe x". Operatorul & poate
fi aplicat numai variabilelor i elementelor unui tablou, construcii ca &(x+1) i &3 sunt
interzise.
Este deasemenea interzis pstrarea adresei unei variabile registru.
Operatorul unar * testeaz operandul su ca adresa ultimului semnal i acceseaz
aceast adresa pentru a aduce coninutul locaiei de la adresa respeciv. Astfel, dac y este tot
un int
y = *px
asigneaz lui y, ori de cte ori este cazul coninutul locaiei unde pointeaz px. Astfel,
secvena
px = &x;
y = *px;
asigneaz lui y aceai valoare ca i
y=x
Totodat este necesar declararea variabilelor care apar n secven:
int x, y;
int *px;
Declararea lui x si y este deja cunoscuta. Nou este declararea pointerului px
int *px
aceasta este interpretat ca o mnemonic: nseamn c *px este un int, adic n momentul n
care px apare n context sub forma *px, este echivalent cu a ntlni o variabil de tip int. De
fapt, sintaxa declarrii unei variabile imit sintaxa expresiilor n care ar putea s apar
respeciva variabil. Acest raionament este util n toate cazurile care implic declaraii
complicate. De exemplu:
double atof(), *dp;
spune c ntr-o expresie atof() i *dp au valoare de tip double.
De notat declaraia implicit, ceea ce vrea s nsemne c un pointer este constrns s pointeze
o anumita categorie de obiecte. (Funcie de tipul obiectului pointat).
Pointerii pot aparea n expresii. De exemplu, dac px pointeaz pe ntregul x atunci *px poate
aprea n orice context n care ar putea apare x.
y = *px + 1
d lui y o valoare egala cu x plus 1.
printf("%d\n", *px)
40
41
schimba(x, y) /* GRESIT */
int x, y;
{
int temp;
temp = x;
x = y;
y = temp;
}
Din cauza apelului prin valoare, schimba nu poate afecta argumentele a i b n rutina
care o apeleaz.
Din fericire, exist o modalitate de a obine efectul dorit. Programul apelant trasmite
pointeri pe valorile care trebuie schimbate.
swap(&a, &b);
Din moment ce operatorul & d adresa unei variabile, &a este un pointer pe a. n swap nsi,
argumentele sunt declarate ca fiind pointeri iar adevraii operanzi sunt accesai prin ei ( prin
pointeri).
swap(px, py) /* interschimba *px i *py */
int *px, *py;
{
int temp;
temp = *px;
*px = *py;
*py = temp;
}
O utilizare comun a argumentelor de tip pointer se ntlnete n cadrul funciilor care
trebuie s returneze mai mult dect o singura valoare. (Vei putea obiecta c swap returneaz
dou valori, noile valori ale argumentelor sale.) Ca un exemplu s lum o funcie getint care
realizeaz inversia la intrare prin transformarea unui ir de caractere n valori ntregi, un ntreg
la fiecare apel, getint trebuie s returneze valoarea gsit sau semnul de sfrit de fiier atunci
cnd s-a terminat irul de caractere de la intrare. Aceste valori trebuie s fie returnate ca
obiecte separate, pentru indiferent ce valoare este utilizat pentru EOF aceasta putnd fi
deasemenea valoarea unui ntreg-input.
O soluie, care este bazat pe funcia input scanf, este de a folosi getint care s
returneze ca valoare o funcie EOF, atunci cnd se ntlnete sfritul de fiier; orice alt
valoare returnat nseamn c a fost prelucrat un ntreg obinuit. Valoarea numeric a
ntregului gsit este returnat printr-un argument care trebuie s fie pointer pe un ntreg.
Aceast organizare separ starea de sfrit de fiier de valorile numerice.
Urmtoarea bucl completeaz un tablou cu ntregi prin apeluri la get int.
int n, v, array[SIZE]
for (n = 0; n < SIZE && getint(&v) != EOF; n++)
array[n] = v;
Fiecare apel pune pe y pe urmtorul ntreg gsit la intrare. De notat faptul c este esenial a
scrie &y n loc de y, ca arg al lui getint. A scrie doar y constituie eroare de adresare, getint
susinnd c are de a face cu un pointer propriu zis.
nsi getint este o modificare evident a lui atoi.
42
43
Dac pa pointeaz pe un element oarecare al lui a, atunci prin definitie pa+1 pointeaz
pe elementul urmtor i n general pa-i pointeaz cu i elemente naintea elementului pointat de
pa iar pa+i pointeaz cu i elemente dup elementul pointat de pa. Astfel, dac pa pointeaz pe
a[0]
*(pa + 1)
refer coninutul lui a[1], pa + i este adresa lui a[i] i *(pa+i) este coninutul lui a[i].
Aceste remarci sunt adevarate indiferent de tipul varaiabilelor din tabelul a. Definiia
"adunrii unitii la un pointer " i prin extensie, toata aritmetica pointerilor este de fapt
calcularea prin lungimea n memorie a obiectului pointat. Astfel, n pa+i, i este nmulit cu
lungimea obiectelor pe care pointeaz pa nainte de a fi adunate la pa.
Corespondena ntre indexare i aritmetica pointerilor este evident foarte strns. De
fapt, referina la un tablou este convertit de ctre compilator ntr-un pointer pe nceputul
tabloului. Efectul este c numele unui tablou este o expresie pointer.
Aceasta are cteva implicaii utile. Din moment ce numele unui tablou este sinonim cu locaia
elementului su zero, asignarea
pa = &a[0]
poate fi scris i,
pa = a
nca i mai surprinztor la prima vedere este faptul c o referin la a[i] poate fi scris
i ca *(a+i). Evalund pe a[i], C l convertete n *(a+i); cele dou forme sunt echivalente.
Aplicnd operatorul & ambilor termeni ai acestei echivalene, rezult c &a[i] este identic cu
a+i: a+i adresa elementului al i-lea n tabloul a. Reciproc: dac pa este un pointer i el poate fi
utilizat n expresii cu un indice, pa[i] este identic cu *(pa+i).
Trebuie inut seama de o diferen ce exist ntre numele tablou i un pointer. Un
pointer este o variabil, astfel c pa=a i pa++ sunt operaii. Dar, un nume de tablou este o
constant, nu o variabil: construcii ca a=pa sau a++ sau p=&a sunt interzise. Atunci cnd se
transmite un nume de tablou unei funcii, ceea ce se transmite este locaia de nceput a
tabloului. n cadrul funciei apelate acest fapt argument este o variabil ca oricare alta astfel
nct un argument nume de tablou este un veritabil pointer, adic o variabil coninnd o
adres. Putem folosi acest lucru pentru a scrie o nou versiune a lui strlen, care calculeaz
lungimea unui ir.
strlen(s) /* returneaz lungimea sirului s */
char *s
{
int n;
for (n = 0; *s != '0'; s++)
n++;
return(n);
}
Incrementarea lui s este perfect legal deoarece el este o variabil pointer; s++ nu are efect pe
irul de caractere n funca care a apelat-o pe strlen, dar incrementeaz doar copia adresei. Ca
parametri formali n definirea unei funcii
char s[]
44
i
char *s;
sunt echivaleni; alegerea celui care trebuie scris este determinat n mare parte de expresiile
ce vor fi scrise n cadrul funciei. Atunci cnd un nume de tablou este transmis unei funcii,
aceasta poate, dup necesiti s-o interpreteze ca tablou sau ca pointer i s-l manipuleze n
consecin. Funcia poate efectua chiar ambele tipuri de operaii dac i se pare potrivit i
corect.
Este posibil i transmiterea catre o funcie doar a unei pari dintr-un tablou prin transmiterea
unui pointer pe nceputul subtabloului. De exemplu, dac a este un tablou;
f(&a[2])
i
f(a + 2)
ambele transmit funciei f adresa elementului a[2] deoarece &a[2] i a+2 sunt expresii pointer
care refer al treilea element al lui a. n cadrul lui f, declarea argumentului poate citi
f(arr)
int arr[];
{
...
}
sau
f(arr)
int *arr;
{
...
}
Astfel, dup cum a fost conceput funcia f faptul c argumentul refer de fapt o parte a unui
tablou mai mare nu are consecine.
45
Aceasta nseamn c memoria gestionat de alloc i free este o stiv sau o list prelucrabil n
regim LIFO.
Biblioteca standard C este prevzut cu funcii analoage care nu au att de multe
restricii. Exist multe aplicatii care au realmente nevoie de canalul alloc pentru a dispensa
mici poriuni de memorie, de lungimi neprevzute la momente neprevzute.
Cea mai simpl implementare este de a scrie alloc pentru declararea de pri ale unui
tablou mare pe care l vom numi allocbuf. Acest tablou este propriu lui alloc i free. Lucrnd
cu pointeri, nu cu indici, n tablou nu este necesar ca vreo alt rutinas cunoasca numele
tabloului, care poate fi declarat static, adic local fiierului surs care susine pe alloc i free
numele tabloului fiind invizibil n afara acestui fiier.n implementrile practice tabloul poate
chiar s nu aib nici un nume, el putnd fi obinut prin cererea ctre sistemul de operare a unui
pointer pe un bloc de memorie fr nume.
O alt informaie necesar este legat de ct anume din allocbuf a fost folosit. Vom
utiliza un pointer pe urmtorul element liber, numit allocp. Cnd este apelat alloc pentru n
caractere, el verific dac exist suficient loc eliberat n allocbuf. Dac astfel alloc returneaz
valoarea curent a lui allocp (adic nceputul blocului liber) atunci aceast valoare este
incrementat cu n n asa fel nct allocp s pointeze pe nceputul urmtoarei zone libere.
Free(p) pune pur i simplu pe allocp pe p dac p este n interiorul lui allocbuf.
#define NULL 0 /* val pointerului n caz de eroare */
#define ALLOCSIZE 1000 /* lung spatiului disponibil */
static char allocbuf[ALLOCSIZE]; /* memorie pentru alloc*/
static char *allocp = allocbuf; /*memorarea parti libere*/
char *alloc(n) /* pointer de return pe n caractere */
int n;
{
if (allocp + n <= allocbuf + ALLOCSIZE)
{
allocp += n;
return(allocp - n); /* vechiul p */
}
else /* nu-i destul loc */
return(NULL)
}
free(p) /* zona de memorie libera pointata de p */
char *p;
{
if (p >= allocbuf && p < allocbuf + ALLOCSIZE)
allocp = p;
}
Cteva explicaii. n general un pointer poate fi iniializat ca orice alt variabil, dei n mod
normal singurele valori semnificative sunt NULL sau o expresie care opereaz adrese ale unor
date n prealabil definite, de tip specificat. Declaraia
static char *allocp = allocbuf;
definete pe allocp ca fiind un pointer pe caractere i l iniializeaz pentru a-l pointa pe
allocbuf care este urmtoarea poziie liber atunci cnd ncepe programul. Aceasta stare ar
putea fi scrisa i astfel
static char *allocp = &allocbuf[0];
46
Testul
if (allocp + n <= allocbuf + ALLOCSIZE)
verific dac este suficient loc pentru a satisface cererea pentru n caractere. Dac exist loc,
noua valoare a lui allocp va fi cel mult mai departe de sfritul lui allocbuf. Dac cererea
poate fi satisfacut, alloc returneaz un pointer normal (observai declaraia funciei). Dac
nu, alloc trebuie s returneze un semnal care s semnifice c nu exist spaiu liber. Limbajul C
garanteaz c nici un pointer care pointeaz o dat valid nu va conine zero, asa c valoarea
zero returnat poate fi utilizat ca semnal de eveniment anormal, nu exist spaiu liber. Se
scrie NULL n loc de zero pentru a indica mai clar c aceasta este o valoare special pentru un
pointer. n general ntregii nu pot fi asignai pointerilor; zero este un caz special.
Teste ca
if (allocp + n <= allocbuf + ALLOCSIZE)
i
if (p >= allocbuf && p < allocbuf + ALLOCSIZE)
relev cteva faete importante ale aritmeticii pointerilor.
Mai nti c n unele situaii pointerii pot fi separai. Dac p i q pointeaz pe elemente ale
aceluiai tablou, relaii ca <, >, =, etc. lucreaz exact.
p<q
este adevarat, de exemplu, n cazul n care p pointeaz pe un element anterior elementului pe
care pointeaz q. Relaiile c= i != sunt i ele permise. Orice pointer poate fi testat cu NULL.
Nu exist nicio ans n a compara pointeri n tablouri diferite. n cazul fericit se va obine un
evident nonsens, indiferent de maina pe care se lucreaz. Mai poate s apar situaia
nefericit n care codul va merge pe vreo maina eund "misterios" pe altele.
n al doilea rnd, tocmai s-a observat c un pointer i un intreg pot fi adunai sau sczui.
Instruciunea:
p+n
desemneaz al n-lea obiect dup cel pointat curent de p. Acest lucru este adevrat indiferent
de tipul obiectelor pe care p a fost declarat ca pointer. Compilatorul atunci cnd l ntlnete
pe n, l decaleaz n funcie de lungimea obiectelor pe care pointeaz p, lungime determinat
prin declaraia lui p.
Este valid i scderea pointerilor: dac p i q pointeaz pe elementele aceluiai
tablou, p-q este numrul de elemente dintre p i q. Acest fapt poate fi utilizat pentru a scrie o
nou versiune a lui strlen (evident, deosebit de cea de mai sus).
strlen(s) /* returneaz lungimea sirului */
char *s;
47
{
char *p = s;
while (*p != '\0')
p++;
return(p-s);
}
Prin declarare, p este iniializat pe s, adic s pointeze pe primul caracter din s. n
cadrul buclei while este examinat pe care caracter pn se ntlnete /0 care semnific
sfritul, iar dac while testeaz numai dac expresia este zero, este posibil omiterea testului
explicit, caz n care astfel de bucle sunt scrise adesea
while (*p)
p++;
Deoarece p pointeaz pe caractere, p++ face ca p s avanseze de fiecare dat pe
caracterul urmtor, iar p-v d numrul de caractere parcurse, adic lungimea irului.
Aritmetica pointerilor este consistent: dac am fi lucrat cu float care ocupa mai mult
memorie dect char, i dac p ar fi un pointer pe float, p++ ar avansa pe urmtorul float.
Astfel, vom putea scrie o alt versiune a lui alloc care pstreaz s zicem, float n loc de char,
pur i simplu prin schimbarea lui char n float. n cadrul lui alloc i free. Toate manipularile de
pointeri iau automat n considerare lungimea obiectului pointat n aa fel nct trebuie s nu
fie alterat.
Alte operaii n afara celor mentionate deja (adunarea sau scderea unui pointer cu
un ntreg, scderea sau compararea a doi pointeri): toate celelalte operatii aritmetice cu
pointeri sunt ilegale. Nu este permis adunarea, mprirea, deplasarea logic, sau adunarea
unui float sau double la pointer.
48
Prima funcie este strcpy(s, t) care copiaz irul t n irul s. Argumentele sunt scrise n
aceast ordine prin analogie cu aranjarea, unde cineva ar putea spune
s=t
pentru a asigna pe t lui s. Versiunea cu tablouri este prima:
strcpy(s, t) /*copiaz t n s */
char s[], t[];
{
int i;
i = 0;
while ((s[i] = t[i] != '\0')
i++;
}
Iat o versiune a lui strcpy cu pointeri:
strcpy(s, t) /* copiaz t n s, versiunea pointeri 1*/
char *s, *t;
{
while ((*s = *t) != '\0') {
s++;
t++;
}
}
Deoarece argumentele sunt transmise prin valoare, strcpy poate utiliza s i t n orice fel se
dorete. Aici ei sunt conventional utilizati ca pointeri, care parcurg tablourile pn n
momentul n care s-a copiat \0 sfrit ul lui t, n s.
n practic, strcpy nu va fi scris uzual ca mai sus. O a doua posilitate ar fi:
strcpy(s, t) /* copiaz t n s, versiunea 2*/
char *s, *t;
{
while ((*s++ = *t++) != '\0')
;
}
n aceasta ultim versiune se imit incrementarea lui s i t n partea de test. Valoarea
lui *t++ este caracterul pe care a pointat nainte ca t s fi fost incrementat; prefixul ++ nu-l
schimb pe t nainte ca acest caracter s fi fost adus. n acelasi fel, caracterul este stocat n
vechea poziie s nainte ca s s fie incrementat. Acest caracter este deasemenea valoarea care
se grupeaz cu \0 pentru simbolul buclei. Efectul net este c, caracterele sunt copiate din t n
s, inclusiv sfritul lui \0.
Ca o ultim abreviere vom observa c i gruparea cu \0 este redundant, astfel c
funcia este adesea scris ca
strcpy(s, t) /* copiaz t n s; versiunea pointeri 3 */
char *s, *t;
{
while (*s++ = *t++)
49
;
}
Dei aceast versiune poate prea complicata la prima vedere, aranjamentul ca notaie
este considerat suveran dac nu exist alte raiuni de a-l schimba astfel c l vei ntlni
frecvent n programele C.
A doua rutin este strcmp(s, t) care compar irurile de caractere s i t i returneaz
negativ, zero sau pozitiv n funcie de relaia dintre s i t, care poate fi: s<t, s=t sau s>t.
Valoarea returnat este obinut prin scderea caracterului de pe prima poziie unde s difer de
t.
strcmp(s, t)
/* returneaz <0 dac s<t, 0 dac s==t, >0 dac s>t */
char s[], t[];
{
int i;
i = 0;
while (s[i] == t[i])
if (s[i++] == '\0')
return(0);
return(s[i] - t[i]);
}
Versiunea cu pointeri a lui strcmp:
strcmp(s, t) /* returneaz <0 dac s<t, 0 dac s==t,
>0 dac s>t */
char *s, *t;
{
for ( ; *s == *t; s++, t++)
if (*s == '\0')
return(0);
return(*s - *t);
}
Dac ++ i -- sunt folosii altfel dect operatori prefix sau postfix pot apare alte combinaii de
* i ++ i --, dei mai puin frecvente. De exemplu:
*++p
incrementeaz pe p nainte de a aduce caracterul pe care pointeaz p.
*--p
decrementeaz pe p n acelai condiii.
4.2. Tablouri
Tabloul este o colecie de date n care fiecare element poate fi identificat pe baz unui
index, colecia asigurnd timp de acces constant pentru fiecare element. Prin reprezentarea
50
t[0]
t[1]
t[2]
t[n-1]
4.3. Liste
O list este o mulime de obiecte, numite atomi, pentru care este definit o ordine:
a1 a 2 a 3 a 4 a 5 ... a n
Operaiile principale care se pot se face n cadrul listei:
inserare: introducerea unui nou element ntr-o anumit poziie;
tergere: scoaterea unui element dintr-o anumit poziie;
consultare: accesul asupra fiecarui element din lista;
parcurgere.
Tipurile speciale de liste sunt stivele i cozile
Stive
O stiva este o list n care operaiile de inserare, tergere i consultare se efectueaz
asupra unui capt al listei. Stiva se poate asemna cu un recipient n care se pune i scoate
diferite obiecte. Operaia care pune obiectele n stiv se numete push, iar cea care scoate
obiecte din stiv se numete pop. Captul accesibil pentru stiv se numete vrful stivei:
Aadar:
push insereaz un element n vrful stivei;
pop terge un element din vrful stivei;
top consulta (citete) elementul din vrful stivei;
top(S) citete vrful stivei.
push
pop
51
Cozi
O coad este o list n care inserarea se face la un capt (la sfrit), iar tergerea se
face de la cellalt capt al cozii (de la nceput). Partea din fa a cozii (a primului element) se
numete front, iar partea din spate (a ultimului element) se numete end.
Operaia de inserare n coada add (put)
Operaia de tergere din coada del (get)
add
del
a1
a 2 a3
... an //////
se face cu deplasare de o poziie la stnga din punctul n care dorim s inserm (pentru a face
astfel loc noului element).
Deplasarea se face nspre zona de memorie liber (cea haurat) presupunem c
dorim s inserm pe a n poziia i):
a1
a2
... ai-1
Presupunnd acum haurat corpul de elemente din list i nehaurat zona de memorie
liber, inserarea s-ar putea figura astfel:
/////////////////////////////
//////////
/////////////////
///////////////////////////////////
tergerea: deplasarea cu o poziie la stnga din acel punct.
a1
a2
a3
cap de lista
Capul de list este un pointer separat care duce la primul element din list, iar 0 este
pointer-ul nul (NULL) cu valoare zero. La implementarea listei nlnuite concentrarea se face
la fluxul instruciunilor, nu la declaraiile de variabile.
n programe vom utiliza urmtoarele notaii:
x adresa unui element din list, deci un pointer;
data(x) atomul memorat n elementul de list indicat de x;
link(x) informaia de legatura memorata n elementul de list indicat de x, adic
adresa elementului urmtor;
y = get_sp() y (de acelai tip cu x) primete adresa unei zone de memorie n care se
poate memora un element din list (get space sau alocare de memorie cnd este vorba de
pointer);
ret_sp(x)
eliberez memoria ocupat de elementul de list indicat de x (din
momentul respeciv acolo se poate memora altceva).
Un element de list va fi o astfel de structura:
struct Element {
Atom data;
Element* link;
};
Se va scrie:
tipul lui x
data(x)
link(x)
y = get_sp()
ret_sp()
---------------- Element* x
---------------- x data
---------------- x link
---------------- y = new Element
---------------- delete x
Inserarea
Inserarea se face:
- n fa, sau
- n interior (la mijloc ori la sfrit)
a)
Inserarea n fa
53
a1
a2
1
1
2
a0
x
1 - Prima atribuire: link(x) = l
2 - A douatribuire: l = x
Observaie: Dac lista este vid, l are valoarea 0 (capatul listei) iar atribuirile de mai
sus ramn valabile:
1
a0
a0
x
1
x
b)
Inserarea la mijloc
ai-1
ai+1
ai
2
x
Analog pentru inserarea la sfrit.
1 - Prima atribuire: link(x) = link(y)
2 - A douatribuire: link(y) = x
2.a)
54
1
a1
a2
2
1 - Prima atribuire: p = l
2 - A douatribuire: l = link(l)
3 - ret_sp(p)
Sau, tergerea din fa s-ar mai putea reprezenta astfel:
Situaia iniial:
cap
Situaia final:
P
1
cap
(1)
p = cap;
(2)
cap = cap link;
delete p ;
// Elibereaz zona de memorie
Elementul care a fost izolat de list trebuie s fie procesat n coninuare, cel puin
pentru a fi eliberat zona de memorie pe care o ocup, de aceea adresa lui trebuie salvat (s
zicem n variabil pointer p).
2.b)
Situaia final:
55
(1)
(2)
p = q link;
q link = p link;
delete p;
Observaii:
Atunci cnd q indic penultimul element dintr-o list, atribuirile de mai sus
funcioneaz corect i terg ultimul element din list.
Nu se poate face tergerea elementului indicat de q fr parcurgerea listei de la capt.
4.3.2. Alte consideraii asupra operaiei de inserare ntr-o list nlnuit
Inserarea presupune deci adugarea unui element ntr-o poziie specificat n list. Exist
posibiliti diferite de a specifica poziia n care vrem s inserm elementul:
Situaia n care poziia de inserat este dat printr-un numr care s indice al ctelea
element trebuie s fie n list elementul inserat;
Situaia n care poziia de inserat este dat prin valoarea atomului dup care sau nainte de
care se face inserarea;
Situaia n care poziia de inserat poate fi dat implicit prin valoarea atomului de inserat.
Inserarea n faa unui element specificat
Funcia nscrie un element n fa altui element dintr-o list:
insert (l, a, b)
// l list (pointer la primul element)
// a valoarea atomului de inserat
// b valoarea atomului n fa cruia se insereaz
{
p=get_sp();
data(p)=a;
if (l==0) or (data(l)==b) then
{
link(p)=l;
l=p;
}
else
{
q=l;
while
data(link(q)!=b))
((link(q)!=0)and
do q=link(q);
link(p)=link(q);
56
link(q)=p;
}
}
Operaia de tergere dintr-o list nlnuit
Operaia delete terge un atom dintr-o list. Deci vom avea n pseudocod, o funcie de
forma:
delete(l, a)
// l
// a
list
valoarea atomului care trebuie ters
{
if l=0 then eroare ("Atomul nu se afla n list")
else if data(l)=a then | p=1
| l=link(l)
|_ ret_sp(p)
else | q=l
|
while(link(q)!
=0)and(data(link(q))!=a) do
|
q=link(q)
| if link(q=0) then eroare("S-a
ajuns la sfrsitul listei i atomul nu a fost gsit")
| else | p=link(q)
|
| link(q)=link(p)
|_
|_ ret_sp(p)
}
Operaia de parcurgere a listei nlnuite
Operaia de parcurgere a listei nlnuite const dintr-o secven de instruciuni care se
folosete de fiecare dat cnd dorim s prelucram elementele listei ntr-un anumit scop.
O parcurgere a listei presupune o prelucrare efectuat asupra fiecarui element din list
(aadar nu o funcie, ci o secven de instruciuni):
Fie p pointer-ul care indic pe rnd fiecare element al listei, i considerm ca p ncepe
cu l:
while (p!=0) do
57
Dac STACK este de tip stiv i ATOM tipul obiectelor coninute n stiv atunci
operaiile care definesc tipul structura de stiv pentru tipul STACK sunt:
CREATE() STACK
Operaia CREATE nu primete parametri, creeaz o stiv care pentru nceput este vid
(nu conine nici un obiect).
PUSH(STACK, ATOM) STACK
Operaia PUSH primete ca parametri o stiv i un obiect i produce stiv modificat
prin adugarea obiectului n stiv.
POP(STACK) STACK, ATOM
Operaia POP primete ca parametri o stiv pe care o modific scond un obiect. De
asemenea produce ca rezultat obiectul scos din stiv.
TOP(STACK) ATOM
Operaia TOP ntoarce ca rezultat obiectul din vrful stivei pe care o primete ca
parametru.
ISEMPTY(STACK) boolean
Operaia ISEMPTY este folosit pentru a testa dac stiv este vid.
Facem notaiile:
S
stiv
S.vect vectorul n care se reprezint elementele stivei S
S.sp indicele vrfului stivei
Elementele sunt memorate aadar unul dup altul n vectori, nefiind neaparat n ordine
cresctoare. Zona de memorat trebuie s conin aceste dou informaii: S.vect i S.sp grupate
ntr-o structur:
struct Stack {
int sp;
Atom vect [DIMMAX]
};
Condiia de stiv vid este: S.sp=0
Se scrie:
push(S,a)
{
if S.sp >=DIMMAX then eroare("Stiv plina")
else | S.sp=S.sp+1
|_ S.vect[S.sp]=a
poziie
}
Funcia pop scoate un element din stiv:
pop(S)
{
if S.sp=0
}
Observaie: Se obinuiete ca pe lng tergerea elementului, funcia pop s returneze
elementul scos din list.
58
top(S)
{
if S.sp=0
}
Funcia isEmpty(S) testeaz condiia stiv vid:
isEmpty(S)
{
return(S.sp==0)
}
//legatura
};
typedef Element* Stack;
Fie S pointer-ul la primul element din nlnuire, se echivaleaz tipul Stack cu typedef
Element* Stack, iar condiia de stiv vid este S=0 :
push(S,a)
{
p=get_sp()
data(p)=a
link(p)=S
S=p
}
pop(S)
{
if S=0 then eroare("Stiv vid")
else | p=S;
| S=link(S)
|_ ret_sp(p)
}
top(S)
{
59
GET
ultimul
primul
head
tail
}
Funcia get scoate un element din coad i-l returneaz:
get(C)
{
if C.head=C.tail
}
isEmpty(C)
{
return(C.head==C.tail)
}
Cozi ordonate circulare
Pentru a obine o coad circular vom porni de la o coad liniar simpl (cu doi
indicatori) i vom face n aa fel nct la incrementarea indicatorilor head i tail, cnd acetia
ating ultima poziie din vector s se coninue cu prima poziie din vector.
Funcia urmtoare poate realiza aceasta cerin:
int nextPoz(int index)
{
if (index<DIMVECTOR-1) return index+1;
else return 0;
}
unde DIMVECTOR este dimensiunea vectorului n care se memoreaz elementele cozii.
Coninutul cozii va arta aa:
61
head
tail
sau aa:
5
tail
head
tail
head
head
tail
put(C,a)
{
if C.head=inc(C.tail) then eroare("Coad plina")
else | C.vect[C.tail]=a
|_ C.tail=inc(C.tail)
}
get(C)
{
if C.head=C.tail
head
tail
| C.head= p
|_ C.tail= p
| link(C.tail)= p
|_ C.tail= p
}
Funcia get scoate un element din poziia fa:
get(C,a)
{
if C.head= 0
}
Funcia front returneaz elementul din fa cozii, fr a-l scoate din coad.
front(C)
{
if C.head=0
}
isEmpty(C)
{
return(C.head=0)
}
Exist aici un element de redundan: ar fi convenabil s nu mai avem spaiu
suplimentar de memorare, ci, s avem un singur pointer ca s putem manevra coada. De aceea
apar utile cozile nlnuite circulare.
Cozi nlnuite circulare
Dac reprezentm coad printr-o structura nlnuit circulara va fi nevoie de un
singur pointer prin intermediul cruia se pot face ambele operaii de adugare i tergere din
coad:
64
ultimul
primul
.....
tail
Fie:
C
pointer la ultimul element din coad
link(C) pointer la primul element din coad
Operaiile de plasare i de scoatere din coad, sunt:
put(C,a)
{
p= get_sp()
data(p)=a
if C=0 then
else
| C= p
|_ link(C)= p
| link(p)= link(C)
| link(C)= p
|_ C= p
}
get(C)
{
if C= 0 then eroare("Coad vid")
else if C=link(C) then| a= data(C)
| ret_sp(C)
| C= 0
|_ return(a)
else | {p= link(C)
| link(C)= link(p)
| a= data(p)
| ret_sp(p)
|_ return(a)
}
front(C)
isEmpty(C)
returneaz data(link(C))
retuneaz condiia C=0.
0
B:
C:
0
0
66
D:
A:
0
B:
_
C
C:
Funcia del ( ) trebuie s in seama de existena unor liste comune. Deci, este necesar
pstrarea n elementul ce conine numele listei A i a unui indicator care s contorizeze
numrul de referine ale lui.
Exemplu:
A
2
Numai dac acest indicator este 0, se face tergerea efeciv a listei.
Copy (l)
{
// l - list nlnuit
if (l = 0)
}
Copy (l)
{
// l - list generalizata
if (l = 0)
}
Funcia pentru testarea egalitii este:
isEqual (l1,l2)
{
}
isEqual (l1,l2)
{
while(p1 0 and p2 0)
remove (S)
- extrage din structur atomul cu cheia cea mai mare.
O coad cu prioriti poate fi implementat printr-o list. Implementarea cozii cu
prioriti prin list permite definirea operaiilor insert i remove, n cazul cel mai bun, una este
de complexitate O(1) i cealalt este de complexitate O(n).
Implementarea cozii cu prioriti prin heap face o echilibrare cu complexitatea
urmtoare: una este de complexitate 0(log n) i cealalt de complexitate 0(log n).
Operaia de inserare
/ \
/ \
/ 50 \
/ / \ \
/ 40
30 \
/ / \
/ \ \
/ 33 37 12 2 \
/ / \ / _________\
/ 10 15 7 | 42
-----------------|
heap:
40
30
33
37
12
10
15
42
Operaiile insert i remove pentru arbori heap au o forma foarte simpl cnd utilizeaz
reprezentarea implicit. Considerm, n coninuare, arbori heap n reprezentare implicit.
Exemplu:
un arbore cu ultimul nivel avnd toate nodurile aliniate la stnga:
Inserm valoarea 42 se adaug nodul la un nivel incomplet;
n reprezentarea implicit se adaug nodul la sfrit.
insert:
1)
n reprezentarea implicit:
V [N + 1] = a
N=N+1
n coninuare reorganizm structura arborelui astfel nct s-i pstreze structura de
heap.
2)
Se utilizeaz interschimbrile. Comparaii:
Iau 2 indici:
child = N
i
parent = [N/2]
(n cazul nostru N = 11 i [N/2] = 5)
69
3)
4)
Operaia insert:
insert(V, N, a) // V
// N
(Funcia
// a
{
N = N+1
V[N] = a
child = N
parent = [N/2]
while | parent 1 do
| if key(V [child]) > key(V [parent]) then
| interchange (V [child],V [parent])
|
| child = parent
|
|_ parent = [child/2]
|_ else break // parasim bucla parent = 0
}
Operaia remove:
50
/ \
45
43
/ \ / \
33 40 40 20
/ \ / \
\
10 15 7 37 39
se scoate elementul cel mai mare care este rdcina heap-ului; se iniializeaz cei 2
indici;
70
Condiia de heap:
parent
/ \
lchild rchild
heap
max
min
(i 1) 2i 1
i 2
72
S artm:
T ( n)
k 1
i 21
i 1
cu tehnica
T ( n) 2 T ( n) T ( n) .
Asadar:
T ( n) 2
k 1
k 1
k 1
i 1
i 1
4
i 1
k 1
i 2i i 2i i 2i 1 i 2i
1 2 2 2 3 2 ... ( k 2 ) 2
2 ( k 1) 2 k
k 1
( k 1) 2 k 1 21 2 22 3 23 ... ( k 1) 2 k 1
2i ( k 1) 2 k 2 20 21
i 2
k
i 1
k 1
k 1
2i
i 0
( k 1) 2 1 ( 2 1) ( k 2 ) 2 2
Rezult:
T ( n ) ( k 2 ) 2 k 2 ( k 2 ) ( 2 k 1) k 2 2 n ( k 2 ) k
iar:
k log2 ( n 1) ,
din
n 2k 1
Rezult:
T ( n ) n (log2 ( n 1) 2 ) log2 ( n 1)
-----------------------termen dominant
Fcndu-se majorri, rezult complexitatea O(nlog n).
Prezentm acum alt strategie de obinere a heap_gen cu o complexitate mai bun:
Construim heap-ul de jos n sus (de la dreapta spre stnga). Cele mai multe noduri sunt
la baz, doar nodurile din vrf parcurg drumul cel mai lung.
II
noduri terminale
73
T ( n)
k 1
( k i ) 2i 1
i 1
T ( n) 2 T ( n) T ( n)
T (n)
k 2
( k 1) 2i
i 1
k 2
( k i ) 2i 1 ( k 1) 21 ( k 2) 22 ( k 3) 23 ... 3 2k 3 2 2k 2
i 1
( k 1) 20 ( k 2 ) 21 ( k 3) 22 ... 2 2 k 3 2 2 k 2 ( k 1)
k 3
i 1
k 1
k 2
2 ( k 1) 2
k 2
( 2 1) k 1 3 2
k 2
Rezult:
74
k 1
21 2 k 1 ( k 1) 20
k 3
21
i 0
T ( n ) 3 2 k 2 k 1 3 ( 2 k 1) k 1
T ( n ) 3 n log2 ( n 1) 1
------termen dominant
Rezult: complexitatea este O(n). Comparnd cu varianta anterioar, n aceast
variant (cu heap-ul la baz) am ctigat un ordin de complexitate. Rezult, complexitatea
algoritmului Heap_Sort este determinat de funciile remove ce nu pot fi aduse la mai puin de
complexitate O(log n). Rezult:
Heap_Sort = O(n) + O(nlog n)
--------------termen ce determin complexitatea
Rezult complexitatea algoritmului
Heap_Sort = O(nlog n)
4.4. Fiiere
Un fiier este o colecie ordonat de articole (nregistrri) pstrate pe un suport extern
de memorie i identificate printr-un nume. n C, pentru fiierul standard de intrare, datele
sunt introduse de la tastatur iar pentru fiierul standard de ieire, rezultatele sunt afiate pe
terminalul standard de ieire.
Mesajele de eroare se afieaz n fiierul standard de eroare.
Fiierul are un articol care marcheaz sfritul fiierului.
Not: Pentru fiierul standard de intrare de la tastatur, sfritul de fiier, pentru sistemele de
operare DOS i Windows se genereaz prin Ctrl-Z (pentru Unix prin Ctrl-D).
Operaiile specifice prelucrrii fiierelor sunt.
deschiderea unui fiier
ntr-un fiier text spaiul de memorare pe disc nu este folosit n mod eficient pentru datele
numerice (astfel ntregul 12345 ocup 5 octei).
ntr-un fiier binar, datele sunt pstrate n formatul lor intern (2 octei pentru int, 4 octei
pentru float, etc).
La fiierele text marcajul de sfrit de fiier (caracterul 0X1A) exist fizic n fiier. La
ntlnirea acestui caracter funcia fgetc() ntoarce EOF (-1). Marcajul de sfrit de fiier se
genereaz de la tastatur prin Ctrl-Z.
n cazul fiierelor binare, marcajul de sfrit de fiier nu exist fizic n fiier, ci este generat
de funcia fgetc().
n MSDOS (i n Unix), la nivelul liniei de comand intrrile i ieirile standard pot fi
redirectate n fiiere disc, fr a opera nici o modificare la nivelul programului. Astfel:
< redirecteaz intrarea standard ctre fiierul specificat
> redirecteaz ieirea standard ctre fiierul specificat
Fiierul standard de eroare nu poate fi redirectat.
Fiierul specificat poate fi:
con pentru consola sistem (tastatura, respeciv ecranul)
prn pentru imprimanta paralel
com1 pentru interfaa serial de date
nume_fiier pentru un fiier disc
NUL pentru perifericul nul.
4.4.2 Accesul la fiiere.
Fiierele disc i fiierele standard sunt gestionate prin pointeri la structuri specializate
FILE, care se asociaz fiecrui fiier pe durata prelucrrii.
Fiierele standard au pointerii predefinii: stdin, stdout, stderr, stdprn, stdaux.
Declararea unui pointer la fiier se face prin:
FILE *pf;
Deschiderea:
nainte de a fi prelucrat, un fiier trebuie s fie deschis. Prin deschidere:
- se asociaz unui nume de fiier un pointer la fiier
- se stabilete un mod de acces la fiier
Exemplu: FILE *fopen(char *nume_fiier, char *mod_acces);
-
Prin deschiderea unui fiier se stabilete o conexiune logic ntre fiier i variabila pointer
i se aloc o zon de memorie (buffer) pentru realizarea mai eficient a operaiilor de
intrare / ieire. Funcia ntoarce:
un pointer la fiier, n caz c deschiderea fiierului se face n mod corect
NULL dac fiierul nu poate fi deschis.
Vom considera mai nti dou moduri de acces :
citire (sau consultare) r citirea dintr-un fiier inexistent va genera eroare
scriere (sau creare) w - dac fiierul exist deja, el va fi ters
Fiierele standard nu trebuiesc deschise.
nchiderea:
Dup terminarea prelucrrilor asupra unui fiier, acesta trebuie nchis. Un fiier este
nchis automat la apelarea funciei exit().
Exemplu: int fclose(FILE *pf);
Revenim asupra modurilor de acces la disc. Sunt posibile urmtoarele situaii:
1.
fiierul nu exist; dorim s-l creem i s punem informaii n el
w - deschidere pentru scriere, noile scrieri se fac peste cele vechi
76
2.
Exemplu:
Obinerea unei situaii cu mai multe grade de total.
Pentru aceasta se stabilesc cmpuri, numite caracteristici de grupare sau caracteristici de
control, asociate gradelor de total. O caracteristic de control este un cmp al articolului din
fiierul de date, care are aceeai valoare pentru mai multe nregistrri. Astfel, articolele care
au valoare comun pentru o caracteristic de grupare se pot ordona pe submulimi, formnd o
grup de control.
Fiierul poate constitui, n ansamblul su, caracteristica de grupare de cel mai nalt
nivel, pentru care se poate calcula totalul general. Numrul maxim de grade de total este
superior cu unu numrului de caracteristici de control stabilite.
ntre caracteristicile de grupare se stabilete o relaie de ordine ierarhic. Pentru prelucrarea
fiierului, cu utilizare minim de memorie, articolele trebuie sortate dup caracteristicile de
control. Acest tip de prelucrare intr n categoria consultrilor secveniale integrale i urmeaz
algoritmul de principiu din figurile 1.3 sau 1.4. Prelucrarea unui fiier sortat dup criteriile
enunate, presupune existena unor operaii standard, executate la schimbarea valorii fiecrei
caracteristici de control stabilite:
operaii iniiale ale unei grupe de control prin care se iniializeaz variabila de total
specific grupei; se salveaz valoarea caracteristicii primului articol din grup; alte
operaii iniiale specifice grupei;
operaii finale ale unei grupe de control prin care se afieaz totalul calculat pentru
caracteristica ce se schimb; se cumuleaz totalul grupei curente la totalul grupei
ierarhic superioar;
alte operaii finale specifice grupei;
condiia de prelucrare a unei grupe de control conine, pe lng condiia specific,
toate celelalte condiii din amonte.
Raportul final este listat la imprimant, fie direct, ca fiier de ieire, fie creat pe suport
magnetic, ca fiier text, n vederea imprimrii ulterioare. Structura unei pagini a raportului i
controlul trecerii la o nou pagin trebuie asigurate de programator.
n coninuare se prezint structura de principiu a unui program de obinere a unui raport final,
cu control dup dou caracteristici i trei grade de total, unde cmp_1 i cmp_2 sunt
caracteristicile de control (cmpuri din articol), v1 i v2 sunt variabile de lucru pentru salvarea
caracteristicilor, iar totg, tot1 i tot2 sunt variabile pentru calculul gradelor de total. Analog, se
78
procedure prel_1;
begin
inceput_1;
while (v1=x.camp_1) and not sf do prel_2;
sfarsit_1;
end;
begin
inceput;
while not sf do prel_1;
sfarsit;
end.
Consultarea n acces direct presupune regsirea articolului dup numrul relativ, prin
secvena Seek(f,nr_relativ); Read(f,art). Numrul relativ este furnizat de utilizator i trebuie s
aparin domeniului 0..FileSize(f)-1. Se remarc faptul c dac nr_relativ depete
dimensiunea fiierului, procedura Seek nu genereaz eroare, dar citirea va determina
ntreruperea execuiei programului. Pentru evitarea acestei situaii se va include n program
validarea apartenenei numrului relativ la intervalul acceptat. Algoritmul de consultare n
acces direct a unui fiier are un alt fiier conductor (de exemplu, tastatura).
Exemplu:
............................
begin
(* citire nume fiier extern *)
checkeof:=true; assign(f,nume_fiier); reset(f);
write('nr. relativ: ');
while not eof do
begin
readln(r); {citirea numarului relativ al articolului}
seek(f,r); {$i-} read(f,art); {$i+}
if ioresult = 0 then
(* -----------------------prelucrare articol
Algoritmi i programe de prelucrare a fisierelor
------------------------ *)
else
writeln('Articol inexistent !');
write('Nr. relativ (sau ctrl-z): ')
end;
close(f)
end.
Consultarea n acces mixt utilizeaz o combinaie ntre accesul direct i cel secvenial,
n vederea prelucrrii unui grup de articole, memorate contiguu n fiier i selectabile
printr-o condiie.
Pentru fiierele binare, metoda poate fi aplicat dac se dorete selectarea articolelor
dntre dou limite ale numerelor relative (limita inferioara - li i limita superioara - ls).
Algoritmul trebuie s verifice relaia 0=li=ls<FileSize(f), dup care parcurgerea fiierului
poate fi realizat prin orice tip de structur repetitiv.
Exemplu:
............................
begin
80
Inserarea unor articole. Se aplic n cazul n care articolele sunt scrise n fiier n
ordinea cresctoare (descrescatoare) a valorilor unui anumit cmp. n acest caz, noul articol va
fi inserat ntre dou articole, astfel:
- se caut (cu un algoritm secvenial, binar etc.) pozitia k n care trebuie inserat noul articol;
- se copiaz, glisnd cu o pozitie spre dreapta, toate articolele de la sfritul fiierului pn la
articolul cu numrul relativ k;
- se scrie n acces direct noul articol, n poziia k.
Exemplu:
{ articolele fisierului sunt n ordinea crescatoare a valorii campului 1 }
begin
(* citire nume fiier extern *)
assign(f,nume_fiier);
reset(f);
checkeof:=true;
write('camp 1: ');
while not eof do { se asigura adaugarea mai multor articole }
begin
readln(art_nou.camp_1); { introducerea campului
dupa care sunt sortate articolele }
(* ----------------------------------preluare de la tastatura a celorlalte
campuri din articolul de adaugat
----------------------------------- *)
{ secventa de cautare a pozitiei n care se va insera articolul }
seek(f,0); { pozitionare pe inceput de fiier }
sf:=false;
read(f,art_existent);
while not sf and (art_existent.camp_1<art_nou.camp_1) do
begin
read(f,art_existent);
if ioresult <> 0 then sf:=true
end;
if not sf then
begin
k:=filepos(f)-1; { articolul se va insera n pozitia k }
for i:=filesize(f)-1 downto k do
begin
seek(f,i); read(f,art_existent);
write(f,art_existent)
end
end
else k:=filesize(f); {articolul se adauga la sfarsitul fisierului}
seek(f,k);
write(f,art_nou);
write('camp 1: ')
end;
close(f)
end.
Modificarea valorii unor cmpuri din articol se realizeaz n mai multe etape:
82
83
writeln('cmmdc=',cmmdc(a,b));
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
3. Calcul cmmdc-varianta Euclid recursiv
program cmmdc_euclid_recursiv;
var sf:char;
a,b:integer;
funcion cmmdc(a,b:integer):integer;
begin
if b=0 then cmmdc:=a
else cmmdc:=cmmdc(b,a mod b);
end;
begin
sf := D;
repeat
write('a=');readln(a);
write('b=');readln(b);
write('cmmdc=',cmmdc(a,b));
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
4. Calcul cmmdc-varianta recursiv
program cmmdc_recursiv;
var a,b:longint;
sf:char;
funcion c(a,b:longint):longint;
begin
if a=b then c:=a
else if a>b
then c:=c(a-b,b)
else c:=c(a,b-a);
end;
begin
sf := D;
repeat
write('a=');readln(a);
write('b=');readln(b);
write('cmmdc=',c(a,b));
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
5. Calcul cmmdc pentru n numere
program cmmmdc_n_numere;
const n_max=100;
type vector =array[1..n_max] of word;
var
i,j,c,n:integer;
85
v:vector;
sf:char;
funcion cmmdc(a,b:word):word;
begin
while a<>b do begin
if a>b then a:=a-b
else b:=b-a;
end;
cmmdc:=a;
end;
begin
sf := D;
repeat
write('n='); readln(n);
for i:=1 to n do
begin
write('v[',i,']=');
readln(v[i])
end;
c:=v[1];
for j:=2 to n do c:=cmmdc(c,v[j]);
writeln('cmmdc pt. ',n,' numere=',c);
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
6. Calculul combinrilor- varianta iterativ
program combinari_iterativ;
var sf:char;
k,m,n:word;
p:real;
begin
sf := D;
repeat
write('n='); readln(n);
repeat
write('m='); readln(m)
until m<n;
p:=1;
for k:=1 to m do p:=(n-m+k)/k*p;
writeln('comb=',p:7:0);
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
7. Calculul combinrilor-varianta recursiv
program combinari_recursiv;
var sf:char;
n,m:integer;
86
funcion comb(n,m:integer):integer;
begin
if (m=0) or (n=m)
then comb:=1
else comb:=comb(n-1,m)+comb(n-1,m-1);
end;
begin
sf := D;
repeat
repeat
write('n='); readln(n);
write('m='); readln(m);
until (0<=m) and (m<=n);
writeln('comb=',comb(n,m));
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
8. Rezolvarea triunghiului
program rezolvarea_triunghiului;
const pi=3.14159;
var
x1,x2,x3,y1,y2,y3:integer;
a,b,c,ab,bc,ac:real;
s,p:real;
sf:char;
begin
sf := D;
repeat
writeln('coordonate primului punct');
readln(x1,y1);
writeln('coordonate al doilea punct');
readln(x2,y2);
writeln('coordonate al treilea punct');
readln(x3,y3);
if (x1*(y2-y3)+x2*(y3-y1)+x3*(y1-y3))<>0 then
begin
writeln( Nu formeaz triunghi');
ab:=sqrt(sqr(x2-x1)+sqr(y2-y1));
bc:=sqrt(sqr(x3-x2)+sqr(y3-y2));
ac:=sqrt(sqr(x1-x3)+sqr(y1-y3));
p:=(ab+bc+ac)/2;
s:=sqrt(p*(p-ab)*(p-bc)*(p-ac));
writeln('Aria=',s:2:2);
if (ab=bc)and(bc=ac) then
writeln('triunghi echilateral')
else if (ab=bc)or(bc=ac)or(ac=ab) then writeln ('triunghi
isoscel')
else writeln('triunghi
oarecare');
if(ab*ab+bc*bc=ac*ac) or (ab*ab+ac*ac=bc*bc) or (bc*bc+ac*ac=ab*ab)
then writeln('triunghi dreptunghic');
end
87
88
else d:=d+2;
end;
if n>1 then write(n:5,' ':9,1:2);
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
11. irul lui Fibonacci-varianta recursiv
program fibonacci_recursiv;
var sf:char;
n,i:longint;
funcion fibo(n:longint):longint;
begin
if n<=2 then fibo:=1
else fibo:=fibo(n-1)+fibo(n-2);
end;
begin
sf := D;
repeat
write('n=');
readln(n);
for i:=1 to n do write(fibo(i),' ');
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
12. irul lui Fibonacci-varianta iterativ
program fibonacci_iterativ;
var sf:char;
a,b,c,n:longint;
begin
sf := D;
repeat
write('n=');readln(n);
write(0,' ',1);
a:=0;
b:=1;
while a+b<=n do
begin
c:=a+b;
write(' ',c);
a:=b;
b:=c;
end;
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
89
sf := D;
repeat
write (n=);
readln (n);
mult:=[2..n];
j:=0;
writeln(Numerele prime pana la ,n);
for i:=2 to n do
if i n mult then
begin
write (i:4);
j:=j+1;
k:=2;
while i*k<=n do
begin
mult:=mult-[i*k];
k:=k+1;
end;
end;
writeln;
writeln(Numrul de elemente prime ,j);
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
17. Sume maxime de numere ntregi
program sume_de_numere;
const nmax=100;
type ir=array[1..nmax]of byte;
var
s,a:ir;
i,j,nr,n:byte;
f:file of byte;
l:string[80];
ss:longint;
nume:string[10];
sf:char;
begin
sf := D;
repeat
write('nume fiier input:');
readln(nume);
assign(f,nume);
rewrite(f);
write('dati nr. de linii:');
readln(n);
write(f,n);
for i:=1 to n do
begin
writeln('Linia cu',i:2,' numere');
for j:=1 to i do
begin
92
write(j:3,'. ');
readln(nr);
write(f,nr);
end;
end;
reset(f);
read(f,n);
for i:=1 to nmax do s[i]:=0;
writeln ('sumele partiale sunt:');
for i:=1 to n do
begin
for j:=1 to i+1 do a[j]:=s[j];
read(f,nr);
s[1]:=s[1]+nr;
for j:=2 to i do
begin
read(f,nr);
if a[j-1]<a[j] then s[j]:=a[j]+nr
else s[j]:=a[j-1]+nr;
end;
s[i+1]:=nr;
for j:=1 to i do write(s[j],' ');
writeln;
end;
ss:=s[1];
for j:=1 to i+1 do
if ss<s[j] then ss:=s[j];
writeln('Suma maxima=',ss:5);
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
18. Eliminare elemente-varianta vector logic
program cerc1_varianta_vector_boolean;
const nmax=100;
type nr=1..nmax;
var i,k,n:nr;
j,m:integer;
prezent:array[nr] of boolean;
sf:char;
begin
sf := D;
repeat
write('n='); readln(n);
write('m='); readln(m);
for i:=1 to n do prezent[i]:=true;
i:=n;
for k:=1 to n do begin
for j:=1 to m do
repeat
93
i:=1;
for k:=n downto 1 do begin
i:=(i+m-2) mod k+1;
write(copil[i]:3);
for j:=i to k-1 do
copil[j]:=copil[j+1];
end;
writeln;
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
21. Eliminare elemente-varianta mulime
program cerc4_varianta_multime;
const nmax=100;
type numar=1..nmax;
var
i,n:numar;
j,m:integer;
multime:set of numar;
sf:char;
begin
sf := D;
repeat
write('n='); readln(n);
write('m='); readln(m);
mulime:=[1..n];
i:=n;
while mulime<>[] do begin
for j:=1 to m do
repeat
if i<n then i:=i+1
else i:=1
until i n mulime;
write(i:3);
mulime:=mulime-[i];
end;
writeln;
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
22. Eliminare elemente-varianta alocare dinamic
program cerc5_varianta_alocare_dinamica;
const nmax=100;
type list=^term;
term=record
nr:integer;
next:list;
end;
var i,n:1..nmax;
95
j,m:integer;
prim,p:list;
sf:char;
begin
sf := D;
repeat
write('n='); readln(n);
write('m='); readln(m);
new(prim);
p:=prim;
for i:=1 to n do begin
p^.nr:=i;
if i<n then begin
new(p^.next);
p:=p^.next;
end;
end;
p^.next:=prim;
i:=n;
while i>0 do begin
for j:=1 to m-1 do p:=p^.next;
write(p^.next^.nr:3);
p^.next:=p^.next^.next;
i:=i-1;
end;
writeln;
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
23. Diferena mulimilor alocate static
program diferenta_a_doua_multimi;
const n_max=50;
type vector=array[1..n_max] of integer;
header=string[20];
var a,b:vector;
na,nb:integer;
sf:char;
procedure citire_vector(var v:vector; var n:integer;x:char);
var i:integer;
begin
repeat
write('nr de componente:');
readln(n)
until n n [1..n_max];
for i:=1 to n do begin
write(x,'[',i,']=');
readln(v[i])
end;
writeln;
end;
96
afisare_vector(a,na,10,'First vector:');
writeln;
afisare_vector(b,nb,10,'Second vector:');
writeln;
det_dif(a,b,na,nb,'First\Second:');
writeln;
det_dif(b,a,nb,na,'Second\First:');
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
24. Operaii cu mulimi generate dinamic
program reuniune_i_intersecie_generate_dinamic;
const nmax=100;
type list=^nod;
nod=record
info:integer;
next:list
end;
var a:array[1..nmax]of integer;
l,l1,l2:list;
n,i:integer;
sf:char;
funcion reun(l1,l2:list):list; forward;
funcion inters(l1,l2:list):list;forward;
funcion creal(i,n:integer):list;
var l:list;
begin
if i>n then creal:=nil
else
begin
new(l);
l^.next:=creal(i+1,n);
l^.info:=a[i];
creal:=l
end;
end;
procedure afisl(l:list);
begin
if l<>nil then begin
write(l^.info,' ');
afisl(l^.next)
end
end;
funcion atasare(x:integer;l1,l2:list):list;
var prim:list;
begin
new(prim);
prim^.info:=x;
prim^.next:=reun(l1,l2);
atasare:=prim;
98
end;
funcion atasare1(x:integer;l1,l2:list):list;
var prim:list;
begin
new(prim);
prim^.info:=x;
prim^.next:=inters(l1,l2);
atasare1:=prim;
end;
funcion reun(l1,l2:list):list;
begin
if (l1=nil)and(l2=nil) then reun:=nil
else if l1=nil then
reun:=atasare(l2^.info,nil,l2^.next)
else if l2=nil then
reun:=atasare(l1^.info, l1^.next,nil)
else if l1^.info<l2^.info then
reun:=atasare(l1^.info,l1^.next,l2)
else if l1^.info>l2^.info then
reun:=atasare(l2^.info,l1,l2^.next)
else
reun:=atasare(l1^.info,l1^.next,l2^.next)
end;
funcion inters(l1,l2:list):list;
begin
if (l1=nil)or(l2=nil) then inters:=nil
else if l1^.info<l2^.info then
inters:=inters(l1^.next,l2)
else if l1^.info>l2^.info then
inters:=inters(l1,l2^.next)
else
inters:=atasare1(l1^.info,l1^.next,l2^.next);
end;
begin
sf := D;
repeat
write('prima list, n='); readln(n);
for i:=1 to n do read (a[i]);
l1:=creal(1,n);
writeln;
afisl(l1);
writeln;
write('A doulist, n='); readln(n);
for i:=1 to n do read (a[i]);
l2:=creal(1,n);
writeln;
afisl(l2);
writeln;
l:=reun(l1,l2);
writeln('reuniunea');
afisl(l);
writeln;
99
l:=inters(l1,l2);
writeln('intersecia');
afisl(l);
writeln;
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
25. Ordonare dinamic recursiv ir numeric
program sortare_dinamica_recursiva_prin_separare;
const nmax=100;
type list=^nod;
nod=record
info:integer;
next:list
end;
var
a:array[1..nmax]of integer;
k,n:integer;
l:list;
sf:char;
funcion fuzi(l1,l2:list):list;
begin
if l1=nil then fuzi:=l2
else if l2=nil then fuzi:=l1
else if l1^.info<=l2^.info then
begin
l1^.next:=fuzi(l1^.next,l2);
fuzi:=l1
end
else begin
l2^.next:=fuzi(l1,l2^.next);
fuzi:=l2
end
end;
funcion separ(l:list):list;
var l1:list;
begin
if l=nil then separ:=nil
else if l^.next=nil then separ:=nil
else begin
l1:=l^.next;
l^.next:=l1^.next;
l1^.next:=separ(l1^.next);
separ:=l1;
end;
end;
procedure sortfuzi(var l:list);
var l1:list;
begin
if l<>nil then
100
sf:char;
procedure readp (var p:poli);
var n:0..maxint;
i:integer;
crt:poli;
begin
write('nr. termeni:');
readln(n);
if n=0 then p:=nil
else begin
writeln('introd. coef+exp n ordine descresc:');
new(p);
crt:=p;
for i:=1 to n do begin
with crt^ do read(cf,ex);
if i<n then begin
new(crt^.next);
crt:=crt^.next
end
end;
crt^.next:=nil
end;
end;
procedure adaug(cf:real;ex:integer;var p:poli; var
n:integer);
begin
if n<>1 then p:=p^.next;
n:=n+1;
p^.cf:=cf;
p^.ex:=ex;
new(p^.next)
end;
procedure writep(p:poli);
var crt:poli;
begin
crt:=p;
while crt<>nil do begin
with crt^ do begin
if cf<0 then write('-')
else if cf>0 then write('+');
if (abs(cf)<>1) or (ex=0) then write(abs(cf):2:0);
if ex>0 then write('x');
if ex>1 then write('^',ex:1)
end;
crt:=crt^.next
end;
writeln
end;
procedure sumap(p,q:poli; var sum:poli);
var crt:poli;
n:integer;
102
begin
new(sum);
crt:=sum;
n:=1;
while (p<>nil)and(q<>nil) do
if p^.ex < q^.ex then begin
adaug(q^.cf,q^.ex,crt,n);
q:=q^.next
end
else if p^.ex > q^.ex then begin
adaug(p^.cf,p^.ex,crt,n);
p:=p^.next
end
else begin
if p^.cf+q^.cf<>0 then
adaug(p^.cf+q^.cf,p^.ex,crt,n);
p:=p^.next;
q:=q^.next
end;
while p<>nil do begin
adaug(p^.cf,p^.ex, crt,n);
p:=p^.next
end;
while q<>nil do begin
adaug(q^.cf,q^.ex, crt,n);
q:=q^.next
end;
crt^.next:=nil
end;
procedure prodp(p,q:poli; var mult:poli);
var crt,crtp,crtq:poli;
exc,rex,n:integer;
cfc:real;
begin
if (p=nil) or (q=nil) then mult:=nil
else begin
new(mult);
crt:=mult;
n:=1;
exc:=p^.ex+q^.ex;
while exc>=0 do begin
cfc:=0;
crtp:=p;
repeat
rex:=exc-crtp^.ex;
if rex>0 then begin
crtq:=q;
while
(crtq^.ex>rex)and(crtq^.next<>nil) do
crtq:=crtq^.next;
if crtq^.ex=rex then
cfc:=cfc+crtp^.cf*crtq^.cf;
103
end;
crtp:=crtp^.next;
until crtp=nil;
if cfc<>0 then
adaug(cfc,exc,crt,n);
exc:=exc-1
end;
crt^.next:=nil
end;
end;
begin
sf := D;
repeat
readp(p);
readp(q);
write('p(x)=');
writep(p);
write('q(x)=');
writep(q);
sumap(p,q,sum);
write('p(x)+q(x)');
writep(sum);
prodp(p,q,mult);
write('p(x)*q(x)=');
writep(mult);
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
27. Afiare vector n ordine invers
program vector_inversat;
const nmax=100;
type vector=array[1..nmax] of integer;
var v:vector;
n,i:integer;
sf:char;
begin
sf := D;
repeat
repeat
write('Numar elemente [1..100]:');
readln(n)
until n n [1..100];
writeln('Dati cele ',n,' elemente');
for i:=1 to n do begin
write('v[',i,')=');
readln(v[i])
end;
writeln('Elementele n ordine inversa:');
for i:=n downto 1 do begin
write(v[i]:3);
104
sf := D;
repeat
repeat
write('Dati Numrul elementelor:');
readln(n)
until n n [1..nmax];
for i:=1 to n do begin
write('list[',i,']=');
readln(list[i])
end;
write('Elementul cautat=');
readln(elem);
ok:=false;
linf:=1;
lsup:=n;
repeat
med:=(linf+lsup) div 2;
if elem=list[med] then ok:=true
else if elem < list[med] then lsup:=med-1
else linf:=med+1
until ok or (linf>lsup);
if ok then writeln ('Elem. ',elem,' gsit pe poziia ',med)
else writeln ('Elem. ',elem,' negasit');
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
30. Proceduri pe iruri de caractere
program proceduri_pe_siruri;
const size=20;
type line=string[size];
var s1,s2:line;
p,c:integer;
option:char;
buflen:word;
sf:char;
begin
sf := D;
repeat
s1:='';
repeat
writeln('String=',s1);
write('Option[Read, Delete, Insert,
Quit]:');
readln(option);
case upcase(option) of 'R':
begin
sf := D; repeat
write('New string: ');
buflen:=size;
readln(s1);
106
end;
'D':
begin
write('Delete starting from: ');
readln (p);
write('Number of deleted
characters: ');
readln(c);
delete(s1,p,c)
end;
'I':
begin
write('Insert substr: ');
buflen:=size;
read(s2);
write('Starting from: ');
readln(p);
insert (s2,s1,p)
end;
'Q':
begin
write ('Are you sure [Y/N]:');
readln(option);
if upcase(option)='Y' then option:='Q'
end
else writeln ('Incorrect')
end;
until option='Q';
writeln('Gata!');
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
31. Conversie ir de caractere n numeric
program str_to_val;
const size=10;
type line=string[size];
var
s:line;
n,code:integer;
x:real;
sf:char;
begin
sf := D;
repeat
repeat
write ('Numeric constant: ');
readln (s);
if length(s)>0 then
begin
val (s,n,code);
if code=0 then writeln('Is a
107
integer constant')
else
begin
val (s,x,code);
if code=0 then writeln('Is a real constant')
else
begin
writeln ('Error!');
writeln('Codul de eroare:19',code)
end
end
end
until s='';
writeln('Gata! Press any key');
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
32. Ordonare vector prin selecie
program sortare_prin_selecie;
const nmax=100;
var
c:array[1..nmax]of integer;
k,n,min,i,j,aux:integer;
sf:char;
begin
sf := D;
repeat
write('Numrul componentelor:'); readln(n);
for i:=1 to n do begin
write ('c[',i,']='); readln (c[i])
end;
for i:=1 to n do begin
k:=i;
min:=c[i];
for j:=i to n do
if c[j]<min then begin
min:=c[j];
k:=j
end;
aux:=c[i];
c[i]:=c[k];
c[k]:=aux
end;
write('vectorul ordonat:');
for j:=1 to n do write(c[j],' ');
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
108
109
110
repeat
write('n='); readln(n);
triunghi[1,1]:=1;
for j:=2 to n do triunghi[i,j]:=0;
for i:=1 to n do begin
triunghi[i,1]:=1;
write(triunghi[i,1],'');
for j:=2 to i do begin
triunghi[i,j]:=
triunghi[i-1,j]+triunghi[i-1,j-1];
write(triunghi[i,j]:4)
end;
for j:=i+1 to n do triunghi[i,j]:=0;
writeln
end;
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
37. Generare stiv de ntregi
program stiv_de_ntregi;
const nmax=100;
var
data,n:integer;
inalt:0..nmax;
stack:array[1..nmax] of integer;
sf:char;
begin
sf := D;
repeat
write('n='); readln(n);
inalt:=0;
writeln('introduceti ',n,' ntregi');
while inalt <n do begin
read(data);
inalt:=succ(inalt);
stack[inalt]:=data;
end;
while inalt >0 do begin
data:=stack[inalt];
inalt:=pred(inalt);
write(data,' ')
end;
writeln;
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
111
write (pointer^.info);
inordine(pointer^.dr)
end
end; {inordine}
procedure postordine (pointer:ref);
begin
if pointer<>nil then begin
postordine (pointer^.st);
postordine(pointer^.dr);
write (pointer^.info);
end
end; {postordine}
procedure creare (var pointer:ref);
begin
read(c);
if c<>'.' then begin
new(pointer);
pointer^.info:=c;
creare (pointer^.st);
creare (pointer^.dr)
end else pointer:=nil
end;
begin {program principal}
sf := D; repeat
write('Arborele dat :':25);
creare (rad);
writeln;
write('Preordine :':25);
preordine (rad);
writeln;
write('Inordine :':25);
inordine (rad);
writeln;
write('Postordine :':25);
postordine (rad);
writeln;
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
40. Modelarea matricilor rare
program matrice_rara;
type ind=0..25;
ir=array[ind]of integer;
mat=array[ind,ind]of integer;
var n,m,p:integer;
v:byte;
sf:char;
procedure varianta1;
var
i,j,k:ind;
113
a,b:ir;
c:mat;
begin
writeln('Dati vectorii:'
write('Lungimea vectorilor:');
readln(m);
for i:=1 to m do begin
write('v[',i,']=');
readln(a[i]);
end;
for i:=1 to m do begin
write('o[',i,']=');
readln(b[i]);
end;
for i:= 1 to n do
for j:= 1 to n do
c[i,j]:=0;
for k:= 1 to m do
begin
j:=(b[k] div n)+1;
i:=b[k] mod n;
if i=0 then begin
i:=n;
j:=j-1;
end;
c[i,j]:=a[k];
end;
for i:= 1 to n do begin
for j:=1 to n do write(c[i,j]:4);
writeln
end
end;
procedure varianta2;
var i,j,k:ind;
a,b:ir;
c:mat;
begin
writeln('Dati matricea:');
k:=0;
for i:= 1 to n do
for j:=1 to n do begin
write('a[',i,',',j,']=');
readln(c[i,j]);
if c[i,j]<>0 then begin
k:=k+1;
a[k]:=c[i,j];
b[k]:=(i-1)*n+j;
end;
end;
for i:=1 to k do begin
write('v[',i,']=',a[i],' ');
114
writeln('o[',i,']=',b[i]);
end;
end;
procedure varianta3;
var i,j,k:ind;
a,b,c,d:ir;
e:mat;
begin
write('Dati prima matrice:');
write('Dati lungimea vectorilor:');
readln(m);
for i:=1 to m do begin
write('v[',i,']='); readln(a[i]);
write('o[',i,']='); readln(b[i]);
end;
write('Dati a doumatrice:');
write('Dati lungimea vectorilor:');
readln(p);
for i:=1 to p do begin
write('v[',i,']='); readln(c[i]);
write('o[',i,']='); readln(d[i]);
end;
k:=m;
for j:= 1 to p do
begin
k:=i;
while(d[j]<>b[i]) and(i<=m) do
i:= i+1;
if i>m then begin
k:=k+1;
a[k]:=c[j];
b[k]:=d[j];
end
else a[i]:=a[i]+c[j];
end;
m:=k;
for i:= 1 to n do
for j:= 1 to n do
e[i,j]:=0;
for k:=1 to m do begin
j:=(b[k] div n)+1;
i:=b[k] mod n;
if i=0 then begin
i:=n;
j:=j-1;
end;
e[i,j]:=a[k];
end;
writeln('Matrice suma este:');
for i:= 1 to n do begin
for j:= 1 to n do writeln(e[i,j]:4);
115
writeln;
end;
end;
begin {programul principal}
sf := D;
repeat
writeln('1-Se dau v i o,s se calculeze a');
writeln('2-Se da a,s se calculeze v i o ');
writeln('3-Se dau doumatrici s se calculeze suma ');
write('Alegeti varianta 1,2,3:');
readln(v);
write('Dati dimensiunea matricei:');
readln(n);
case v of
1:
varianta1;
2:
varianta2;
3:
varianta3;
end;
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
41. Polinoame de m variabile generate static
program polinoame_de_mai_multe_variabile;
type adev=0..1;
ind=0..50;
ir=array[ind] of real;
mat=array[ind,ind]of byte;
var
m,n,p,q:ind;
a,c,e:ir;
b,d,f:mat;
sf:char;
procedure citire_p(r:ind;var x:ir;var y:mat);
var i,j:ind;
begin
writeln('Dati coeficienti monoamelor:');
for i:=1 to r do begin
write('a(',i,')=');
readln(x[i]);
end;
writeln('Dati exponenti necunoscute:');
for i:=1 to r do
for j:=1 to m do begin
write('b(',i,',',j,')=');
readln(y[i,j]);
end;
end;
procedure suma_p(x,z:ir;y,t:mat;var r:ind;var u:ir;var v:mat);
var i,j:ind;
begin
116
for k:=1 to m do
y[j-1,k]:=y[j,k];
end;
r:=r-1;
i:=i-1;
end;
i:=i+1;
end;
end;
procedure afisare_p(r:ind;x:ir;y:mat);
var i,j:ind;
begin
write('P(a');
for i:=1 to m-1 do write(',',chr(ord('a')+i));
write(')=');
if x[1]<>0 then begin
write (x[1]:3:1);
for j:=1 to m do
if y[1,j]<>0 then begin
write('*',chr(ord('a')+j-1));
write('^',y[1,j]);
end;
end;
for i:=2 to r do
if x[i]<>0 then begin
if x[i]>0 then write('+')
else write('-');
write(abs(x[i]):3:1);
for j:=1 to m do
if y[i,j]<>0 then begin
write('*',chr(ord('a')+j-1));
write('^',y[i,j]);
end;
end;
writeln;
end;
begin
sf := D;
repeat
writeln('Dati primul polinom:');
write('Dati Numrul de monoame:');
readln(n);
write('Dati Numrul de necunoscute:');
readln(m);
citire_p(n,a,b);
writeln('Primul polinom este:');
afisare_p(n,a,b);
writeln('Dati al doilea polinom:');
write('Dati Numrul de monoame:');
readln(p);
citire_p(p,c,d);
writeln('Al doilea polinom este:');
118
afisare_p(p,c,d);
suma_p(a,c,b,d,q,e,f);
reducere_p(q,e,f);
micsorare_p(q,e,f);
writeln('Polinomul suma este:');
afisare_p(q,e,f);
produs_p(a,c,b,d,q,e,f);
reducere_p(q,e,f);
micsorare_p(q,e,f);
writeln('Polinomul produs este:');
afisare_p(q,e,f);
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
42. Cutare drumuri de ieire din labirint
program labirinturi;
const n=8;
maxl=5;
spa= ;
type labirint=array[0..n,0..n]of char;
var l:labirint;
t:array[1..maxl]of labirint;
k,nrd,i,j:integer;
sf:char;
procedure afis_ini;
var i,j,lg,sp:integer;
begin
lg:=maxl*(n+4)-3;
sp:=(lg-n-1)div 2;
writeln;
writeln( :sp,LABIRINTUL:);
writeln;
for i:=0 to n do begin
write( :sp);
for j:=0 to n do write(l[i,j]);
writeln;
end;
writeln;
readln;
end;
procedure titlu;
var i:integer;
begin
for i:=nrd-k+2 to nrd do
write(Drum::n-2,i:3,spa);
writeln;
writeln;
end;
procedure scriet;
var i,j,p:integer;
119
begin
titlu;
for i:=0 to n do begin
for p:=1 to k-1 do begin
for j:=0 to n do
write(t[p][i,j]);
write(spa);
end; {for p}
writeln;
end;{for i}
writeln;
writeln;
writeln( Coninuati (D / N) ? ); read(sf); until sf = N;
end; {scriet}
procedure scriel;
begin
if k>maxl then begin
scriet;
k:=1
end;
t[k] :=l ;
k:=k+1;
nrd:=nrd+1;
end; {scriel}
procedure caut(x,y:integer);
begin
if l[x,y]= then begin
l[x,y] :=+ ;
if (x mod n=0)or(y mod n=0) then scriel
else begin
caut(x+1,y) ; {jos}
caut(x,y+1) ; {dr}
caut(x-1,y) ; {sus}
caut(x,y-1) ; {st}
end;
l[x,y] := ;
end
end; {caut}
begin {program principal}
sf := D;
repeat
for i:=0 to n do begin
for j:=0 to n do read(l[i,j]);
readln
end;
k:=1;
nrd :=0 ;
afis_ini ;
caut(n div 2, n div 2) ;
if k>1 then scriet;
writeln( Coninuati (D / N) ? );
read(sf);
120
until sf = N;
end.
43. Livada cu meri
program Livada_cu_mere;
const nmax=100;
type matr=array[1..nmax,1..nmax]of longint;
lo=record
v:integer;
linia:1..nmax;
coloana:1..nmax;
latura:1..nmax;
end;
var a:matr;
s:array[1..nmax]of lo;
li,co,la,m,n,i,j,k,l,nm,smax:integer;
sf:char;
begin
sf := D;
repeat
write('n='); readln(n);
write('m='); readln(m);
for i:= 1 to n do
for j:=1 to m do begin
write('a[',i:2,',',j:2,']=');
readln(a[i,j]);
end;
for i:= 1 to n do begin
for j:=1 to m do write(a[i,j]:4);
writeln;
end;
if n>m then nm:=m else nm:=n;
l:=0;
for i:=1 to n do
for j:=1 to m do
for k:=1 to nm do
if (i+k<=n)and(j+k<=m) then begin
l:=l+1;
with s[l] do begin
v:=a[i,j]+a[i+k,j]+
a[i,j+k]+a[i+k,j+k];
linia:=i;
coloana:=j;
latura:=k;
end
end;
smax:=s[1].v;
for i:=2 to l do
if s[i].v>=smax then smax:=s[i].v;
write('S=(');
for i:=1 to l do write(s[i].v:4);
write(')');
121
writeln;
for i:=1 to l do
if smax=s[i].v then
writeln('smax=',s[i].v, ' linia=',
s[i].linia:3,'coloana=',
s[i].coloana:3,' latura=',
s[i].latura:3);
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
44. Conversie text n alfabetul Morse
program morse;
const a:array[48..122]of string=
('_____','.____','..___','...__','...._','.....','_
....','__...','___..',
'____.',':',';','<','=','>','?','@',
'._','_...','_._.','_..','.','.._.','__.',
'....','..','.___','_._','._..','__','_.','___','._
_.','__._','_._','...','_','.._',
'..._','.__','_.._','_.__','__..','[','\',']','^','
_','`','._','_...','_._.','_..','.','.._.','__.','.
...','..','.___','_._','._..','__','_.','___','.__.
','__._','_._','...','_','.._','..._','.__','_.._',
'_.__','__..');
var
ir:string[120];
i,j,n:integer;
c:char;
sf:char;
begin
sf := D;
repeat
write('n='); readln(n);
writeln('introduceti cele ',n,' car.:');
for i:=1 to n do write(i:1);
writeln;
for i:=1 to n do read (ir[i]);
writeln;
for i:=1 to n do
if ir[i]=' ' then begin
write(' ':4);
delay(500);
end
else begin
delay(300);
write(a[ord(ir[i])],' ');
for j:=1 to ord(a[ord(ir[i])][0])
do begin
c:=a[ord(ir[i])][j];
sound(512);
if c='_' then delay(300);
122
writeln;
k:=k-1;
ok:=true;
i:=1;
while (i<=n) and ok do begin
if a[i]<>b[i] then ok:=false;
i:=i+1
end
until (k=0) or ok;
if ok then writeln ('Ati reusit s reconstituiti cuvantul')
else writeln('Ati esuat: mai
incerati');
write('Coninuati (D/N)?:');
readln(co)
until upcase (co)<>D;
write(Gata: Press any Key!:);
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
46. Construire careu magic de ordin impar
program careul_magic_de_ordin_impar;
var n,m1,m2,i,j,k:integer;
a:array[1..19,1..19] of integer;
sf:char;
begin
sf := D;
repeat
writeln('Se construieste un careu magic cu n linii');
repeat
write('n=');
readln(n);
until (n n [1..19]) and (odd(n));
for i:=1 to n do
for j:=1 to n do
a[i,j]:=0;
i:=(n div 2)+2;
j:=(n div 2)+1;
for k:=1 to n*n do begin
a[i,j]:=k;
m1:=i+1;
m2:=j+1;
if m1=n+1 then m1:=1;
if m2=n+1 then m2:=1;
if a[m1,m2]=0 then begin
i:=m1;
j:=m2;
end
else begin
i:=i+2;
124
s:array[0..22]of integer;
begin
sf := D;
repeat
write('n='); readln(n);
write('a='); readln(a);
k:=0;
while n>0 do begin
s[k]:=n mod a;
n:=n div a;
k:=k+1
end;
{linia se trece n baz 10}
lin:=0;
p:=1;
for i:=2 to 11 do begin
lin:=lin+s[i]*p;
p:=p*a
end;
{bmp se trece n baz 10}
bpm:=0;
p:=1;
for i:=12 to 22 do begin
bpm:=bpm+s[i]*p;
p:=p*a
end;
writeln('Linia n cache:',lin);
writeln('Bitii de pondere mare:',bpm);
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
Conversii ntre sistemele roman i arab
49. Conversie din sistemul roman n sistem arab
program roman_arab;
var sf:char;
cifra:char;
val_prec, val_urm:1..1000;
n:integer;
corect:boolean;
begin
sf := D;
repeat
n:=0;
write('Numrul din cifre romane:');
read(cifra);
corect:=true;
case cifra of
'M':val_prec:=1000;
'D':val_prec:=500;
126
'C':val_prec:=100;
'L':val_prec:=50;
'X':val_prec:=10;
'V':val_prec:=5;
'I':val_prec:=1;
else corect:=false
end;
while corect and not eoln do begin
read(cifra);
case cifra of
'M':val_urm:=1000;
'D':val_urm:=500;
'C':val_urm:=100;
'L':val_urm:=50;
'X':val_urm:=10;
'V':val_urm:=5;
'I':val_urm:=1;
else corect:=false
end;
if corect then begin
if val_prec<val_urm then
n:=n-val_prec
else n:=n+val_prec;
val_prec:=val_urm;
end;
end;
if corect then writeln
('Numrul n scriere araba:',n+val_prec)
else writeln('Eroare: ',cifra,' nu este cifra romana');
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
50. Conversie din sistemul arab n sistem roman
program arab_roman;
var sf:char;
x,y:integer;
begin
sf := D;
repeat
y:=1;
while y<=5000 do begin
x:=y;
write(y,':');
while x>1000 do begin
write('M');
x:=x-1000;
end;
if x>=900 then begin
write('CM');
x:=x-900;
127
end;
if x>=500 then begin
write('D');
x:=x-500;
end;
if x>=400 then begin
write('CD');
x:=x-400;
end;
while x>=100 do begin
write('C');
x:=x-100
end;
if x>=90 then begin
write('XC');
x:=x-90;
end;
if x>=50 then begin
write('L');
x:=x-50;
end;
if x>=40 then begin
write('XL');
x:=x-40;
end;
while x>=10 do begin
write('X');
x:=x-10;
end;
if x>=9 then begin
write('IX');
x:=x-9;
end;
if x>=5 then begin
write('V');
x:=x-5;
end;
if x>=4 then begin
write('IV');
x:=x-4;
end;
while x>=1 do begin
write('I');
x:=x-1;
end;
y:=2*y;
writeln;
end;
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N; end.
128
repeat
i:=0;
j:=-1;
repeat
read (a[i]); i:=i+1;
until a[i-1]='%';
i:=-1;
spinit;
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
130
ng:numeg;
n,i:integer;
sf:char;
begin
sf := D;
repeat
write(numef:);
readln(nf);
assign(f,nf);
rewrite(f);
write(nr.grupe:);
readln(n);
for i:=1 to n do
begin
write(grupa ,i,:);
readln(ng);
write(f,ng);
end;
close(f);
reset(f);
while not eof(f) do
begin
read(f,ng);
writeln(ng);
end;
close(f);
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
55. Actualizare n acces direct fiier studeni
program accesare_directa_fisiere;
const nm=15;
type numes=string[25];
note=0..10;
student =record
nume:numes;
m:array[1..nm]of note;
end;
grupa=file of student;
numeg=string[6];
var
g:grupa;
ng:numeg;
ns,nn,no,nr,i,j:integer;
s:student;
sf:char;
procedure modi_nota(var g:grupa;is,im:integer; noua:note);
var s:student;
begin
seek(g,is-1);
read(g,s);
132
s.m[im] :=noua ;
seek(g,is-1);
write(g,s);
end;
procedure list_note(var g:grupa;x,y:integer);
var s:student;
i:integer;
begin
seek(g,x-1);
read(g,s);
write(x:2, .,s.nume);
for i:=1 to nn do write(s.m[i]:3);
writeln;
end;
begin
sf := D;
repeat
write(numeg:); readln(ng);
assign(g,ng);
rewrite(g);
write(numar studenti i note:);
readln(ns,nn);
for i:=1 to ns do
with s do begin
write(nume,i:2, :);
readln(nume);
write(notele:);
for j:=1 to nn do read(m[j]);
readln;
writeln;
write(g,s);
end;
close(g);
reset(g);
write(modif. Nota nr pt stud, ns,:);
readln(nr,ns);
write(noua nota :) ;
readln(no);
writeln(note vechi stud. Cu nr.,ns:2);
list_note(g,ns,nr);
modi_nota(g,ns,nr,no);
writeln(note noi stud. Cu nr.,ns:2);
list_note(g,ns,nr);
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;.
end.
133
note=array[1..maxnote]of 0..10;
student=record
stud_nume:nume;
n:note;
restante:0..maxnote;
absente:0..maxnote;
end;
studenti=array[1..maxstud]of student;
var
s:studenti;
ns,nn,o:integer;
c:char;
sf:char;
procedure read_st;
var i,j:integer;
begin
repeat
write('Numar studenti i note:');
readln(ns,nn)
until (ns n [1..maxstud]) and (nn n [1..maxnote]);
for i:=1 to ns do
with s[i] do begin
write ('Nume student ',i,' :');
readln(stud_nume);
write('note: ');
for j:=1 to nn do
read(n[j]);
readln
end
end; {read_st}
procedure write_st;
var i,j:integer;
begin
sf := D;
repeat
writeln('Nume student Note');
for i:=1 to ns do
with s[i] do begin
write(stud_nume,' ':25-length(stud_nume));
for j:=1 to nn do write(n[j]:3);
writeln
end
end; {write_st}
procedure order (o:integer);
var i,j:integer;
temp:student;
begin
for i:=1 to ns-1 do begin
for j:=i+1 to ns do
if (s[j].n[o]>s[i].n[o]) or
(s[j].n[o]=s[i].n[o]) and
(s[j].stud_nume=s[i].stud_nume)
135
then begin
temp:=s[i];
s[i]:=s[j];
s[j]:=temp
end
end;
write_st
end; {order}
begin {programul principal}
sf := D; repeat
read_st;
repeat
write('Index nota[1..', nn,']:');
o:=0;
readln(o);
if o n [1..nn] then order(o)
else writeln ('Eroare');
write ('Stop? [D/N]:');
readln(c)
until upcase(c)='D';
writeln('Press any key');
writeln( Coninuati (D / N) ? );
read(sf);
until sf = N;
end.
58. Ordonare fiier studeni varianta a 2-a
program ordonare_studenti_varianta2;
const maxstud=30;
maxnote=15;
type
nume=string[24];
note=array[1..maxnote]of 0..10;
student=record
stud_nume:nume;
n:note;
restante:0..maxnote;
absente:0..maxnote;
end;
studenti=array[1..maxstud]of student;
var
s:studenti;
ns,nn,o:integer;
c:char;
o_list:array[1..maxstud]of integer;
sf:char;
procedure read_st;
var i,j:integer;
begin
repeat
write('Numar studenti i note:');
readln(ns,nn)
until (ns n [1..maxstud]) and
136
(nn n [1..maxnote]);
for i:=1 to ns do
with s[i] do begin
write ('Nume student ',i,' :');
readln(stud_nume);
write('note: ');
for j:=1 to nn do
read(n[j]);
readln;
o_list[i]:=i;
end
end; {read_st}
procedure write_st;
var i,j:integer;
begin
sf := D;
repeat
writeln('Nume student Note');
for i:=1 to ns do
with s[o_list[i]] do begin
write(stud_nume,' ':25-length(stud_nume));
for j:=1 to nn do write(n[j]:3);
writeln
end
end; {write_st}
procedure order (o:integer);
var i,j:integer;
temp:student;
begin
for i:=1 to ns-1 do begin
for j:=i+1 to ns do
if
(s[o_list[j]].n[o]>s[o_list[i]].n[o]) or
(s[o_list[j]].n[o]=s[o_list[i]].n[o])and
(s[o_list[j]].stud_nume=s[o_list[i]].stud_nume)
then begin
temp:=s[o_list[i]];
s[o_list[i]]:=s[o_list[j]];
s[o_list[j]]:=temp
end
end;
write_st
end; {order}
begin {programul principal}
sf := D; repeat
read_st;
repeat
write('Index nota [1..', nn,']:');
o:=0;
readln(o);
if o n [1..nn] then order(o)
else writeln ('Eroare');
137
until not er
end;
(* ------------------------------------- *)
procedure cit_cant;
begin
repeat
er:=false; gotoxy(38,i+8); clreol;
{$i-} readln(art.cant[i]); {$i+}
if ioresult<>0 then
begin
s:='Caractere nenumerice !';
eroare
end
until not er
end;
procedure inceput;
begin
textbackground(magenta); textcolor(yellow); clrscr;
assign(f,'produse.dat'); rewrite(f); checkeof:=true;
gotoxy(20,5); write('Cod (sau ^Z): ');
gotoxy(20,6); write('Denumire : ');
gotoxy(20,7); write('Cod depozit: ');
gotoxy(20,8); write('Pret mediu : ');
for i:=1 to 12 do
begin
gotoxy(20,i+8);
write('Cant. luna ',i:2,' : ');
end;
gotoxy(38,5);
end;
(* ------------------------------------- *)
procedure prelucrare;
begin
cit_cod; cit_den; cit_dep; cit_pret;
for i:=1 to 12 do cit_cant;
write(f,art);
for i:=5 to 20 do begin gotoxy(38,i); clreol; end;
gotoxy(38,5);
end;
(* ------------------------------------- *)
procedure sfarsit;
begin
close(f);
end;
(* ------------ program principal ----------- *)
begin
inceput;
while not eof do prelucrare;
sfarsit;
end.
140
gotoxy(30,15);
writeln('Cod produs eronat !',#7)
end;
clrscr; gotoxy(27,5);
write('Codul produsului (sau ^Z): ')
end;
close(f);
end.
61. Afarea denumirii i a produciei valorice anuale pentru
produsele existente n fierul Produse.dat, aflate n depozitele ale
cror coduri se introduc de la tastatur. Sfritul introducerii de la
tastatur se marcheaz standard (^Z n cmpul dep).
Observaii: Deoarece ntr-un depozit se af mai multe produse (cmpul
dep are valori duplicate), cutarea se realizez de la nceputul pn la
sfritul fierului pentru fecare nou cod de deposit introdus. n cazul n
care nici un produs nu are codul depozitului egal cu valoarea introdus de
la tastatur, se afeaz un mesaj corespunztor i procesul se reia.
Existena sau inexistena a cel puin unui produs n depozitul cutat este
marcat cu o variabil boolean.
program consultare_dupa_camp_cu_valoare_duplicata;
uses crt;
type
produs=record
cod:byte;
den:string[30];
dep:char;
pu:longint;
cant:array[1..12] of word
end;
var
art:produs;
f:fle of produs;
ir:string[30];
dep_t:char;
i,k:byte;
v:real;
begin
assign(f,'produse.dat'); reset(f);
clrscr; checkeof:=true;
gotoxy(27,5);
write('Codul depozitului: ');
while not eof do
begin
gotoxy(50,5); readln(dep_t);
seek(f,0);
k:=0;
while not eof(f) do
begin
fllchar(ir,31,' ');
read(f,art);
142
if art.dep=dep_t then
begin
inc(k); v:=0;
for i:=1 to 12 do v:=v+art.cant[i];
v:=v*art.pu;
gotoxy(10,12);
writeln('Cod',' ':10,'Denumire',' ':25,'Valoare');
gotoxy(10,14+k); ir:=art.den; ir[0]:=#30;
writeln(art.cod:3,' ':10,ir,' ',v:10:0,' lei');
end
end;
if k=0 then
begin
gotoxy(30,15);
writeln('Cod depozit eronat !',#7)
end;
readln; clrscr; gotoxy(27,5);
write('Codul depozitului (sau ^Z): ')
end;
close(f);
end.
62. Afarea produciei valorice anuale pentru fecare depozit i pe
ntreprindere, utiliznd fierul Produse.dat.
Observaii: Problema se rezolv cu ajutorul algoritmului de consultare
secvenial cu control dup o caracteristic. Pentru obinerea situaiei
cerute se creeaz un fier de manevr, care va conine date privind codul
depozitului i stocul valoric anual pentru toate produsele existente n
fierul de date. Fiierul de manevr se sorteaz dup cmpul cod depozit,
apoi este consultat secvenial i integral dup aceast caracteristic,
obinndu-se dou grade de total: unul pentru depozit i unul pentru
ntreprindere.
program consultare_cu_control_dupa_caracteristica;
uses crt;
type artf=record
cod:byte;
den:string[30];
dep:char;
pu:longint;
cant:array[1..12] of word
nd;
artm=record
depm:char;
v:real
end;
var
z:artf; x,y:artm;
f:fle of artf;
m:fle of artm;
i,j:byte;
totgen,totdep:real;
143
vb,sf:boolean;
c:char;
procedure copiere;
begin
assign(f,'produse.dat'); reset(f);
assign(m,'manevra.tmp'); rewrite(m);
with z,x do
begin
while not eof(f) do
begin
read(f,z);
v:=0;
for i:=1 to 12 do v:=v+cant[i];
v:=v*pu;
depm:=dep;
write(m,x);
end;
end;
close(f);
end;
procedure sortare;
begin
repeat
vb:=false;
for i:=1 to flesize(m)-1 do
begin
seek(m,i-1); read(m,x,y);
if x.depm>y.depm then
begin
seek(m,i-1);
write(m,y,x);
vb:=true;
end;
end;
until not vb
end;
procedure afsare;
begin
seek(m,0); sf:=false;
totgen:=0; i:=0;
clrscr; gotoxy(5,3);
writeln('Stocul valoric pe depozite');
gotoxy(9,6);
writeln('Depozit Stoc');
read(m,x);
while not sf do
begin
totdep:=0;
c:=x.depm;
while (x.depm=c) and not sf do
begin
totdep:=totdep+x.v;
144
146
147