Sunteți pe pagina 1din 7

Capitolul 11 – Liste simplu înlănţuite

Obiectiv: familiarizarea cu noţiunile de alocare dinamică şi folosirea listelor.


Activităţi:
- Prezentarea listelor simplu înlănţuite;
- Prezentarea operaţiilor de bază cu liste simplu înlănţuite (adăugare, căutare, ştergere);

11.1 Noţiuni introductive


O listă simplu înlănţuită este o structură de date ce utilizează alocarea dinamică a
memoriei. Un element al listei se numeşte nod. Fiecare nod al unei liste conţine un câmp care
are rolul de a indica adresa următorului element din listă.
Exemplu:
typedef struct student
{
char nume[20];
float grupa;
struct student *urm; /*campul de inlantuire*/
}nod;
1000 7000 2000
Ionel Mircea Ana
1.2 2.1 1.1
7000 2000 NULL
Figura 11.1 – Exemplu de listă simplu înlanţuită

11.2 Crearea listelor simplu înlănţuite


O lista simplu înlănţuită poate fi creata în felul următor:
• Prin inserare la început;
• Prin inserare la sfârşit;
• Prin inserare ordonată;

Toate operaţiile de inserare a unui nod într-o listă presupun întâi alocarea dinamică a
memoriei pentru nodul ce urmează să se insereze. În cazul în care avem câmpuri de tip şir de
caractere declarate ca şi pointer la char, trebuie alocată memorie şi pentru ele. Pentru alocare
se utilizează funcţia malloc.

nod *p=(nod*)malloc(sizeof(nod));

După alocare urmează introducerea informaţiei utile în câmpurile nodului. Pentru


exemplul considerat:

strcpy(p->nume,”Ionel”);
p->grupa=1.2;
p->urm=NULL;

Toate operaţiile cu liste simplu înlănţuite (inserare, căutare, ştergere,afişare) pornesc de


la primul element al listei. Accesul la un anumit element al listei se face secvenţial, accesând
Programarea Calculatoarelor Capitolul 11 – Liste simplu înlanţuite

nodurile aflate înaintea sa în înlanţuire şi pornind de la primul element al listei. Dacă lista este
vidă primul element indică spre NULL.

În exemplele următoare vom considera că p este nodul care se inserează, q este


pointerul folosit pentru a parcurge lista, prim este primul nod al listei.
11.2.1 Inserarea la început
Nodul se inserează înaintea primului element, deci nodul care îl urmează este primul
element, în urma inserării el devine noul prim.

p->urm=prim;
prim=p;

prim
p
prim
urm urm NULL
urm
Figura 11.2 – Inserarea la început

11.2.2 Inserarea la sfârşit


Întâi se verifică dacă lista este vidă sau nu. Dacă lista este vidă primul nod devine cel
alocat. Altfel se parcurge lista până când se ajunge la ultimul nod. Pentru a putea realiza cu
uşurinţă legătura dintre ultimul nod şi cel care urmează să se insereze lista va fi parcursă cu q-
>urm. Următorul ultimului nod devine nodul alocat.

p->urm=NULL;
if(prim==NULL )
prim=p;
else
{
q=prim;
while(q->urm!=NULL)
q=q->urm;
q->urm=p;
}
prim q p

urm urm urm


Figura 11.3 – Inserarea la sfârşit NULL

11.2.3 Inserarea ordonată a unui nod într-o listă


În situaţia în care se doreşte afişarea ordonată a nodurilor listei în funcţie de informaţia
dintr-un câmp, se poate crea o listă ordonată după informaţia din câmpul respectiv. Câmpul
după care se ordonează elementele din lista se numeşte câmp cheie. Inserarea ordonată a unui
nod într-o listă presupune parcurgerea listei cu scopul găsirii poziţiei în care trebuie inserat
nodul, astfel încât lista să rămână ordonată dupa inserarea lui.

La inserarea ordonată a unui nod într-o listă se disting următoarele situaţii:


• lista este vidă şi nodul inserat devine primul din listă;

2
Programarea Calculatoarelor Capitolul 11 – Liste simplu înlanţuite

• nodul se inserează la începutul listei (devine noul prim);


• nodul se inserează pe parcurs sau la sfârşit în listă;
Exemplu:
if(prim==NULL)
return p; /*inserarea primului nod*/
else
if(strcmp(prim->nume,p->nume)>0)
{
p->urm=prim;/* inserare inainte de primul nod*/
return p;
}
else
{
q=prim;
while(q->urm!=NULL && strcmp(q->urm->nume,p->nume)<0)
q=q->urm;
p->urm=q->urm;/*inserare pe parcurs sau la sfarsit*/
q->urm=p;
return prim;
}
prim q
Alina Mircea Victor
4.2 1.2 3.2
urm urm NULL
p
Paul
1.2
urm
Figura 11.4 – Inserarea ordonată

11.3 Ştergerea unui nod din listă


La şteregea unui nod din listă se disting următoarele situaţii:
• se şterge primul nod (noul prim devine cel care-l urmează);
• se şterge un nod din interiorul listei sau de la sfârşit;

Ştergerea unui nod presupune refacerea legăturilor şi eliberarea memoriei ocupate de


nodul respectiv. Dacă se şterege primul nod, noul prim devine cel care îl urmează. Dacă se
sterge un nod din interiorul listei, trebuie facută legătura dintre nodul dinaintea lui şi nodul
care îl urmează.

nod* stergere(nod *prim,char *nume){


nod *q,*p;

if(prim!=NULL) /*daca lista nu este vida*/


{
if(strcmp(prim->nume,nume)==0)
{
q=prim;
prim=prim->urm; /*stergerea primului nod*/
free(q);
return prim;
}

3
Programarea Calculatoarelor Capitolul 11 – Liste simplu înlanţuite

q=prim;
while(q->urm!=NULL && strcmp(q->urm->nume,nume)!=0)
q=q->urm;
if(q->urm!=NULL && strcmp(q->urm->nume,nume)==0)
{
p=q->urm;
q->urm=q->urm->urm;/*stergerea unui nod din
interiorul listei sau de la sfarsit*/
free(p);
}
return prim;
}
else
{
printf(“\nLista vida!”);
return prim;
}
}

prim q

urm urm urm urm NULL


Figura 11.5 –Ştergerea unui nod din listă

11.4 Parcurgerea listei


Parcurgerea unei liste simplu înlănţuită se realizează plecând de la primul element:
q=prim;
while(q!=NULL)
{
printf("\n%s %1.f",q->nume,q->grupa);
q=q->urm;
}

11.5 Program rezolvat:


Să se scrie un program pentru evidenţa studenţilor unui an de studiu. Pentru rezolvarea
problemei se vor folosi liste simplu înlănţuite. Informaţiile de interes sunt numele studentului
şi grupa. Programul va implementa următoarele operaţii:
1. Introducerea unui student;
2. Afisarea ordonată a studenţilor;
3. Căutare unui student;
4. Ştergerea unui student;

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>

typedef struct student


{
char *nume;
float grupa;
struct student *urm;
}nod;

4
Programarea Calculatoarelor Capitolul 11 – Liste simplu înlanţuite

nod *adauga(nod*prim,char *nume,float grupa)


{
nod *q,*p;

p=(nod*)malloc(sizeof(nod));
p->nume=(char*)malloc(strlen(nume)+1);

strcpy(p->nume,nume);
p->grupa=grupa;
p->urm=NULL;

if(p==NULL || p->nume==NULL)
{
printf("Eroare la alocare!");
exit(0);
}

if(prim==NULL)
return p;
else
if(strcmp(prim->nume,p->nume)>0)
{
p->urm=prim;
return p;
}
else
{
q=prim;
while(q->urm!=NULL && strcmp(q->urm->nume,p->nume)<0)
q=q->urm;
p->urm=q->urm;
q->urm=p;
return prim;
}
}

void afisare(nod *prim){


nod *q;
q=prim;
while(q!=NULL){
printf("\n%s %.1f",q->nume,q->grupa);
q=q->urm;
}
}

nod* cautare(nod *prim,char *nume){


nod *q;
q=prim;
while(q!=NULL && strcmp(q->nume,nume)!=0)
q=q->urm;
return q;
}

nod* stergere(nod *prim,char *nume){


nod *q,*p;

5
Programarea Calculatoarelor Capitolul 11 – Liste simplu înlanţuite

if(prim!=NULL)
{
if(strcmp(prim->nume,nume)==0)
{
q=prim;
prim=prim->urm;
free(q->nume);
free(q);
return prim;
}

q=prim;
while(q->urm!=NULL && strcmp(q->urm->nume,nume)!=0)
q=q->urm;
if(q->urm!=NULL && strcmp(q->urm->nume,nume)==0)
{
p=q->urm;
q->urm=q->urm->urm;
free(p->nume);
free(p);
}
return prim;
}
else
return prim;
}

int main(){
int opt;
nod *prim,*p;
char nume[10];
float grupa;

prim=NULL;
while(1){
clrscr();
printf("\n1. Introducerea unui student");
printf("\n2. Afisarea alfabetica a studentilor
introdusi");
printf("\n3. Cautarea unui student");
printf("\n4. Stergerea unui student");
printf("\n5. Iesire\n");
scanf("%d",&opt);
fflush(stdin);
switch(opt)
{
case 1:printf("Numele:");
gets(nume);
printf("Grupa:");
scanf("%f",&grupa);

prim=adauga(prim,nume,grupa);
break;
case 2:afisare(prim);
break;
case 3:printf("Introduceti numele studentului

6
Programarea Calculatoarelor Capitolul 11 – Liste simplu înlanţuite

cautat:");
gets(nume);
p=cautare(prim,nume);
if(p==NULL)
printf("Studentul nu se gaseste in
lista!");
else
printf("%s %.1f",p->nume,p->grupa);
break;
case 4:printf("Introduceti numele
studentului:");
gets(nume);
prim=stergere(prim,nume);
afisare(prim);
break;
case 5:exit(1);
default:printf("\n1..5!");
}
getch();
}
return 0;
}

11.6 Probleme propuse


1. Într-un depozit se află diverse utilaje. Informaţiile de interes pentru fiecare utilaj sunt:
denumirea, anul de fabricaţie, sectorul de depozitare. Să se scrie un program care
realizează următoarele:
a) Introducerea unui utilaj;
b) Afişarea utilajelor din depozit,
c) Mutarea unui utilaj dintr-un sector în altul;
d) Afisarea în ordine descrescătoare a vechimii, a utilajelor dintr-un sector citit de la
tastatură;
e) Ştergerea unui utilaj;
Pentru rezolvarea problemei se vor utiliza liste simplu inlanţuite.
2. Se consideră o listă simplu înlănţuită. Să se inverseze nodurile listei. (primul devine
ultimul, etc).
3. Se propune realizarea unui program C care să implementeze o stivă utilizând alocarea
dinamică. Elementele stivei sunt reprezentate de adrese (nume stradă şi număr). Se vor
implementa operatorii:
a) push – pune un element în vârful stivei;
b) pop – extrage elementul aflat în vârful stivei;
c) display - afisează conţinutul stivei;

11.7 Intrebări recapitulative


1. Precizaţi care sunt avantajele şi dezavantajele oferite de alocarea dinamică a memoriei
în comparaţie cu alocarea statică a memoriei.
2. Precizaţi care sunt funcţiile care permit alocarea respectiv eliberarea dinamică a
memoriei.
3. Care sunt modalităţile de inserare a unui nod într-o listă? Precizaţi modul de realizare a
legăturilor în toate variantele.
4. Precizaţi modul de refacere al legăturilor la ştergerea unui nod.

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