Sunteți pe pagina 1din 39

Liste inlantuite

Conf. dr. Smaranda Belciug


sbelciug@inf.ucv.ro
Liste simplu inlatuite
—  O lista inlantuita este reprezentata printr-o serie de noduri

conectate intre ele, unde fiecare nod este reprezentat de o


structura de date.

—  O lista inlantuita poate sa-si modifice dimensiunea in timpul

rularii programului.
—  Inserarea si stergerea de noduri se face mai rapid cu liste

inlantuite decat cu vectori.

2
Liste simplu inlatuite
—  Fiecare nod dintr-o lista inlantuita contine informatii despre

date.

—  Fiecare nod dintr-o lista inlantuita contine si un pointer care

face legatura cu un alt nod.

3
Liste simplu inlatuite
—  O lista simplu inlantuita se numeste “inlantuita” deoarece

fiecare nod din ea are un pointer prin care se face legatura cu


urmatorul nod din lista.

4
Cum se declara?
—  In primul rand, trebuie sa declaram o structura de date

pentru noduri. De exemplu, urmatoarea structura poate fi


folosita pentru a crea o lista in care nodurile stocheaza date
de tip float.
struct ListNode
{
float value;
struct ListNode *next;
};

5
—  Urmatorul pas este sa declaram un pointer care sa fie capul

listei.
ListNode *head;

•  Odata declarata structura nod si creat capul listei ca

pointer NULL, avem o lista simplu inlantuita vida.

•  Urmatorul pas il reprezinta implementarea operatiilor

listei.

6
Operatii cu liste
—  Vom folosi declararea clasei din slide-ul urmator, care este stocata

in FloatList.h.

7
class FloatList
{
private:
// declaram o structura pentru nod
struct ListNode
{
float value;
struct ListNode *next;
};

ListNode *head; // capul listei - pointer


public:
FloatList(void) // Constructor
{ head = NULL; }
~FloatList(void); // Destructor
void appendNode(float);
void insertNode(float);
void deleteNode(float);
void displayList(void);
};

8
Adaugarea unui nod la o lista
—  A adauga un nod la o lista inlatuita inseamna a-l adauga la finalul listei.

—  Pseudocodul pentru aceasta operatie este prezentat mai jos. Codul C++
urmeaza.

Creeaza un nou nod


Stocheaza date in noul nod
Daca nu exista niciun nod in lista
Nodul este capul listei
Altfel
Parcurge lista pentru a gasi ultimul nod
Adauga nodul la finalul listei

9
void FloatList::appendNode(float num)
{
ListNode *newNode, *nodePtr;

// aloca spatiu pentru noul nod si stocheaza date in el


newNode = new ListNode;
newNode->value = num;
newNode->next = NULL;
// Daca nu sunt noduri in lista
// noul nod va fi capul listei
if (!head)
head = newNode;
else // altfel insereaza nodul la sfarsit
{
// initializeaza nodePtr cu capul listei
nodePtr = head;
// cauta ultimul nod din lista
while (nodePtr->next)
nodePtr = nodePtr->next;
// insereaza nodul ca ultimul nod din lista
nodePtr->next = newNode;
}
}
10
Program

//Acest program face o simpla adaugare intr-o lista inlantuita


#include <iostream.h>
#include "FloatList.h”

void main(void)
{
FloatList List;

list.appendNode(2.5);
list.appendNode(7.9);
list.appendNode(12.6);
}
(Programul nu afiseaza nimic.)

11
Programul pas cu pas
—  Pointerul head este declarat ca variabila globala. head este

automat initializat cu 0 (NULL), ceea ce indica faptul ca lista este


vida.

—  Primul apel al appendNode trimite 2.5 ca argument. In


urmatoarele instructiuni, un nou nod este alocat in memorie, 2.5
este copiat in membrul value iar NULL este atribuit
pointerului next.

12
newNode = new ListNode;
newNode->value = num;
newNode->next = nULL;

13
—  Urmatoarea instructiune este if.
  if (!head)
head = newNode;

—  Nu mai exista instructiuni de executat, asa ca functia main

preia controlul.

14
—  In cel de-al doilea apel al appendNode, 7.9 este

argumentul. Inca o data, se creeaza un nou nod, se atribuie


valoarea lui value si se asigneaza NULL pointerului
next.

15
—  Deoarece head nu mai pointeaza NULL, intram pe
ramura de else.
else // altfel insereaza newNode la final
{
// initializeaza nodePtr cu capul listei
nodePtr = head;
// cauta ultimul nod din lista
while (nodePtr->next)
nodePtr = nodePtr->next;
// insereaza newNode la final
nodePtr->next = newNode;
}

16
—  nodePtr este deja la finalul listei, deci bucla while se

termina imediat. Ultima instructiune nodePtr->next


= newNode; face ca nodePtr->next sa pointeze
catre noul nod. Acest fapt insereaza newNode la finalul
listei.

17
—  A treia oara cand metoda appendNode este apelata, 12.6

este argumentul. Inca o data, primele 3 instructiuni creeaza


un nou cu argumentul stocat ca valoare a lui value.

18
—  Apoi, else se executa. nodePtr pointeaza catre head.

19
—  Atat timp cat nodePtr->next nu este NULL, se

executa while. Dupa prima iteratie, nodePtr va pointa


catre al doilea nod din lista.

20
—  Testul din conditia lui while pica dupa prima iteratie

deoarece nodePtr->next pointeaza acum catre NULL.


Ultima instr uctiune, nodePtr ->next =
newNode; face ca nodePtr->next sa pointeze catre
noul nod. Asa se insereaza newNode la capatul listei.

21
Parcurgerea unei liste
—  Functia displayList parcurge lista, afisand

value a fiecarui nod. Urmatorul pseudocod reprezinta


algoritmul. Codul C++ este pe slide-ul urmator.

Atribuie capul listei unui pointer nod


Atat timp cat pointerul nod nu este NULL
Afiseaza value a nodului la care pointeaza pointerul nod
Atribuie pointerul nod urmtorului nod al listei

22
void FloatList::displayList(void)
{
ListNode *nodePtr;

nodePtr = head;
while (nodePtr)
{
cout << nodePtr->value << endl;
nodePtr = nodePtr->next;
}
}

23
#include <iostream.h>
#include "FloatList.h"

void main(void)
{
FloatList List;

list.appendNode(2.5);
list.appendNode(7.9);
list.appendNode(12.6);
list.displayList();

24
Inserarea unui nod
—  Folosind structura listNode, pseudocodul urmator

prezinta un algoritm pentru gasirea pozitiei corecte de


inserare a unui nod nou.

—  Algoritmul presupune ca nodurile din lista sunt deja

ordonate.

25
Creeaza un nou nod
Stocheaza datele in noul nod
Daca nu sunt noduri in lista
Noul nod va fi capul listei
Altfel
Gaseste primul nod a carei valoare este mai mare sau egala cu noua valoare sau finalul listei.
Insereaza noul nod inaintea celui gasit sau pe ultima pozitie.

26
void FloatList::insertNode(float num)
{
ListNode *newNode, *nodePtr, *previousNode;

// aloca spatiu si stocheaza valoarea


newNode = new ListNode;
newNode->value = num;

// daca nu sunt noduri in lista


// newNode va fi capul listei
if (!head)
{
head = newNode;
newNode->next = NULL;
}
else // altfel insereaza nod {

nodePtr = head;

// sare peste nodurile care au valoarea mai mica decat num


while (nodePtr != NULL && nodePtr->value < num)
{
previousNode = nodePtr;
nodePtr = nodePtr->next;
}

27
// daca noul nod trebuie sa fie primul in lista, il inseram
//inaintea tuturor, daca trebuie sa fie ultimul se insereaza la final
if (previousNode == NULL)
{
head = newNode;
newNode-> = nodePtr;
}
else
{
previousNode->next = newNode;
newNode->next = nodePtr;
}
}
}

28
#include <iostream.h>
#include "FloatList.h”

void main(void)
{
FloatList list;

list.appendNode(2.5);
list.appendNode(7.9);
list.appendNode(12.6);

list.insertNode(10.5);

list.displayList();
}

29
—  In insertNode, un nou nod este creat si argumentul

functiei este copiat in value. Atat timp cat lista are deja
noduri stocate in ea, ramura de else se va executa. Incepe
prin a asigna nodePtr lui head.

30
—  Atat timp cat nodePtr nu este NULL si nodePtr-

>value este mai mica decat num, bucla while va itera.


Pe parcursul acestei iteratii previousNode va pointa
catre acelasi nod ca si nodePtr. nodePtr va pointa mai
apoi catre nodul urmator.

31
—  Inca o data, bucla testeaza conditia. Deoarece nodePtr nu

este NULL si nodePtr->value este mai mica ca num,


bucla itereaza a doua oara. In timpul celei de-a doua iteratii,
atat previousNode cat si nodePtr avanseaza cu un
nod in lista.

32
Stergerea unui nod
—  Un nod se sterge dintr-o lista inaltuita in doi pasi:

—  Se scoate nodul din lista

—  Se sterge nodul din memorie

—  Functia deleteNode incepe in slide-ul urmator.

33
void FloatList::deleteNode(float num)
{
ListNode *nodePtr, *previousNode;

// daca lista e vida nu se face nimic


if (!head)
return;

// dterminam daca nodul pe care vrem sa-l stergem e


//primul
if (head->value == num)
{
nodePtr = head->next;
delete head;
head = nodePtr;
}
34
else
{
// initializa nodePtr cu capul listei
nodePtr = head;

// sarim peste toate nodurile a caror valoare


//e diferita de num
while (nodePtr != NULL && nodePtr->value != num)
{
previousNode = nodePtr;
nodePtr = nodePtr->next;
}

// se face legatura dintre nodul anterior si nodul


// posterior lui
previousNode->next = nodePtr->next;
delete nodePtr;
}
}
35
#include <iostream.h>
#include "FloatList.h“

void main(void)
{
FloatList list;

// Build the list


list.appendNode(2.5);
list.appendNode(7.9);
list.appendNode(12.6);
cout << “Valorile initiale:\n";
list.displayList();
cout << endl;

cout << “Stergem nodul din mijloc.\n";


cout << “Noduri ramase.\n";
list.deleteNode(7.9);
list.displayList();
cout << endl;

36
cout << “Stergem ultimul nod.\n";
cout << “Noduri ramase.\n";
list.deleteNode(12.6);
list.displayList();
cout << endl;

cout << “Stergem ultimul nod ramas.\n";


cout << “noduri ramase.\n";
list.deleteNode(2.5);
list.displayList();
}

37
Variatii ale listelor inlantuite
—  Lista dublu inlantuita

—  Lista circulara inlantuita

38
Pe saptamana viitoare!

39

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