Documente Academic
Documente Profesional
Documente Cultură
Structuri de date statice i dinamice Tipul pointer Utilizarea pointerilor Pointeri structuri i tablouri Alocarea dinamic a memoriei Liste liniare simplu nlnuite Liste ordonate Liste dublu nlnuite Liste multiplu nlnuite
Pointeri
Tipul pointer
Un pointer este o variabil care are ca valoare o adres de memorie. Spunem c variabila pointer indic locaia de memorie de la adresa pe care o conine. Cel mai comun caz este acela n care valoarea unei variabile pointer este adresa unei alte variabile. n C, pointerii se refer la un anumit tip: tipul datelor coninute n locaia de memorie indicat de variabila pointer. => O variabil pointer n C este de regul pointer la un anumit tip.
Pointeri
Tipul pointer
Declararea variabilelor pointer se face n felul urmtor: tip * nume_variabila_pointer; variabila nume_variabila_pointer conine adrese de zone de memorie alocate datelor de tipul tip. * semnific faptul c variabila este de tip pointer la tipul respectiv. De exemplu, int *p; definete o variabil p pointer la ntreg. Variabila p poate conine adrese de locaii n care se memoreaz valori ntregi.
Pointeri
Tipul pointer
Declaraiile variabilelor pointer la un anumit tip pot s apar n aceeai list cu alte variabile obinuite de acel tip: int x, *p; definete o variabil x de tip ntreg i o variabil p de tip pointer la ntreg. Se pot declara i pointeri generici, de tip void * ( tipul datelor indicate de ei nu este cunoscut). Un pointer de tip void reprezint doar o adres de memorie a unui obiect oarecare: - dimensiunea zonei de memorie indicate i interpretarea informaiei nu sunt definite; - poate apare n atribuiri, n ambele sensuri, cu pointeri de orice alt tip; - folosind o conversie explicit de tip cu operatorul cast : (tip *), el poate fi convertit la orice alt tip de pointer(pe acelai calculator, toate adresele au aceeai lungime).
Pointeri
Utilizare operatorii de adresare i derefereniere
Ca i n cazul variabilelor de orice tip, i variabilele pointer declarate i neiniializate conin valori aleatoare. Pentru a atribui variabilei p valoarea adresei variabilei x, se folosete operatorul de adres ntr-o expresie de atribuire de forma: p=&x; n urma acestei operaii, se poate spune c pointerul p indic spre variabila x. Pentru a obine valoarea obiectului indicat de un pointer se utilizeaz operatorul de derefereniere (indirectare) (operatorul *): Dac p este o variabil de tip pointer care are ca valoare adresa locaiei de memorie a variabilei ntregi x (p indic spre x) atunci expresia *p reprezint o valoare ntreag (valoarea variabilei x).
Pointeri
Utilizare operatorii de adresare i derefereniere
int x, *p; x=3; p=&x; printf("%d", *p); *p=5; printf("%d", x); Expresia *p care se afieaz cu primul printf reprezint valoarea obiectului indicat de p, deci valoarea lui x. Se va afia valoarea 3. Atribuirea *p=5; modific valoarea obiectului indicat de p, adic valoarea lui x. Ultimul printf din secven afieaz 5 ca valoare a lui x.
Pointeri
Utilizare operatorii de adresare i derefereniere
ntotdeauna cnd se aplic operatorul * asupra unui pointer ptr declarat ca i tip * ptr; expresia obinut prin derefereniere (*ptr) este de tipul tip. n cazul unui pointer generic (de tip void *), dereferenierea trebuie precedat de cast (altfel nu tim ce tip de valori indic pointerul). Cnd se utilizeaz operatorul de derefereniere trebuie avut grij ca variabila pointer asupra creia se aplic s fi fost iniializat, adic s conin adresa unei locaii de memorie valide. O secven ca cea de mai jos este incorect i poate genera erori grave la execuie: int *p; *p=3; Pentru a indica adres inexistent, se utilizeaz ca valoare a unui pointer, constanta NULL.
Pointeri
Utilizare operatorii de adresare i derefereniere Variabilele pointer pot fi utilizate n expresii i direct (fr operaia de indirectare): int x, *p1, *p2; x=3; p1=&x; p2=p1; /* atribuire de pointeri */ Atribuirea p2=p1; copiaz coninutul lui p1 n p2, deci p2 va fi fcut s indice spre acelai obiect ca i p1. n contextul secvenei, p2 va indica tot spre x.
Pointeri
Pointeri i structuri
Operatorul de derefereniere poate avea i o alt reprezentare n cazul pointerilor la structuri. struct ts { int x; ... } i variabilele struct ts structura, *pstructura; ... pstructura = &structura; Pentru a selecta cmpul x al structurii indicate de pstructura, se poate scrie: (*pstructura). x sau, mai concis: pstructura -> x
Pointeri
Pointeri ca argumente de funcii
Modul implicit de transmitere a parametrilor funciilor n C este prin valoare: void schimba1(int x, int y) { int aux ; aux = x; x = y; y = aux ; } schimba1(a,b) /* schimb doar copiile lui a i b */ Pointerii permit accesul direct la locaia de memorie a unui argument. void schimba2(int *x, int *y) { int aux ; aux = *x; *x = *y; *y = aux ;} schimba2(&a, &b) / * schimb valorile variabilelor a i b * /
Pointeri
Pointeri i tablouri
n limbajul C, numele unui tablou este echivalent cu un pointer care conine adresa primului su element. Fie urmtoarele declaraii: tab un tablou de elemente de tip T i p un pointer la tipul T: T tab[N]; T * p; Cele 3 atribuiri urmtoare sunt echivalente, si au ca efect faptul c p va indica adresa primului element al tabloului tab: p=tab; p=&tab; p=&tab[0]; Atribuirea tab=p; nu este permis. Numele tabloului indic o adres constant: adresa primului element al tabloului este o valoare constant din momentul n care tabloul a fost alocat static, deci nu mai poate fi modificat printr-o atribuire ca cea de mai sus.
case 'a':
void AfisezMeniu(void) { puts("\ni ----- adaugare inceput"); puts("\ns ----- adaugare sfarsit"); puts("\na ----- afisare lista"); puts("\nc ----- cautare nod in lista"); puts("\nx ----- parasire program"); }
Liste ordonate
Principii
Listele ordonate se construiesc de la bun nceput ordonate, plecnd de la faptul c lista vid este n mod intrinsec ordonat, iar nodurile ulterioare se insereaz astfel nct s nu se strice ordinea deja existent. Transpunerea direct a metodelor utilizate, cu succes, la tablouri sau fiiere, n cazul listelor nlnuite este, cel mai adesea, total nerecomandabil.
Liste ordonate
Exemplu de program
Programul anterior se completeaz cu cerina ca afiarea persoanelor s fie fcut ntotdeauna n ordine alfabetic. Cel mai bine ar fi ca lista s fie pstrat n permanen ordonat alfabetic dup nume. Orice operaie de adugare a unei noi persoane va trebui s in cont de ordonarea listei i s insereze noul element la locul potrivit. n plus, faptul c lista este ordonat crete performana operaiilor de cutare dup nume n list. Cmpul care servete la identificarea nodurilor i asupra cruia opereaz criteriul de ordonare este numit cmpul cheie (cmpul nume din program).
Liste ordonate
Exemplu de program
Cutarea unui element ntr-o list ordonat Cutarea unui element cu o cheie dat ntr-o list ordonat se face traversnd lista atta timp ct nu s-a ajuns la sfritul listei (p!=NULL) i cheile din nodurile curente sunt mai mici dect cheia cutat (strcmp(p->nume,nume)<0). n cazul n care nu exist n list un nod cu cheia cutat, n cele mai multe cazuri nu se mai ajunge cu parcurgerea listei pn la sfritul ei, ci cutarea se oprete n momentul ntlnirii primului nod care are cheia mai mare dect cheia cutat.
Liste ordonate
Exemplu de programcutarea unui element
persoana* cauta_ordonat(char *nume) { /*Cauta daca este prezenta o persoana cu numele dat. Daca da, returneaza un pointer la nodul in care se gaseste; Daca nu, returneaza NULL */ persoana *p; for (p=lista; p!=NULL && strcmp(p->nume,nume)<0; p=p->urm) ; if (p!=NULL && strcmp(p->nume,nume)==0) return p; else return NULL; }
Liste ordonate
Exemplu de program
Inserarea unui element ntr-o list ordonat Adugarea unui nou element la lista aflat n stare ordonat se face astfel nct lista s rman ordonat i dup adugarea noului element. Pentru aceasta se face o cutare a poziiei de inserare n list: noul nod va fi inserat naintea primului nod care are cheia mai mare dect cheia lui. Se utilizeaz un pointer curent q1 care avanseaz n list, atta timp ct nodurile curente au chei mai mici dect noua cheie de inserat i nu s-a ajuns la sfritul listei. Dac q1 s-a oprit pe primul nod cu cheie mai mare dect cheia de inserat, noul nod trebuie inserat naintea nodului q1. Este necesar deci accesul i la nodul anterior lui q1, pentru a putea reface legturile. Se utilizeaz pentru aceasta tehnica parcurgerii listei cu 2 pointeri, q1 i q2, q2 fiind tot timpul cu un pas n urma lui q1.
Liste ordonate
Cazurile 1 i 2
nou null lista q2
h
nou lista q2
h
...
nou->urm=lista; lista=nou;
...
Liste ordonate
Cazurile 1 i 2
nou lista q2
null
nou
lista
q2
h
...
nou->urm=lista; lista=nou;
...
Liste ordonate
Cazurile 3 i 4
nou lista q2
h
nou lista
f
q2
h
...
null
Liste ordonate
Cazurile 3 i 4
nou lista q2
h
nou lista
f
q2
h
...
null
Liste ordonate
Exemplu de programinserarea unui element
void adauga_ordonat(void) { /* se va insera in lista in ordinea alfabetica a numelui */ char nume[100], adr[100]; int varsta; persoana *nou, *q1, *q2; printf("introduce numele, varsta si adresa \n"); scanf("%s %d %s", nume, &varsta, adr); /* aloca spatiu pentru noul nod */ if(((nou=(persoana *)malloc(sizeof(persoana)))==NULL)|| ((nou->nume=(char *)malloc(strlen(nume)+1))==NULL)|| ((nou->adresa=(char *)malloc(strlen(adr)+1))==NULL)) { printf("\n Eroare alocare memorie \n"); exit(1); }
Liste ordonate
Exemplu de programinserarea unui element
/*copiaza informatiile in nod */ strcpy(nou->nume,nume); strcpy(nou->adresa, adr); nou->varsta=varsta; /* introduce noul nod in lista,cauta locul de insertie */ for(q1=q2=lista;q1!=NULL&&strcmp(q1->nume, nume)<0; q2=q1, q1=q1->urm) ;
Liste ordonate
Exemplu de program inserarea unui element
if (q1!=NULL && strcmp(q1->nume, nume)==0) { printf("Eroare: %s apare deja in lista\n", nume); return; } else if (q1!=q2) { /* inserarea nu se face la inceput - cazurile 3 si 4*/ q2->urm=nou; nou->urm=q1; } else { /* inserarea se face la inceputul listei cazurile 1 si 2 */ nou->urm=lista; lista=nou; } }
Liste ordonate
Exemplu de program
Eliminarea unui element dintr-o list ordonat Eliminarea unui nod din lista ordonat se face la fel ca i n cazul listei neordonate, difer doar modul de localizare a nodului ce trebuie ters: n cutare se tine cont de faptul c lista este ordonat i cutarea se face doar atta timp ct nodurile curente au cheia mai mic dect cheia cutat. void sterge_ordonat(void) { /* scoate din evidenta o persoana */ char nume[100]; persoana *q1,*q2; printf("Introd numele "); scanf("%s",&nume);
for(q1=q2=lista;q1!=NULL&&strcmp(q1->nume,nume)<0;
q2=q1,q1=q1->urm) ;
Liste ordonate
Exemplu de programeliminarea unui element
if (q1!=NULL && strcmp(q1->nume,nume)==0) { if (q1==lista) /* sterge capul listei */ lista=q1->urm; else /* sterge un nod din interiorul listei */ q2->urm=q1->urm; free(q1->nume); free(q1->adresa); free(q1); return; } /* aici se ajunge daca numele nu a fost gasit */ printf("Stergere: %s nu a fost gasit in lista \n",nume); }
void adauga_nume(persoana *nou) { persoana *q1,*q2; for(q1=q2=lista_nume; q1!=NULL && strcmp(q1->nume, nou->nume)<0; q2=q1, q1=q1->urm_nume); nou->urm_nume = q1; if(q1 == q2 ) lista_nume=nou; else q2->urm_nume = nou; }