43
Curs SDA (PC2) Liste simplu înlănțuite (continuare) Iulian Năstac

structuri de date si algiritmi_curs6

Embed Size (px)

DESCRIPTION

SDA

Citation preview

  • Curs SDA (PC2)

    Liste simplu nlnuite (continuare)

    Iulian Nstac

  • 2RecapitulareOperaii ce in de o list nlnuit:

    a) crearea listei nlnuite;b) accesul la un nod oarecare al listei;c) inserarea unui nod ntr-o list

    nlnuit;d) tergerea unui nod dintr-o list

    nlnuit;e) tergerea unei liste nlnuite.

  • 3Lista simplu nlnuit(Recapitulare)

    ntre nodurile listei simplu nlnuite avem o singur relaie de ordonare. Exist un singur nod care nu mai are succesor i un singur nod care nu mai are predecesor. Aceste noduri formeaz capetele listei.

    Vom utiliza doi pointeri spre cele dou capete pe care i notm cu:

    prim - pointerul spre nodul care nu are predecesor ultim - pointerul spre nodul care nu are succesor.

  • 4Pointerul urm definete relaia de succesor pentru nodurile listei. Pentru fiecare nod, el are ca valoare adresa nodului urmtor din list. Excepie face nodul spre care pointeaz variabila ultim (pentru care urmia valoarea zero).

  • 5Observaii:

    Se consider tipul utilizator:typedef struct nod

    { declaraii;struct nod *urm;

    } NOD;

  • 62.2. Accesul la un nod ntr-o list simplu nlnuit

    Putem avea acces la nodurile unei liste simplu nlnuite ncepnd cu nodul spre care pointeaz variabila global prim i trecnd apoi pe rnd de la un nod la altul, folosind pointerul urm.

    O alt metod, mai bun, este aceea de a avea o dat, component a nodurilor, care s aib valori diferite, pentru noduri diferite. O astfel de dat se numete cheiei este de un tip oarecare (uzual se folosete char i int). Funcia returneaz pointerul spre nodul cutat sau zero n cazul n care lista nu conine un nod a crui cheie s aib valoarea indicat de parametrul ei.

    2.1. Crearea unei liste simplu nlnuite(Recapitulare)

  • 7 O cheie se insereaz n tipul utilizator:

    typedef struct nod{ declaraii;tip cheie; /*practic orice tip*/struct nod *urm;

    } NOD;

    Cheia poate fi int, long, double, char, etc.

  • 8(Recapitulare) Se consider tipul utilizator:

    typedef struct nod{ char *cuvant; /*aceasta este cheia */int frecventa;struct nod *urm;

    } NOD;

    Considernd o list simplu nlnuit ale crei noduri au tipul NOD se scrie o funcie care caut, n lista respectiv, nodul pentru care pointerul cuvant are ca valoare adresa unui cuvnt dat.

    Pointerul cuvant joac rol de cheie i se cere s se gseasc nodul a crui cheie pointeaz spre un cuvnt dat.

  • 92.3. Inserarea unui nod ntr-o list simplu nlnuit (Recapitulare)

    ntr-o list simplu nlnuit se pot face inserri de noduri n diferite poziii:

    a) inserare naintea primului nod;b) inserarea naintea unui nod precizat

    printr-o cheie;c) inserarea dup un nod precizat printr-o

    cheie;d) inserarea dup ultimul nod al listei.

  • 10

    2.4. tergerea unui nod dintr-o list simplu nlnuit (Recapitulare)

    Sunt avute n vedere urmtoarele cazuri:

    a) tergerea primului nod al listei simplu nlnuite;

    b) tergerea unui nod precizat printr-o cheie;

    c) tergerea ultimului nod al listei simplu nlnuite.

  • 11

    tergerea primului nod (Recapitulare)

    void spn()

    {

    extern NOD *prim, *ultim;

    NOD *p;

    if (prim == 0) return;

    p = prim;

    prim = prim -> urm;

    elibnod(p);

    if (prim == 0) /* lista este vida */

    ultim = 0;

    }

  • 12

    2.5. tergerea unei liste simplu nlnuite(Recapitulare)

    void sterge_l(){

    extern NOD *prim, *ultim;NOD *p;while(prim)

    {p = prim;prim = prim -> urm;elibnod (p);

    }ultim = 0;

    }

  • 13

    Stiva (Recapitulare)

    O stiv este o list simplu nlnuit gestionat conform principiului LIFO (Last In First Out).

    Conform acestui principiu, ultimul nod pus n stiv este primul nod care este scos din stiv. Stiva, ca i lista obinuit, are dou capete:

    baza stivei vrful stivei

  • 14

    Asupra unei stive se definesc cteva operaii, dintre care cele mai importante sunt:

    1. pune un element pe stiv (PUSH);

    2. scoate un element din stiv (POP);

    3. terge (videaz) stiva (CLEAR).

  • 15

    Coada (Recapitulare) Un alt principiu de gestionare a listelor simplu

    nlnuite este principiul FIFO (First In First Out). Conform acestui principiu, primul element introdus n list este i primul care este scos din list.

    Despre o list gestionat n acest fel se spune c formeaz o coad. Cele doua capete ale listei simplu nlnuite care implementeaz o coad sunt i capetele cozii.

  • 16

    Asupra cozilor (ca i asupra stivelor) se definesc trei operaii:

    a. pune un element n coad;

    b. scoate un element din coad;

    c. tergerea (vidarea) unei cozi.

  • 17

    Lista circular simplu nlnuit

    Lista simplu nlnuit conine:- un nod care nu are succesor (pointeaz ultim);- un nod care nu are predecesor (pointeaz prim).

    Se tie c ntr-o list obinuit: ultim -> urm = 0;

    Dac facem ultim -> urm = prim, atunci rezult o list circular simplu nlnuit.

  • 18

    Observaii:

    ntr-o list circular toate nodurile sunt echivalente.

    Fiecare nod are un succesor i un predecesor.

    ntr-o astfel de list nu avem capete, deci nu sunt necesare variabilele prim i ultim.

  • 19

    Pentru gestiunea nodurilor, se folosete o variabil global care pointeaz spre un nod oarecare al listei pcirc:

    NOD *pcirc;

    unde NOD este tipul comun al nodurilor listei.

  • 20

  • 21

    Listele circulare au o serie de aplicaii:

    operaii cu numere ntregi cu un numr mare de cifre;

    operaii asupra polinoamelor de una sau mai multe variabile;

    alocarea dinamic a memoriei.

  • 22

    Observaii: Funciile malloc i free utilizeaz o zon de

    memorie numit heap organizat ca o list circular.

    Cnd apelm malloc se parcurg nodurile listei pn cnd se gsete o zon de memorie de dimensiune cel puin egal cu cea cerut de apel. Dac zona liber este mare, se divide i partea neutilizat se nlnuie cu celelalte blocuri ale listei.

    Dac nu se gsete o zon de memorie corespunztoare, se ncearc obinerea ei printr-un apel la sistemul de operare.

  • 23

    Observaii:

    Funcia free elibereaz o zon de memorie care se nlnuie la lista circular.

    Dac dou noduri aparin de dou zone de memorie care se nvecineaz, atunci ele se vor concatena formnd o singur zon liber de memorie.

    Se utilizeaz free pentru a elibera o zon de memorie imediat ce nu mai este nevoie de datele din ea.

  • 24

    Operaiile uzuale asupra unei liste circulare sunt:

    1. Crearea unei liste circulare.

    2. Accesul la un nod al unei liste circulare.

    3. Inserarea unui nod ntr-o list circular.

    4. tergerea unui nod dintr-o list circular.

    5. tergerea unei liste circulare.

  • 25

    Crearea unei liste circulareSe utilizeaz funciile de tipul incnod i elibnod

    Paii sunt urmtorii:

    1) La nceput lista circular este vid (pcirc = 0).

    2) Se rezerv zon de memorie (cu malloc) n memoria heap pentru nodul curent.

    3) Exist date de ncrcat? NU se revine din funcie (se face i elibnod); DA se ncarc nodul curent cu datele curente

    (incnod(p)) i se trece la punctul 4;

  • 26

    4) Dac lista: era vid:

    pcirc = p;pcirc -> urm = p;

    nu era vid:p -> urm = pcirc -> urm;pcirc -> urm = p;

    Nodul curent se insereaz dup cel spre care pointeaz pcirc.

    5) Pointerul pcirc pointeaz spre noul nod inserat pcirc = p;

    6) Se reia procesul de la punctul 2.

  • 27

    Accesul la un nod al unei liste circulare

    Definim o funcie acces care caut un nod dup o cheie numeric i returneaz una din valorile:

    pointerul spre nodul cutat;

    0 dac nu exist un astfel de nod.

  • 28

    Considerm declarat tipul structur:

    typedef struct nod{

    declaratii;int cheie; /*practic orice tip*/declaratii;struct nod *urm;

    } NOD;

  • 29

    O posibil soluie:NOD *acces(int c) /* cauta nodul de cheie c (de tip integer)- returneaza pointerul spre nodul respectiv sau 0 daca nu exista un astfel de nod */{ extern NOD *pcirc;NOD *p;p=pcirc;if (p==0) return 0; /* lista vida */do{if (p->cheie == c) return p;p = p->urm;

    } while (p!=pcirc);return 0;}

  • 30

    Inserarea unui nod ntr-o list circular

    Cazuri (pentru care se va prezenta schema logic):

    1. Inserarea naintea unui nod precizat printr-o cheie

    2. Inserarea dup un nod precizat printr-o cheie

  • 31

    Inserarea naintea unui nod precizat printr-o cheie

  • 32

    Inserarea dup un nod precizat printr-o cheie

  • 33

    tergerea unui nod dintr-o list circular

    Pentru o funcie care terge dintr-o list circular un nod precizat printr-o cheie, se pot conveni urmtoarele:

    dac pcirc pointeaz spre nodul care se terge, dup tergere pcirc va pointa spre nodul precedent.

    dac lista devine vid, atunci pcirc=0.

  • 34

    Observaii:

    Funcia de tergere se aseamn cu NOD *ins_i(int c)

    tergerea unui nod se mai poate face i prin precizarea poziiei acestuia fa de un reper (pe care l vom nota cu rep).

  • 35

    typedef struct individ {

    char *nume_cavaler;struct individ *urm;

    }SOLDAT;

  • 36

    Exemplu:

    Funcia eliminare terge din lista circularindicat de pointerul rep cel de-al n-lea nod pornind de la rep i apoi ntoarce noul pointer ctre lista circular, care este precedentul celui ters.

    Pointerul rep (reper) joaca rolul lui pcirc.

  • 37

    SOLDAT *eliminare(SOLDAT *rep, int n) {

    SOLDAT *q,*p;int k=1;

    if(rep==0) return(0); /*cazul in care lista era deja vida*/

  • 38

    if(rep!=rep->urm) /*lista are cel putin doua noduri*/{

    p=rep;while(kurm;k++;}

    q->urm=p->urm;elibnod(p);rep=q;

    }

  • 39

    else /*a ramas cazul in care lista era dintr-un singur nod*/

    {elibnod(rep);rep=0;

    }

    return(rep);}

  • 40

    tergerea unei liste circularevoid sterge_l_c(){

    extern NOD *pcirc;NOD *p,*p1;if ((p=pcirc)==0) return; /*lista vida*/do

    {p1=p;p=p->urm;elibnod(p1);

    } while (p!=pcirc);pcirc=0;

    }

  • 41

    Problema lui Josephus(posibil problem de examen)

    O cetate asediat este aprat de un numr de cavaleri (soldai). Se pune problema de a alege pe unul dintre ei pentru a pleca dup ajutor. Soldaii sunt dispui n cerc (ca ntr-o list circular). Se alege un numr n, dup care pornind de la unul din soldai, se elimin succesiv tot al n-lea soldat pn cnd mai rmne unul singur care pleac n misiune.

  • 42

    Paii algoritmului sunt:

    1) Se pornete cu nodul imediat urmtor celui care conine pointerul spre irul dat i se elimin din list al n-lea nod care urmeaz.

    2) Se execut pasul 1 continund cu nodul imediat urmtor celui ters pn cnd lista se reduce la un singur nod.

  • 43

    Programul rezolv urmtoarele cerine: creaz lista circular spre care

    pointeaz un pointer pcirc. citete un numr n indicat n

    formularea problemei. elimin nodurile listei conform pailor

    1 i 2. afieaz cuvntul din nodul rmas n

    list.