Il 0% ha trovato utile questo documento (0 voti)
2 visualizzazioni41 pagine

Handouts 4

Il documento descrive le liste concatenate, strutture dati che rappresentano collezioni di oggetti tramite nodi concatenati. Vengono illustrate le operazioni fondamentali sulle liste concatenate come il calcolo della lunghezza, l'inserimento e la cancellazione di elementi.

Caricato da

Pietro Matta
Copyright
© © All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Il 0% ha trovato utile questo documento (0 voti)
2 visualizzazioni41 pagine

Handouts 4

Il documento descrive le liste concatenate, strutture dati che rappresentano collezioni di oggetti tramite nodi concatenati. Vengono illustrate le operazioni fondamentali sulle liste concatenate come il calcolo della lunghezza, l'inserimento e la cancellazione di elementi.

Caricato da

Pietro Matta
Copyright
© © All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Sei sulla pagina 1/ 41

Corso “Programmazione 1”

Capitolo 11: Liste Concatenate

Docente: Marco Roveri - [email protected]


Esercitatori: Giovanni De Toni - [email protected]
Stefano Berlato - [email protected]
C.D.L.: Informatica (INF)
A.A.: 2021-2022
Luogo: DISI, Università di Trento
URL: https://bit.ly/2VgfYwJ
Ultimo aggiornamento: 15 novembre 2021

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 1


Terms of Use and Copyright

USE
This material (including video recording) is intended solely for students of the University of Trento
registered to the relevant course for the Academic Year 2021-2022.
SELF-STORAGE
Self-storage is permitted only for the students involved in the relevant courses of the University of
Trento and only as long as they are registered students. Upon the completion of the studies or their
abandonment, the material has to be deleted from all storage systems of the student.
COPYRIGHT
The copyright of all the material is held by the authors. Copying, editing, translation, storage,
processing or forwarding of content in databases or other electronic media and systems without
written consent of the copyright holders is forbidden. The selling of (parts) of this material is
forbidden. Presentation of the material to students not involved in the course is forbidden. The
unauthorised reproduction or distribution of individual content or the entire material is not permitted
and is punishable by law.

The material (text, figures) in these slides is authored by Marco Roveri.

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 2


Introduzione

Quando dobbiamo scandire una collezione di oggetti in modo sequenziale e non


sequenziale, un modo conveniente per rappresentarli è quello di organizzare gli
oggetti in un array.
Esempi:
{1, 2, -3, 5, -10} è una sequenza di interi.
{’a’, ’d’, ’1’, ’F’} è una sequenza di caratteri.
Una soluzione alternativa all’uso di array per rappresentare collezioni di oggetti
quando l’accesso non sequenziale non è un requisito, consiste nell’uso delle
cosiddette liste concatenate.
In una lista concatenata i vari elementi che compongono la sequenza di dati sono
rappresentati in zone di memoria che possono anche essere distanti fra loro (al
contrario degli array, in cui gli elementi sono consecutivi).
In una lista concatenata, ogni elemento contiene informazioni necessarie per
accedere all’elemento successivo.
© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 3
Liste concatenate

Una lista concatenata è un insieme di oggetti, dove ogni oggetto è inserito in un nodo
contenente anche un link ad un altro nodo.

// Lista concatenata di interi Campo contenente


struct nodo { informazioni del nodo
int dato;
nodo * next;
} Puntatore al nodo
successivo

dato

Elemento 1 Elemento 2 Elemento 3

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 4


Liste concatenate (II)
Per il nodo finale si possono adottare diverse convenzioni:

Punta ad un link nullo che non punta a nessun nodo (e.g. <val> = NULL)

Elemento 1 Elemento 2 Elemento 3 NULL

Punta ad un nodo fittizio che non contiene alcun nodo (e.g. <val> = (nodo *)300)

Elemento 1 Elemento 2 Elemento 3 (nodo *)300

Punta indietro al primo elemento della lista, creando una lista circolare

head
Elemento 1 Elemento 2 Elemento 3

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 5


Operazioni su liste concatenate

Calcolo della lunghezza di una lista concatenata.


Inserimento di un elemento in una lista concatenata, aumentando la lunghezza di una
unità.
Cancellazione di un elemento in una lista concatenata, diminuendo la lunghezza di
una unità.
Rovesciamento di una lista.
Append: concatenazione di due liste.

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 6


Calcolo lunghezza di una lista

s El 1 El 2 El 3 El 4 El 5 NULL

s L=0
s L=1
s L=2
s L=3
s L=4
s L=5

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 7


Calcolo lunghezza di una lista (II)
// lista con terminatore NULL
int length (nodo * s) {
int l = 0;
for( ; s != NULL; s = s->next) l++;
return l;
}

// lista circolare, x primo elemento


int length (nodo * s, nodo * x) {
int l = 0;
if (s != NULL) {
l = 1;
for( s = s->next; s != x; s = s->next) l++;
}
return l;
}
© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 8
Inserimento di un elemento

Per inserire un nodo t in una lista concatenata nella posizione successiva a quella
occupata da un dato nodo x, poniamo t->next a x->next, e quindi x->next a t.
x x
1 2 3 NULL 1 2 3 NULL

4 NULL 4

t t
x
1 2 3 NULL

t
© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 9
Inserimento di un elemento (II)
t->next inizializzato a x->next

x->next inizializzato a t

void insert_node(nodo * x, nodo *t) {


t -> next = x -> next;
x -> next = t;
}

Assunzione che sia x che t


siano diversi da NULL

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 10


Inserimento di un elemento (II)
int main () { Allocazione di un nodo per
nodo * x = new nodo; memorizzare primo elemento
cout << "Inserire numero: ";
cin >> x->dato; Allocazione di un nuovo nodo per
x->next = NULL; memorizzare i-esimo elemento
for (int i = 0; i < 10; i++) {
nodo * t = new nodo; Campo next di t inizializzato a
NULL
cout << "Inserire un numero: ";
cin >> t->dato;
t->next = NULL; Inserzione del nuovo elemento t
insert_node(x, t); successivamente al nodo iniziale x
}
for (nodo *s =x; s != NULL; s=s->next)
cout << "valore = " << s->dato << endl;
} Variabile temporanea
per scorrere lista
Manca deallocazione della lista!!!
© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 11
Inserimento di un elemento in testa

Si vuole inserire un nuovo elemento 26 in testa alla lista!


p 1 13 2 67 NULL
node *q = new nodo;
q q->dato = 26;
26 NULL

p 1 13 2 67 NULL
q->next = p;
q 26

p 1 13 2 67 NULL
p = q;
q 26

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 12


Inserimento di un elemento in testa (II)

Se dobbiamo inserire un elemento in testa della lista:


- void insert_first(nodo * s, int v);
- void insert_first(nodo * &s, int v);
- nodo * insert_first(nodo * s, int v);
La seconda e la terza sono le uniche possibili dichiarazioni corrette.
- Nella seconda side effect sull’argomento.
- Nella terza lista nuova ritornata dalla funzione.

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 13


Inserimento di un elemento in testa (III)
void insert_first(node * s, int v) {
node * n = new node;
n->dato = v;
n->next = s;
s = n;
}

void insert_first(node*&s, int v) {


node * n = new node;
n->dato = v; node * insert_first(node*s, int v) {
n->next = s; node * n = new mode;
s = n; n->dato = v;
} n->next = s;
return n;
}

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 14


Inserimento di un elemento in coda

Si vuole inserire un nuovo elemento 26 in coda alla lista!

p 1 13 2 NULL node *q = p;
while(q->next != NULL)
q q = q->next;

p 1 13 2
q->next = new node;
q

p 1 13 2 26 NULL
q->next->dato = 26;
q q->next->next = NULL;

Nota:
Questo ragionamento è corretto solo se la lista non è vuota!!!
© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 15
Inserimento di un elemento in coda (II)
void insert_last(nodo * & p, int n) {
nodo * r = new nodo; Allocazione del nuovo nodo
r->dato = n;
r->next = NULL; Se la lista non è vuota, cerco in q il
if (p != NULL) { puntatore all’ultimo elemento
node * q = p;
while(q->next != NULL) { q è garantito essere diverso da
NULL
q = q->next;
}
q->next = r; Memorizzo in q->next il nuovo
} nodo r allocato in precedenza
else {
p = r; Se la lista è vuota, p punta al nuo-
} vo nodo allocato: p è passato per
} riferimento

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 16


Inserimento di un elemento in lista ordinata

Si vuole inserire un nuovo elemento 26 in una lista ordinata mantenendo ordinamento!

p 3 16 32 NULL node *q = p;
while(q->next->dato <= 26)
q q = q->next;

p 3 16 32 NULL node *r = new node;


r->dato = 26;
q r 26 r->next = q->next;

p 3 16 32 NULL
q->next = r;
q r 26

Nota:
Devono essere considerati alcuni casi limite!!!
© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 17
Inserimento di un elemento in lista ordinata (II)

Primo caso limite: inserimento in testa


perchè la lista è vuota: p == NULL
perchè tutti gli elementi hanno un valore maggiore

p if ((p == NULL) || (p->dato >= 26))


32 53 NULL insert_first(p, 26);

Secondo caso limite: inserimento in coda


perchè tutti gli elementi hanno un valore minore

p 3 16 NULL node *q = p;
while(q->next != NULL &&
q->next->dato <= 26)
q q = q->next;

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 18


Inserimento di un elemento in lista ordinata (III)
void insert_order(nodo * &p, int inform){
if ((p==NULL) || (p->dato >= inform)) {
insert_first(p, inform);
}
else {
nodo* q=p;
while ((q->next != NULL) &&
(q->next->dato <= inform)) {
q=q->next;
}
nodo* r = new nodo;
r->dato = inform;
r->next = q->next;
q->next = r;
}
}

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 19


Rimozione di un elemento

Per rimuovere un nodo y in una lista concatenata nella posizione successiva a quella
occupata da un dato nodo x, cambiamo x->next a y->next.
x y x

1 2 3 NULL 1 3 NULL

2 NULL

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 20


Rimozione di un elemento (II)

y inizializzato a x->next

node * remove_element(node *x) {


node * y = x->next; x->next punta a y->next
x->next = y->next;
y->next = NULL;
return y; Assunzione che x, x->next (e
} quindi anche y) siano diversi da
NULL

y ritornato per ad esempio essere


deallocato!

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 21


Rimozione di un elemento (II)
int main () {
nodo * x = new nodo;
cout << "Inserire numero: ";
cin >> x->dato
x->next = NULL;
for (int i = 0; i < 10; i++) { Variabile temporanea per
nodo * t = new nodo; memorizzare nodo rimosso!
cout << "Inserire un numero: ";
cin >> t->dato
t->next = NULL;
insert_node(x, t);
}
for ( int i = 0; i < 10; i++) {
nodo * t = remove_element(x);
cout << "valore = " << t->dato << endl;
delete t; Deallocazione del nodo rimosso
}
delete x;
} Deallocazione del nodo x iniziale

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 22


Rimozione di un elemento in testa

Si vuole eliminare primo elemento della lista!

p
1 13 2 67 NULL node *q = p;
q

p
1 13 2 67 NULL p = p->next;
q

p
13 2 67 NULL delete q;
q NULL

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 23


Rimozione di un elemento in testa (II)

Se dobbiamo rimuovere un elemento in testa della lista:


- void remove_first(nodo * s);
- void remove_first(nodo * &s);
- nodo * remove_first(nodo * s);
La seconda e la terza sono le uniche possibili dichiarazioni corrette.
- Nella seconda side effect sull’argomento.
- Nella terza lista nuova ritornata dalla funzione.

Nota:
Il nodo rimosso deve essere deallocato!!!

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 24


Rimozione di un elemento in testa (III)
void remove_first(nodo * s) {
nodo * n = s;
if (s != NULL) {
s = s->next;
delete n;
}
}

void remove_first(nodo * & s) {


nodo * n = s;
if (s != NULL) { nodo * remove_first(nodo * s)
s = s->next; {
delete n; nodo * n = s;
} if (s != NULL) {
} s = s->next;
delete n;
}
return s;
} // attenzione a come invocata
© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 25
Rimozione di un elemento particolare

Si vuole cercare un nodo che contiene nel campo dato un valore ed eliminarlo!

p 1 2 26 13 NULL
nodo* q=p;
q

while(q->next!=NULL){
if(q->next->dato==26){

}
q=q->next;
}

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 26


Rimozione di un elemento particolare

Si vuole cercare un nodo che contiene nel campo dato un valore ed eliminarlo!

p 1 2 26 13 NULL
nodo* q=p;
q

p 1 2 26 13 NULL while(q->next!=NULL){
if(q->next->dato==26){
q r node *r = q->next;

}
q=q->next;
}

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 27


Rimozione di un elemento particolare

Si vuole cercare un nodo che contiene nel campo dato un valore ed eliminarlo!

p 1 2 26 13 NULL
nodo* q=p;
q

p 1 2 26 13 NULL while(q->next!=NULL){
if(q->next->dato==26){
q r node *r = q->next;
q->next = q->next->next;

}
q=q->next;
}

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 28


Rimozione di un elemento particolare

Si vuole cercare un nodo che contiene nel campo dato un dato valore ed eliminarlo!

p 1 2 26 13 NULL
nodo* q=p;
q

p 1 2 26 13 NULL while(q->next!=NULL){
if(q->next->dato==26){
q r node *r = q->next;
q->next = q->next->next;
p 1 2 13 NULL delete r;

q NULL r }
q=q->next;
}

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 29


Rimozione di un elemento particolare

Si vuole cercare un nodo che contiene nel campo dato un valore ed eliminarlo!

p NULL if (p != NULL) {
nodo* q=p;

while(q->next!=NULL){
if(q->next->dato==26){
node *r = q->next;
q->next = q->next->next;
delete r;

}
Nota: q=q->next;
Primo caso limite: Lista vuota!!! }
}

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 30


Rimozione di un elemento particolare

Si vuole cercare un nodo che contiene nel campo dato un valore ed eliminarlo!

p 26 2 16 13 NULL if (p != NULL) {
nodo* q=p;
q if (p->dato == 26) {
p = p->next; delete q;
}
p 26 2 16 13 NULL while(q->next!=NULL){
if(q->next->dato==26){
q node *r = q->next;
q->next = q->next->next;
p 2 16 13 NULL delete r;

q NULL }
q=q->next;
Nota: }
Secondo caso limite: primo nodo da levare!!!
}

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 31


Rimozione di un elemento particolare

Si vuole cercare un nodo che contiene nel campo dato un valore ed eliminarlo!

p 1 2 26 NULL if (p != NULL) {
nodo* q=p;
q if (p->dato == 26) {
p = p->next; delete q;
}
p 1 2 26 NULL while(q->next!=NULL){
if(q->next->dato==26){
q r node *r = q->next;
p 1 2 NULL q->next = q->next->next;
delete r;
q r NULL return;
}
q=q->next;
Nota: }
Terzo caso limite: ultimo nodo da levare!!! }

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 32


Rimozione di un elemento particolare (II)
void search_remove(nodo* &p, int val){
if (p != NULL) {
nodo* q = p;
if (q->dato == val) {
p = p->next;
delete q;
}
else {
while(q->next != NULL) {
if (q->next->dato == val) {
nodo* r = q->next;
q->next = q->next->next;
delete r;
return;
}
if (q->next != NULL) {
q=q->next;
}
}
}
}
}
© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 33
Rovesciamento di una lista concatenata
La funzione di rovesciamento inverte i link di una lista concatenata:
restituisce un puntatore al nodo finale che a sua volta punta al penultimo e così via.
Il link del primo elemento della lista è posto a NULL.

NULL
x 1 2 3 NULL 1 2 3 NULL
r NULL y t r y t NULL

NULL NULL
x 1 2 3 NULL 1 2 3
r y t
r y NULL
t NULL

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 34


Rovesciamento di una lista concatenata (II)

La funzione di rovesciamento inverte i link di una lista concatenata:


restituisce un puntatore al nodo finale che a sua volta punta al penultimo e così via.
Il link del primo elemento della lista è posto a NULL.
node * reverse(node * x) {
node * t; x 1 2 3 NULL
node * y = x;
node * r = NULL; r NULL y t
while ( y != NULL ) {
t = y->next; NULL
y->next = r; x 1 2 3 NULL
r = y;
y = t; r y t
}
return r;
}

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 35


Liste doppiamente concatenate

Sono una estensione della definizione delle liste concatenate


Differiscono per la presenza di un ulteriore puntatore al nodo che lo precede

12 99 37

struct node {
int n;
node * prev;
node * next;
};

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 36


Rimozione di un nodo in una lista doppiamente concatenata

12 99 37

12 99 37

12 99 37

12 99 37

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 37


Inserimento di un nodo in una lista doppiamente concatenata

Soluzione 1:
node * remove(node * t) {
t->next->prev = t->prev;
t->prev->next = t->next;
t->next = t->prev = NULL;
return t;
}
Soluzione 2:
void remove(node * t) {
t->next->prev = t->prev;
t->prev->next = t->next;

delete t;
}

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 38


Inserimento di un nodo in una lista doppiamente concatenata

12 37

12 99 37

x t

12 99 37

x t

12 99 37

x t

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 39


Inserimento di un nodo in una lista doppiamente concatenata

void insert_node(node * x, node * t) {


t->next = x->next;
t->next->prev = t;
t->prev = x;
x->next = t;
}

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 40


Esercizi proposti

Vedere file ESERCIZI_PROPOSTI.txt

© Marco Roveri et al. Cap. 11: Liste Concatenate 15 novembre 2021 41

Potrebbero piacerti anche