Sunteți pe pagina 1din 14

Universitatea Tehnică a Moldovei

FCIM
Catedra Informatica Aplicativă

RAPORT
la lucrarea de laborator nr. 4

la SDA

Tema: Analiza prelucrării structurilor de date cu liste

Varianta 13

A efectuat: st. gr. Ti-161 Trifan Iulian.

A verificat: Marin Ştefan

Chişinău – 2016
Sarcina şi obiectivele:
- de studiat şi însuşit materialul teoretic pentru evidenţierea esenţialului prelucrării
structurilor de date cu liste în elaborarea modelelor soluţiei, anaizând exemplele din text;
- să se selecteze problemele din compartimentul “3 şi Anexe” şi să se elaboreze
organigramele (pentru funcţiile principale) şi programele cu liste (declarări, parcurgeri,
etc.), pentru aprofundare şi rularea programelor în limbajul C să se elaboreze scenariile
succinte de soluţionare prin respectiva tehnică de prelucrare cu calculele de verificare şi
explicaţii.
- să se analizeze tehnica modelării şi programării eficiente pentru diverse compartimente
ale diferitor situaţii cu diverse argumentări şi modele de structuri abstracte, incluzând
fişiere cu teste de verificare şi vizualizări.
Consideraţii teoretice:
1. Consideraţiile teoretice generale. Tipuri de date abstracte Tipul de date abstract este o entitate manipulata
doar prin operatiile ce definesc acel tip. Avantajele utilizarii tipurilor de date abstracte sunt:
- Programele devin independente de modul de reprezentare a datelor. Modul de reprezentare poate fi modificat,
fara însa a afecta restul programului (de exemplu, o multime poate fi implementata printr-un tablou sau printr-o
lista ordonata, dar partea de program ce foloseste operatorii tipului abstract rămâne neschimbata).
- Se previne violarea accidentala a datelor. Utilizatorul tipului abstract este forţat sa manipuleze datele doar prin
intermediul operatorilor ce compun tipul abstract, astfel reducându-se riscul unei distrugeri a datelor.
Dupa cum este exemplificat în continuare, în C tipurile abstracte sunt realizate folosind fişiere. Acest mod are
desigur propriile sale limitari. Mentionam doar doua din ele: nu se pot defini tablouri de tipuri abstracte si nu se pot
transmite parametri având ca si tip un tip abstract.
Pentru utilizarea eficientă a unui calculator trebuie ca relaţiile structurale existente in mulţimea datelor şi modul de
acces la aceste date să se reflecte în metodele de reprezentare şi manipulare a structurilor de date în cadrul sistemelor de
calcul. Vom face o introducere a celor mai importante noţiuni despre structurile informaţiei: proprietăţi statice şi
dinamice ale diferitelor tipuri de structuri liniare, precum şi algoritmi eficienţi pentru crearea, modificarea, regăsirea şi
ştergerea informaţiilor cu o anumită structură în interiorul sistemelor de calcul. Structurile de date arborescente vor fi
introduse in materialul care trateză despre aplicaţiile arborilor binari (Ll5). În continuare vom denumi anumiţi termeni
care vor fi utilizaţi în acest material. Astfel informaţiile conţinute într-un tabel constant dintr-o mulţime de noduri
(numite şi înregistrări, entităţi sau articole). Fiecare nod se compune din unul sau mai multe cuvinte consecutive din
memoria calculatorului, fiind împărţite în părţi componente numite cîmpuri. De exemplu, un nod poate ocupa un singur
cuvînt din memorie avînd un singur cîmp de lungime egală cu lungimea întregului cuvînt din memorie. Să presupunem
acum că elementele tabelului reprezintă nişte cărţi de joc: nodurile sunt formate de cîte un cuvînt, divizat în patru
cîmpuri: MARCA, CULOARE, RANG şi URMĂTOR:
MARCA CULOARE RANG URMĂTOR
Am presupus că un cuvînt al calculatorului nostru se compune din cinci octeţi, cîmpul URMĂTOR ocupînd ultimii
doi octeţi. Adresa unui nod, numită şi pointerul sau referinţa acelui nod reprezintă locaţia din memorie a primului cuvînt
aparţinînd nodului (în caz cînd acesta se compune din mai multe noduri consecutive) sau a unicului cuvînt aparţinînd
nodului. Adresa se consideră ca adresă relativă faţă de o locaţie de bază, dar pentru simplitate vom considera adresa ca
adresă absolută a locaţiei din memorie. Conţinutul oricărui cîmp al unui nod poate reprezenta numere, caractere
alfabetice, referinţe la alte noduri sau orice altă informaţie dorită de programator. În exemplul dat, să presupunem că
dorim să reprezentăm un pachet de cărţi de joc, adoptînd următoarele convenţii: MARCA=1 pentru cartea respectivă cu
faţa în jos, MARCA=0 pentru cartea cu faţa în sus; CULOARE=1,2,3 SAU 4 pentru treflă, caro, cupă şi respectiv pică;
RANG=1,2, ... 13, pentru as, doi, ... rege; URMĂTOR este o referinţă la cartea care urmează în pachet. Un pachet de
cărţi constînd din cinci cărţi: rege de treflă, patru de treflă, as de cupă (cu faţa în jos), şase de pică şi valet de caro în
această ordine se pot reprezenta în calculator în modul următor:
Locaţiile din memorie utilizate sunt în acest caz 102, 366, 242, 244 şi
102 164.
0 Aceste1 adrese
13 pot fi schimbate în funcţie de memoria
366
366 disponibilă,
0 1 cu condiţia
4 de a cunoaşte prima adresă ( în cazul nostru
242
102 ) şi respectînd regula ca fiecare carte să conţină o referinţă la
242 cartea
1 următoare
3 1,corespun-
244 zător ordinii din pachet. Referinţa
244 specială
0 4„Λ ” 6din nodul
164 164 semnifică referinţa nulă, care nu
164 corespunde
0 2 nici12unui alt
Λ nod şi apare în nodul 164 deoarece cartea
valet de caro este ultima carte dinfig
pachet.
1.1
În acest material vom folosi litera lambda din alfabetul grecesc pentru reprezentarea referinţei nule. În memoria
calculatorului, Λ va fi reprezentată printr-o valoare uşor de recunoscut care nu poate reprezenta adresa unui nod, de
exemplu un număr negativ sau numărul zero.
Introducerea de referinţe sau pointeri către alte noduri reprezintă o idee foarte utilă pentru reprezentarea
structurilor complexe.
Astfel toate referinţele la noduri într-un program se realizează direct cu ajutorul variabile- lor referinţe sau
indirect prin cîmpurile referinţe ale altor noduri.
Referirea la cîmpurile din cadrul nodurilor se realizează simplu indicînd numele cîmpu- lui urmat de o referinţă la
nodul respectiv, între paranteze. Pentru exemplul dat avem RANG (ÎNCEPUT) =13; URMĂTOR (244)=164;
CULOARE(URMĂTOR(ÎNCEPUT))=1.
Următorul algoritm numără cîte cărţi de joc conţine pachetul:
1.N ← 0, X← ÎNCEPUT ( N este o variabilă întreagă şi X este o variabilă de tip referinţă ).
2.Dacă X=Λ, stop ( N reprezintă numărul de cărţi din pachet ).
3.N← N +1, X← URMĂTOR(X) şi mergi la pasul 2.
Să notăm utilizarea de nume simbolice atît pentru variabile ( ÎNCEPUT, N, X ) cît şi pentru cîmpuri ( URMĂTOR
). Dacă P este numele unui cîmp iar L ≠ Λ este o referinţă, atunci P(L) este o variabilă fără ca P să fie la rîndul lui
variabilă.
Structura de date aferentă unui anumit algoritm poate avea consecinţe serioase atît asupra memoriei ocupate
(complexitate spaţiu) cît şi asupra timpului de calcul (complexitate timp).

1.1 LISTE LINIARE


Lista liniara este o structura de date in care fiecare element are un succesor unic, (exceptie face ultimul element al
listei).

Ex: Intr-o lista de articole carre cuprind date despre angajatii unei firme, cheia o poate reprezenta numele
angajatului sau marca, etc...
listele generale au asociate patru operatii elementare :
• Inserarea
• Stergerea
• Cautarea
• Traversarea
Inserarea reprezinta o oparatie prin care un nou element este introdus in lista.
Intr-o lista generala, inserarea unui element se face la inceputul, in interiorul sau la sfarsitul ei. Deoarece, intr-o lista
neordonata, nu conteaza pozitia unde se efectueaza inserarea, se obisnuieste ca operatia sa se efectueze la sfarsitul ei. In
acest fel elementele pot fi gasite in ordinea in care au fost ele introduse (inserate). Acesta este si motivul pentru care
Inserarea reprezinta o oparatie prin care un nou element este introdus in lista.
Intr-o lista generala, inserarea unui element se face la inceputul, in interiorul sau la sfarsitul ei. Deoarece, intr-o lista
neordonata, nu conteaza pozitia unde se efectueaza inserarea, se obisnuieste ca operatia sa se efectueze la sfarsitul ei. In
acest fel elementele pot fi gasite in ordinea in care au fost ele introduse (inserate). Acesta este si motivul pentru care
listele neordonate se mai numesc si liste cronologice.
Stergerea reprezinta o operatie care permite eliminarea unui element al listei. Aceasta operatie cuprinde:
• Cautarea elementului care trebuie eliminat
• Stergerea efectiva a elementului respectiv
Daca lista este reprezentata cu ajutorul unui vector, atunci elementele ce succed elementul care trebuie sters vor fi
deplasate spre stanga cu o pozitie. Dupa aceasta operatie elementul fiind inlocuit cu succesorul sau.
Cautarea reprezinta operatia prin care se urmareste gasirea unui element intr-o structura.
In general algoritmul de cautare secventiala (element cu element) poate fi aplicat indiferent de tipul listei sau de
modul ei de reprezentare. Daca avem de-a face cu o lista ordonata, reprezentata ca vector, se poate folosi algoritmul de
cautare binara.
Traversarea accesarea secventiala a tuturor elementelor din structura. Ea poate fi privita ca un caz special de cautare,
deoarece consta in regasirea tuturor elementelor structurii. Traversarea consta in exiistenta in algoritm a unei bucle. La
fiecare iteratie este accesat cate un element. Bucla se incheie cand aceasta operatie a fost efectuata asupra ultimului
element.
Obs. Este necesar sa mentionam ca reprezentarea listelor liniare cu ajutorul vectorilor are unele dezavantaje majore.
Astfel, operatia de inserare sau stergere a unui singur element implica operatii de deplasare ce se efectueaza asupra unui
ansamblude elemente. Inserarea pe pozitia a doua a unei liste ce contine 1000 de elemente conduce la efectuarea a 999
de operatii de deplasare.
Stiva reprezinta o lista liniara in care operatiile de introducere si extragere se efectueaza la unul din capetele
structurii. Primul element intalnit la acest capat poarta numele de varf. Orice ansamblu liniar asupra caruia putem
actiona prin introducerea sau extragerea unui element, doar la unul din capete, reprezinta o stiva.
La nivelul memoriei interne stivei i se aloca o zona fixa, care "exista" pe tot parcursul executiei programului. In
cadrul acestui spatiu de memorie locatiile sunt "ocupate" sau "eliberate", conform operatiilor de introducere extragere
descrise prin program. Datorita restrictiei asupra operatiilor de introducere si extragere, stiva se mai numeste si structura
LIFO.
Coada - lista liniara in care operatiile de introducere se efectueaza printr-un capat al structurii, iar operatiile de
extragere se efectueaza la celalalt capat. Elementul care poate fi extras dintr-o coada se numeste varf, iar ultimul se
numeste baza.
Aceasta restrictionare a operatiilor asigura procesarea elementelor in ordinea in care au fost "primite". Cu alte
cuvinte o coada este o structura FIFO.
Ca si stiva, coada reprezinta o structura semistatica. Ea are alocata, la nivelul memoriei interne, o zona fixa care
exista pe tot parcursul executiei programului.
Dezvoltarea structurii se efectueaza in interiorul acestui spatiu de memorie, in urma operatiilor de adaugare si
eliminare. Acestea conduc la ocuparea si eliberarea locatiilor de memorie existente in interiorul zonei rezervate. Ca
deosebire intre manipularea unei stive si manipularea unei cozi, lucrul cu o coada implica "monitorizarea" atat a varfului
cat si al Asupra cozii se pot efectua patru operatii elementare :
• Adaugarea - aceasta operatie permite adaugarea unui element in coada, ca succesor al bazei curente. Dupa
introducere baza va deveni acest nou element. Ca si in cazul stivei, trebuie sa avem in vedere ca operatia nu se poate
efectua cand coada este plina, deci cand spatiul rezervat acesteia sete in totalitate folosit.
• Eliminarea - aceasta operatie permite extragerea varfului cozii. Dupa aceasta operatie, varful va deveni elementul
succesor celui eleiminat. Operatia nu se poate efectua cand coada este vida.
• Accesarea varfului cozii - aceasta operatie permite accesarea varfului cozii, fara ca acesta sa fie eliminat. Trebuie
mentionat ca, in cazul in care coada este vida, operatia nu poate fi efectuata.
• Accesarea bazei cozii - aceasta operatie permite accesarea (citirea) bazei cozii, fara ca elementul sa fie eliminat.
Operatia nu se poate efectua asupra unei cozi vide.
Obs. Coada accepta mai multe forme de reprezentare. De exemplu poate fi implementata cu ajutorul unui tablou
unidimensional sau, daca are un numar extrem de mare de elemente, se poate folosi un fisier.
Daca luand in discutie modul de reprezentare al unei cozi cu ajutorul unui vector, operatia de adaugare a unui
element intr-o coada vida conduce la plasarea acestuia pe prima componenta a tabloului. Elementul astfel introdus
devine atat baza, cat si varf. Fiecare operatie de adaugare conduce la plasarea elementului pe pozitia urmatoare bazei
curente. In operatia de eliminare (stergere), varful inainteaza cu o pozitie. Observam ca in urma operatiilor succesive de
adaugare si eliminare, elementele cozii migreaza de la prima componenta a vectorului spre ultima. O coada este plina
cand varful se afla pe prima pozitie in vector, iar baza pe ultima pozitie. Cand datele sunt stocate cu rapiditate in coada,
exista tendinta de avansare catre finalul vectorului, ajungadu-se la situatia in care ultimul element din vector este ocupat,
dar coada nu este plina, deoarece exista componente libere la inceputul acestuia. Cand datele sunt grupate la finalul
vectorului si avem nevoie sa gasim un loc pentru adaugarea unui nou element, o solutie ar fi deplasarea in bloc a tuturor
elementelor la inceputul vectorului.
O solutie mult mai eficienta este folosirea unui vector circular. El reprezinta o structura de date conceptuala in cadrul
careia ultimul element are ca succesor logic primul element. In aceasta situatie, adaugarea unui element intr-o coada a
carei baa se afla pe ultima pozitie a vectorului se va efectua pe prima pozitie.
Deci o listă liniară este o mulţime ordonată constînd din n ≥ 0 noduri (pentru n=0 lista este vidă ). Aceste
noduri se noteză da exemplu X[1], X[2], ..., X[n], unde indicele care apare în paranteze ne arată poziţia
nodului în cadrul listei; astfel dacă n>0 , X[1] este primul nod; pentru 1< k < n , nodul X[k] este precedat de
nodul X[k-1] şi este urmat de nodul X[k+1]; X[n] este ultimul nod. Desigur pentru n=1 nodul X[1] este atît
primul cît şi ultimul nod, iar pentru n=2 X[1] este primul nod, X[2] este ultimul nod şi nu există alte noduri
intermediare.
Intrebari de autocontrol
Exerciţiul 1. Să se analizeze programul pentru crearea unei liste simplu înlănţuite cu preluarea datelor de
la tastatură. Sfârşitul introducerii datelor este marcat standard (CTRL+Z). După creare, se va afişa conţinutul
listei apoi se va elibera memoria ocupată.
#include<conio.h>
#include<stdio.h>
//#include<stdin.h>
#include <memory.h>
#define NEW (NOD*)malloc(sizeof(NOD));
struct lista {int info;int *next;}lista ;
typedef struct lista NOD;
NOD* creare() { NOD *prim,*ultim,*q; int nr;
printf(" primul nr="); scanf("%i",&nr); // se citeşte primul număr
prim=(NOD*)malloc(sizeof(NOD)); prim->info=nr; // se creează primul nod
prim->next=NULL; ultim=prim; // se creează ultimul nod
printf("\n urmatorul nr sau tastati CTRL+Z pentru iesire) = "); scanf("%i",&nr); // se citeşte al
doilea număr
while(!feof(stdin)) // atâta timp cât nu introducem CTRL+Z
{ q=(NOD*)malloc(sizeof(NOD)); q->info=nr; // se creează nodul următor
q->next=NULL; ultim->next=q; ultim=q; // se creează ultimul nod
printf("\n urmatorul nr sau tastati CTRL+Z pentru iesire)= "); scanf("%i",&nr); // se citeşte
numărul următor
} return prim; }
void afis(NOD* prim) { printf("\n"); printf("\n Lista este");
while(prim!=NULL) // atâta timp cât p este diferit de NULL
{ printf("\t \n%i",prim->info); // se afişează nodul curent
prim=prim->next; // se trece la următorul nod
} }
void stergere (NOD* prim) { NOD *p;
while(prim) // atâta timp cât prim este diferit de NULL
{ p=prim; // p devine primul nod
prim=prim->next; // prim devine următorul nod
free(p); // se eliberează nodul curent
} }
void main() { NOD *prim; int a,b,c,d,e,f,g; system("cls");
// Creare
prim=creare(); afis(prim);
// Eliberare memorie
stergere(prim); getch();
}

Programul memoreaza identificatorii si valorile asociate lor într-o evidenta, pe care o foloseste conform
functionalitatii cerute. Evidenta este realizata printr-o lista simplu înlantuita ordonata. Fiecare nod al listei contine un
câmp pentru pastrarea identificatorului, care este indicat de char *id, un câmp pentru memorarea valorii asociate
identificatorului, câmpul int valoare, si un câmp pentru a crea înlantuirea cu nodul urmator din lista, câmpul
struct elem *urm. Lista este ordonata crescator functie de câmpurile id ale nodurilor.

 a - Se citeste o linie de forma: identificator numar, unde numar este un numar întreg.
Ca rezultat, se retine în evidenta identificatorul împreuna cu numarul asociat lui.
 t - Se citeste o linie ce contine un identificator. Daca acesta apare în evidenta, se tipareste valoarea
asociata lui; în caz contrar se tipareste un mesaj de eroare.
 s - Se citeste o linie ce contine un identificator si îl sterge din evidenta.
 l - Se tiparesc identificatorii din evidenta în ordine alfabetica împreuna cu valorile asociate lor.
 +- Se citesc doua linii, fiecare continând un identificator. În cazul în care ambii se afla în evidenta se
tipareste suma lor. În caz ca unul sau ambii identificatori lipsesc din evidenta, se afiseaza un mesaj de eroare.
 -- Se citesc doua linii, fiecare continând un identificator. În cazul în care ambii se afla în evidenta se
tipareste diferenta lor. În caz ca unul sau ambii identificatori lipsesc din evidenta, se afiseaza un mesaj de
eroare.
 *- Se citesc doua linii, fiecare continând un identificator. În cazul în care ambii se afla în evidenta se
tipareste produsul lor. În caz ca unul sau ambii identificatori lipsesc din evidenta se afiseaza un mesaj de
eroare.
 /- Se citesc doua linii, fiecare continând un identificator. În cazul în care ambii se afla în evidenta se
tipareste rezultatul împartirii lor. În caz ca unul sau ambii identificatori lipsesc din evidenta se afiseaza un
mesaj de eroare.
 f - Se termina programul.
Observatie: Identificatorii sunt pastrati în tabela în mod ordonat.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <ctype.h>
#define Max 100 /* lungimea maxima a unei linii */

/* tipul pentru nodul listei */


typedef struct elem
{
char *id;
int valoare;
struct elem *urm;
} nod;

nod *radacina=NULL; /* pastreaza inceputul listei */


/*---------------------------------------------------------*/
/* */
/* Functia caut cauta sirul s in lista al carei inceput e indicat de parametrul lista. Daca sirul apare in lista*/
/* atunci functia returneaza pointerul la nodul respectiv, in caz contrar returneaza NULL */
/* */
/*---------------------------------------------------------*/
nod *caut(nod *lista, char *s)
{
nod *q1;

for (q1=lista; q1!=NULL && strcmp(q1->id, s)<0; q1=q1->urm);


/* caut 1 */

if (q1!=NULL && strcmp(q1->id, s)==0) /* caut 2 */


return q1; /* daca sirul s a fost gasit in lista */

return NULL;
}
/*---------------------------------------------------------*/
/* */
/* Functia listez parcurge lista si pentru fiecare nod afiseaza identificatorul memorat si valoarea atasata lui.*/
/*Deoarece lista este ordonata, afisarea identificatorilor* este in ordine alfabetica */
/* */
/*---------------------------------------------------------*/
void listez(void)
{
nod *q;

for (q=radacina; q!=NULL; q=q->urm)


printf("Identificator: %s Valoare: %d\n",q->id,q->valoare);
}

/*---------------------------------------------------------*/
/* Functia sterg elimina din lista indicata de pointerul lista, nodul ce are campul id egal cu argumentul s */
/* */
/*---------------------------------------------------------*/
nod *sterg(nod *lista, char *s)
{
nod *q1, *q2;

for (q1=q2=lista; q1!=NULL && strcmp(q1->id, s)<0;


q2=q1,q1=q1->urm); /* sterg 1 */
/* se parcurge lista cautandu-se nodul avand */
/* campul id egal cu sirul s */

if (q1!=NULL && strcmp(q1->id, s)==0) /* sterg 2 */


{
/* daca s-a gasit un astfel de nod */
if (q1!=q2) /* daca nodul nu este la inceputul listei */
/* sterg 3 */
q2->urm = q1->urm; /* elimina nodul din lista */
else /* nodul apare la inceputul listei */
lista = lista->urm; /* sterg 4 */

free(q1->id);
/* se elibereaza memoria ocupata de nodul eliminat */
free(q1);

return lista; /*returneaza pointerul catre inceputul listei modificate*/


}
else
{
printf("Eroare: identificatorul %s nu apare in lista\n", s);
return lista;
}
}
/*---------------------------------------------------------*/
/* */
/* Functia introduc insereaza un nod in lista ordonata, indicata de parametrul lista. Lista ramine ordonata si */
/* dupa inserare. Nodul nou are campul id egal cu sirul indicat de parametrul s, iar campul valoare egal cu */
/* parametrul v. Functia returneaza pointerul catre inceputul listei modificate */
/*---------------------------------------------------------*/
nod *introduc(nod *lista, char *s, int v)
{
nod *q1, *q2, *aux;
if ((aux=(nod *)malloc(sizeof(nod)))==NULL ||
(aux->id=(char *)malloc(strlen(s)+1))==NULL)
/* introduc 1 */
{
/* daca nu e memorie suficienta pentru a crea un nod nou, respectiv pentru a memora sirul s, se da un mesaj de
eroare
dupa care executia e incheiata */

printf("Eroare: memorie insuficienta\n");


exit(1);
}
strcpy(aux->id, s); /* se salveaza s in nodul nou */
aux->valoare=v; /* se salveaza v in nodul nou */

/* nodul nou este inserat in lista ordonata astfel incat ea ramane ordonata si dupa inserare. Lista este parcursa
cautandu-se primul nod avand campul id mai mare sau egal cu s */

for (q2=q1=lista; q1!=NULL && strcmp(q1->id, s)<0;


q2=q1, q1=q1->urm); /* introduc 2 */

if (q1!=NULL && strcmp(q1->id, s)==0) /* introduc 3 */


/* daca in lista apare un nod avand campul id egal cu s, atunci se afiseaza un mesaj de eroare si se pastreaza
lista nemodificata*/
{
printf("Eroare: %s apare in tabela\n", s);
return lista;
}

if (q1!=q2) /* daca inserarea nu se face la inceputul listei*/


/* introduc 4 */
{
q2->urm=aux;
aux->urm=q1;
return lista ;
}

/* daca inserarea se face la inceputul listei */


/* introduc 5 */
aux->urm=lista;
return aux;
}

/*-------------------------------------------------------------*/
/* */
/*Functia citesc_linie citeste urmatoarea linie de la tastatura si recunoaste identificatorul si valoarea asociata lui. */
/*Identificatorul este returnat in parametrul s, iar valoarea in parametrul val */
/*-------------------------------------------------------------*/
void citesc_linie(char *s, int *val)
{
int i, j;
char temp[Max];

/* citeste urmatoarea linie de la tastatura */


gets(temp); /* citesc_linie 1 */

s[0]='\0'; /* initializeaza valorile argumentelor */


for (i=0; temp[i]!='\0'; )
/* atata timp cat nu a fost atins sfarsitul sirului */
/* citesc_linie 2 */
{
if (isalpha(temp[i])) /* daca incepe un identificator */
/* citesc_linie 3 */
{
j=0;

/* memoreaza identificatorul in s */
while (isalnum(temp[i]))
s[j++]=temp[i++]; /* citesc_linie 4 */

/* memoreaza sfarsitul de sir */


s[j]='\0'; /* citesc_linie 5 */
continue;
}

if (isdigit(temp[i])) /* daca incepe un numar */


/* citesc_linie 6 */
{
*val=0;
while (isdigit(temp[i])) /* citesc_linie 7 */
{
/* calculeaza valoarea numarului */
*val=*val*10+temp[i]-'0' ; /* citesc_linie 8 */
i++;
}
continue;
}

/* altfel se trece peste caracterul curent */


i++; /* citesc_linie 9 */
} /* while */
}
/*----------------------------------------------------------*/
/* */
/* Functia comanda_a realizeaza functionalitatea comenzii a */
/* */
/*----------------------------------------------------------*/
void comanda_a(void)
{
int val;
char s[Max];

citesc_linie(s, &val); /* citeste o linie de la tastatura */


if (strlen(s)!=0) /* daca linia e corecta */
radacina=introduc(radacina, s, val);
else printf("Eroare : linie incorecta\n");
}

/*---------------------------------------------------------*/
/* */
/* Functia comanda_t realizeaza functionalitatea comenzii t */
/* */
/*---------------------------------------------------------*/
void comanda_t(void)
{
int val;
char s[Max];
nod *p;

citesc_linie(s, &val); /* citeste o linie de la tastatura */


if (strlen(s)==0) /* daca linia e incorecta */
{printf("Eroare: linie incorecta\n"); return;}

if ((p=caut(radacina, s))!=NULL) /* cauta nodul in lista */


printf("Identificator:%s Valoare:%d\n", p->id, p->valoare);
else
printf("Eroare: Identificator nedefinit\n");
}
/*---------------------------------------------------------*/
/* */
/* Functia comanda_s realizeaza comanda s */
/* */
/*---------------------------------------------------------*/

void comanda_s(void)
{
char s[Max];
int val;

citesc_linie(s, &val); /* citeste o linie de la tastatura */


if (strlen(s)==0) /* daca linia citita e incorecta */
{printf("Eroare: linie incorecta\n"); return;}

radacina=sterg(radacina, s); /* sterge nodul din lista */


}

/*---------------------------------------------------------*/
/* */
/* Functia comanda_oper executa operatiile legate de */
/* comenzile +, -, *, / */
/* Se citesc cei doi operatori si se executa operatia */
/* dorita. Rezultatul este afisat. */
/* */
/*---------------------------------------------------------*/
void comanda_oper(char c)
{
char s1[Max], s2[Max];
int val;
nod *p1, *p2;

/* se citeste primul operand */


citesc_linie(s1, &val); /* comanda_oper 1 */

/* se citeste al doilea operand */


citesc_linie(s2, &val); /* comanda_oper 2 */

if (strlen(s1)!=0 && strlen(s2)!=0)


if(((p1=caut(radacina, s1))!=NULL) &&
((p2=caut(radacina, s2))!=NULL)) /* comanda_oper 3 */
/* se verifica daca operanzii apar in lista */
{
switch(c) /* functie de tipul comenzii */
{
case '+':
val=p1->valoare+p2->valoare;
break;
case '-':
val=p1->valoare-p2->valoare;
break;
case '*':
val=p1->valoare*p2->valoare;
break;
case '/':
if (p2->valoare!=0)
val=p1->valoare/p2->valoare;
else
printf("Eroare: Impartire la 0\n");
break;
}
printf("Rezultatul operatiei e %d\n", val);
}
else
printf("Operand nedefinit\n");
else
printf("Eroare: linie eronata\n");
}
/*-----------------------------------------------------------*/
/* */
/* Functia meniu afiseaza meniul programului,citeste comanda */
/* si apeleaza subrutina corespunzatoare */
/* */
/*-----------------------------------------------------------*/
void meniu(void)
{
char o;

while(1) /* meniu 1 */
{
clrscr();
/* se afiseaza meniul programului */
puts("a : adauga un identificator si valoarea asociata");
puts("t : tipareste valoarea asociata unui identificator");
puts("s : sterge un identificator");
puts("l : listeaza identificatorii si valorile asociate");
puts("+ : calculeaza suma pentru 2 identificatori");
puts("- : calculeaza diferenta pentru 2 identificatori");
puts("* : calculeaza produsul pentru 2 identificatori");
puts("/ : calculeaza impartirea pentru 2 identificatori");
puts("f : termina programul");
printf("\nOptiunea: ");
o=getche(); /* meniu 2 */
printf("\n\n");

switch (tolower(o)) /* meniu 3 */


{
case 'a':
comanda_a(); break;
case 't':
comanda_t(); break;
case 's':
comanda_s(); break;
case 'l':
listez(); break;
case '+': case '-': case '*': case '/':
comanda_oper(o);
break;
case 'f':
return;
default:
printf("Eroare : Comanda inexistenta\n");
}
printf("\nApasa orice tasta...");
getch();
}
}

/*----------------------------------------------------*/
/* Functia main apeleaza functia meniu */
/*----------------------------------------------------*/
void main(void)
{
meniu();
}

Problema 13:
1. Scrieţi un program de convertire a fiecărui element dintr-o stivă într-un şir de caractere şi invers, salvându-le în una
nouă şi sa se sorteze.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* aceasta structura este apelata structural gresita , din aceasta cauza


aceasta nu va mai lucra in alte compilatoae , am folosito (preluato ) de pe
internet necontrolind daca aceasta structura va lucra si in alte
compilatoare
Greseala consta in faptul ca dupa forma structurala numele structurii
trebuie apelat la sfirsitul acestia, in cazul nostru in cazul apelarii structurii
compilatorul citeste aceasta strutura de 2 ori , adica o denumire prin
faptul ca se repeta este in surplus .
typedef struct node node
{
Int data;
Struct node * next; }
*/

typedef struct node


{
char data ;
struct node* next;
}node;

void push (char c) {


Node temp =
(Node) malloc(sizeof(node));
if (temp == NULL) {
printf("Nu
este posibil sa creezi un nod !");
return;
}
temp->data = c;
temp->next = top;
top = temp;
}

char pop() {
if (top == NULL)
return;
char c = top->data;
Node temp = top;
top = top->next;
free(temp);
return c;
}

void Reverse(char s[], int n) {


int i;
for (i=0; i<n; i++)
push(s[i]);
for (i=0;i<n;i++)
s[i] = pop();
}

int main () {
char str[20];
printf("Introduceti
propozitia ");
gets(str);
Reverse(str,strlen(
str));
printf("Propozitia
inversa: %s",str);
return 0;
}

Concluzie:Am lucrat cu structurile de date liste , care ne-au permis


structurarea datelor in format lista , cu avataje si dezavantaje fata
de aceleasi ( array , grafuri ect) . Asemenea am creat un program
folosindune de stiva si functiele prestabilite pentru ea .
Bibliografie
 Limbajul de programare C". Brian W.Kernighan. Dennis M.Ritchie.
- Liviu Negrescu. ”Limbajul de programare C şi C++” V.1-4. Buc. 1999
- Knuth, D. E. - "Arta programarii calculatoarelor, vol. 1: Algoritmi fundamentali", Ed. Teora, 1999.
- Knuth, D. E. - "Arta programarii calculatoarelor, vol. 2: Algoritmi seminumerici", Ed. Teora, 2000.
- Knuth, D. E. - "Arta programarii calculatoarelor, vol. 3: Sortare si cautare", Ed. Teora, 2001.
- Bacivarov, A.; Nastac, I. - "Limbajul C. Indrumar de laborator", Tipografia UPB, Bucuresti, 1997.
- Bates, J; Tompkins, T. - "Utilizare C++", Ed. Teora 2001.
- Andonie, R.; Gabarcea, I. - "Algoritmi fundamentali. O perspectiva C++", Ed. Libris, 1995.
- Help din Turbo C ++IDE ,versiunea 3.0. 1999
- CORMEN, T. - LEISERSON, CH. - RIVEST, R. : Introducere in algoritmi, Editura Computer Libris. Agora,
Cluj-Napoca, 2000.
- Conspectele la PC 2009 şi SDA-2010
- L.Negrescu.Limbajele C si C++ pentru incepatori.Vol 1 si 2.Ed.Microinformatica.Cluj-N.,1994 si reeditata in
1996 ,1998,2000.
- L.Livovschi,H.Georgescu.Analiza si sinteza algoritmilor. Ed.Enciclopedica, Bucuresti,, 1986.
- I.Ignat, C.Ignat. Structuri de date si algoritmi. Indrumator de laborator. U.T.Pres, 2001.
- Informatica. Îndrumar metodic pentru lucrările de laborator. Marin Şt. Chişinău 2003. UTM

S-ar putea să vă placă și