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; 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 7000 Mircea 2.1 2000 1000 Ionel 1.2 7000 2000 Ana 1.1 NULL Figura 11.1 – Exemplu de listă simplu înlanţuită

Capitolul 11 – Liste simplu înl n uite - aut.upt.rorraul/PC/2009-2010/PC_lab11.pdf · Capitolul 11 – Liste simplu înl ănţuite Obiectiv: familiarizarea cu no ţiunile de alocare

  • Upload
    ngodien

  • View
    216

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Capitolul 11 – Liste simplu înl n uite - aut.upt.rorraul/PC/2009-2010/PC_lab11.pdf · Capitolul 11 – Liste simplu înl ănţuite Obiectiv: familiarizarea cu no ţiunile de alocare

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;

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

7000 Mircea

2.1

2000

1000 Ionel

1.2

7000

2000 Ana

1.1

NULL

Figura 11.1 – Exemplu de listă simplu înlanţuită

Page 2: Capitolul 11 – Liste simplu înl n uite - aut.upt.rorraul/PC/2009-2010/PC_lab11.pdf · Capitolul 11 – Liste simplu înl ănţuite Obiectiv: familiarizarea cu no ţiunile de alocare

Programarea Calculatoarelor Capitolul 11 – Liste simplu înlanţuite

2

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;

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;

}

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ă;

prim

prim

p

urm urm NULL urm

Figura 11.2 – Inserarea la început

p

NULL

prim

urm urm urm

q

Figura 11.3 – Inserarea la sfârşit

Page 3: Capitolul 11 – Liste simplu înl n uite - aut.upt.rorraul/PC/2009-2010/PC_lab11.pdf · Capitolul 11 – Liste simplu înl ănţuite Obiectiv: familiarizarea cu no ţiunile de alocare

Programarea Calculatoarelor Capitolul 11 – Liste simplu înlanţuite

3

• 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;

}

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;

}

Figura 11.4 – Inserarea ordonată

p

urm

prim

urm

Alina 4.2

NULL

Victor 3.2

urm

Mircea 1.2

q

Paul 1.2

Page 4: Capitolul 11 – Liste simplu înl n uite - aut.upt.rorraul/PC/2009-2010/PC_lab11.pdf · Capitolul 11 – Liste simplu înl ănţuite Obiectiv: familiarizarea cu no ţiunile de alocare

Programarea Calculatoarelor Capitolul 11 – Liste simplu înlanţuite

4

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;

}

}

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;

urm

prim

urm

q

urm urm NULL Figura 11.5 –Ştergerea unui nod din listă

Page 5: Capitolul 11 – Liste simplu înl n uite - aut.upt.rorraul/PC/2009-2010/PC_lab11.pdf · Capitolul 11 – Liste simplu înl ănţuite Obiectiv: familiarizarea cu no ţiunile de alocare

Programarea Calculatoarelor Capitolul 11 – Liste simplu înlanţuite

5

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;

Page 6: Capitolul 11 – Liste simplu înl n uite - aut.upt.rorraul/PC/2009-2010/PC_lab11.pdf · Capitolul 11 – Liste simplu înl ănţuite Obiectiv: familiarizarea cu no ţiunile de alocare

Programarea Calculatoarelor Capitolul 11 – Liste simplu înlanţuite

6

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

Page 7: Capitolul 11 – Liste simplu înl n uite - aut.upt.rorraul/PC/2009-2010/PC_lab11.pdf · Capitolul 11 – Liste simplu înl ănţuite Obiectiv: familiarizarea cu no ţiunile de alocare

Programarea Calculatoarelor Capitolul 11 – Liste simplu înlanţuite

7

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.