• Non ci sono risultati.

il tipo di dato

N/A
N/A
Protected

Academic year: 2021

Condividi "il tipo di dato"

Copied!
18
0
0

Testo completo

(1)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 1

strutture dinamiche collegate (liste, pile, code)

obiettivi di questa seconda metà del corso fare un passo avanti rispetto a :

• ...

• meccanismi di composizione dei dati

– puntatori ( strutture dinamiche collegate)

• motivazione : rappresentare sequenze “dinamiche” di elementi omogenei

il tipo di dato lista

– sequenza : insieme di elementi linearmente ordinato

• 1°, 2°, 3°, ... , n°, …

– dinamica : composizione variabile nel tempo

• inserzione/rimozione in qualsiasi posizione – p.es. per mantenere ordinata la sequenza

– omogenea : elementi della sequenza dello stesso tipo

• come rappresentare una lista in C++ ?

– quale meccanismo?

(2)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 3

• • •

0 1

N-1

• • •

...

...

• meccanismo array?

– elementi omogenei

– sequenza “naturalmente ordinata”

• indici dellʼarray – dinamismo?

– a) aggiungere un nuovo

elemento? – non cʼè spazio

– rimedio:

“sovradimensionare”

lʼarray

0 1

N-1

• • •

• • •

• • •

– b) rimuovere un

elemento? – si crea un “buco”

– rimedio: traslare parte dellʼarray

operazioni

“costose”

• meccanismo puntatori?

– a) aggiungere un nuovo elemento?

prec succ

“valore”

elemento

– elementi omogenei

– sequenza naturalmente ordinata

• relazioni di precedente/successore – dinamismo?

“valore”

elemento

“valore”

elemento

“valore”

elemento

“valore”

elemento

X X

(3)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 5

– b) rimuovere un elemento?

“valore”

elemento

“valore”

elemento

“valore”

elemento

X X X

definizione del tipo di dato lista (e del tipo di dato iteratore) T : insieme dei possibili “valori”

P : insieme di “iteratori”

un iteratore è un “indicatore” di un elemento in una lista

• operazioni del tipo di dato iteratore : get : P → T

get(p) restituisce il valore dellʼelemento indicato da p

next : P → P

next(p) restituisce un iteratore che indica lʼelemento successivo a p

previous : P → P

previous(p) restituisce un iteratore che indica lʼelemento precedente a p

equal : P x P→ Bool

equal(p1, p2) vale vero se p1 e p2 indicano lo stesso elemento, falso altrimenti

is_null : P → Bool

Nota: is_null(p) non definita nel libro (cap. 16)

(4)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 7

"Anna Verdi"

"Luca Neri"

"Mario Rossi"

p

get(p)

previous(p)

next(p)

 "Anna Verdi"

"Anna Verdi"

"Luca Neri"

"Mario Rossi"

p

"Anna Verdi"

"Luca Neri"

"Mario Rossi"

p

• operazioni del tipo di dato lista : push_back : lista(T) x T → lista(T)

push_back(l, t) inserisce t dopo lʼultimo elemento di l

insert : lista(T) x P x T → lista(T)

insert(l, p, t) inserisce t prima dellʼ elemento di l indicato da p

erase : lista(T) x P → lista(T)

erase(l, p) elimina da l lʼelemento indicato da p

begin : lista(T) → P

begin(l) restituisce un indicatore al primo elemento di l

end : lista(T) → P

end(l) restituisce un indicatore allʼultimo elemento di l

empty : lista(T) → Bool

empty(l) vale "vero" se l è vuota, "falso" altrimenti

Nota: end(l) definita diversamente nel libro (cap. 16)

Nota: empty(l) non definita nel libro (cap. 16)

(5)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 9

realizzazione in C++ del tipo di dato lista (e del tipo di dato iteratore)

– assumiamo T = insieme di stringhe – (  liste di stringhe)

precsucc

“valore”

elemento

class Node {public:

Node(string s);

private:

string data;

Node* prec;

Node* succ;

friend class List;

friend class Iterator;

};

costruttore

“valore”

puntatori

una classe qualificata come “friend” ha il diritto di accedere alla parte privata della classe che concede la qualifica

- qui List e Iterator hanno il diritto di accedere alla parte privata di Node

 meccanismo da usare con cautela !!!

• realizzazione in C++ di un elemento della lista:

• realizzazione in C++ del tipo di dato iteratore :

class Iterator {public:

Iterator();

string get() const;

Iterator next() const;

Iterator previous() const;

bool equals(Iterator b) const;

bool is_null() const;

private:

Node* position;

friend class List;

};

costruttore

funzioni membro

“indicatore” di un elemento della lista

Nota: nel libro (cap. 16) è definito anche un altro attributo privato Node* last;

(6)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 11

• realizzazione in C++ del tipo di dato lista :

costruttore

funzioni membro

puntatori al primo e allʼultimo elemento della lista

class List {public:

List();

void push_back(string s);

void insert(Iterator p, string s);

void erase(Iterator p);

bool empty() const;

Iterator begin();

Iterator end();

private:

Node* first;

Node* last;

};

"Anna Verdi"

"Luca Neri"

"Mario Rossi"

Node Node Node

NULL

NULL List

first last

Iterator position

Nota: nel libro (cap. 16) erase() è di tipo Iterator

esempio dʼuso del tipo di dato lista

...

List elenco;

int num_nomi;

Iterator pos;

string nome, residuo;

int c;

cout<<"scrivi numero nomi da inserire in elenco \n";

cin>>num_nomi;

for (int i=1;i<=num_nomi;i++) {leggi nome

inserisci nome in elenco, in ordine alfabetico;

}

leggi nome;

inserisci nome in 4a posizione;

rimuovi il nome in 2a posizione;

leggi nome;

verifica se è presente in elenco;

stampa tutti i nomi in elenco

(7)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 13

• inserzione in ordine alfabetico (1)

void inserisci_in_ordine(List& l, string s) {Iterator i;

• se l è vuota inserisci s altrimenti

{• posiziona i all’inizio della lista;

• avanza i finchè non trovi un elemento maggiore di s;

• se i indica un elemento maggiore di s

inserisci s prima dell’elemento indicato da i;

altrimenti inserisci s dopo l’elemento indicato da i;

} }

inserzione in ultima posizione

void inserisci_in_ordine(List& l, string s) {Iterator i;

if (l.empty()) l.push_back(s);

else {i = l.begin();

while (!i.equals(l.end()) && i.get()<=s) i = i.next();

if (i.get()>s) l.insert(i,s);

else l.push_back(s);

} }

• inserzione in ordine alfabetico (2)

cout<<"scrivi numero nomi da inserire in elenco \n";

cin>>num_nomi;

for (int i=1;i<=num_nomi;i++) {leggi nome;

inserisci nome in elenco, in ordine alfabetico;

}

cout<<"scrivi numero nomi da inserire in elenco \n";

cin>>num_nomi;

for (int i=1; i<=num_nomi; i++) {getline(cin, nome);

inserisci_in_ordine(elenco, nome);

}

getline(cin, residuo); risolve un problema

di “coabitazione” tra

>> e getline() (vedi libro, sez. 6.1)

(8)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 15

• inserzione in 4a posizione

• leggi nome;

• posiziona l’iteratore pos all’inizio della lista;

• avanza pos fino alla 4a posizione

• inserisci il nuovo nome prima dell’elemento indicato da pos

cout<<"scrivi nome\n"; getline(cin, nome);

pos = elenco.begin(); c = 1;

while (c<4 && !pos.equals(elenco.end())) {pos = pos.next(); c++;}

if (c==4)

elenco.insert(pos, nome);

else ??inserzione impossibile??

• leggi nome;

• inserisci nome in 4a posizione;

else if (c==3)

elenco.push_back(nome);

else cout<<"lista con meno di 3 elementi \n";

• rimozione dalla 2a posizione

• posizione l’iteratore pos all’inizio della lista;

• avanza pos fino alla 2a posizione

• rimuovi l’elemento indicato da pos

pos = elenco.begin(); c = 1;

while (c<2 && !pos.equals(elenco.end())) {pos = pos.next(); c++;}

if (c==2)

elenco.erase(pos);

else cout<<"lista con meno di 2 elementi \n";

rimuovi il nome in 2a posizione;

(9)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 17

• verifica presenza

• leggi nome;

• se la lista non è vuota

• posizione l’iteratore pos all’inizio della lista;

• scorri la lista, confrontando il nome con il valore dell’elemento indicato da pos;

cout<<"scrivi nome\n"; getline(cin, nome);

pos = elenco.begin();

if (!elenco.empty())

{while (!pos.equals(elenco.end()) && pos.get()!=nome) pos = pos.next();

if (pos.get()==nome)

cout<<nome<<" presente nella lista \n";

else cout<<nome<<" non presente nella lista \n";

}

else cout<<" lista vuota \n";

• leggi nome;

• verifica se è presente in elenco;

• stampa della lista

• se la lista non è vuota

• posizione l’iteratore pos all’inizio della lista;

• scorri la lista, e stampa il valore dell’elemento indicato da pos;

if (!elenco.empty()) {pos = elenco.begin();

while (!pos.is_null())

{cout << pos.get() << "\n"; pos = pos.next();

} }

stampa tutti i nomi in elenco

if (!elenco.empty())

{for (pos=elenco.begin();!pos.is_null();pos=pos.next()) cout << pos.get() << "\n";

} versione alternativa

(10)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 19

class Node {public:

Node(string s);

private:

string data;

Node* prec;

Node* succ;

friend class List;

friend class Iterator;

};

costruttore

“valore”

realizzazione in C++ del tipo di dato nodo

Node::Node(string s) {data = s;

prec = NULL;

succ = NULL;

}

costruttore :

realizzazione in C++ delle funzioni membro del tipo di dato iteratore

Iterator::Iterator() {position = NULL;

}

costruttore :

class Iterator {public:

Iterator();

string get() const;

Iterator next() const;

Iterator previous() const;

bool equals(Iterator b) const;

bool is_null() const;

private:

Node* position;

friend class List;

};

costruttore

funzioni membro

“indicatore” di un elemento della lista

(11)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 21

string Iterator::get() const {

return position->data;

}

assert(position != NULL);

bool Iterator::equals(Iterator b) const {

return position == b.position;

}

se position==NULL,non è lecito accedere ai campi dellʼoggetto riferito (non esiste)

get : P → T

get(p) restituisce il valore dellʼelemento indicato da p

equals : P x P→ Bool

equals(p1, p2) vale vero se p1 e p2 indicano lo stesso elemento, falso altrimenti

Iterator Iterator::next() const {

Iterator t;

t.position=position->succ;

return t;

}

assert(position != NULL);

se position==NULL,non è lecito accedere ai campi dellʼoggetto riferito (non esiste)

"Anna Verdi"

"Luca Neri"

"Mario Rossi"

p

Iterator Iterator::previous() const {

Iterator t;

t.position=position->prec;

return t;

}

assert(position != NULL);

"Anna Verdi"

"Luca Neri"

"Mario Rossi"

p

previous : P → P

previous(p)

restituisce lʼ “indicatore”

allʼelemento precedente a p (NON modifica p)

next : P → P

next(p) restituisce lʼ “indicatore”

allʼelemento

successivo a p (NON modifica p)

(12)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 23

bool Iterator::is_null() const {return position==NULL;

}

is_null : P → Bool

is_null(p) vale vero se p non indica nessun elemento falso altrimenti

realizzazione in C++ delle funzioni membro del tipo di dato lista

"Anna Verdi"

"Luca Neri"

"Mario Rossi"

Node Node Node

NULL

NULL List

first last

Iterator position

costruttore

funzioni membro

puntatori al primo e allʼultimo elemento della lista

class List {public:

List();

void push_back(string s);

void insert(Iterator p, string s);

void erase(Iterator p);

bool empty() const;

Iterator begin();

Iterator end();

private:

Node* first;

Node* last;

};

(13)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 25

List::List() {first = NULL;

last = NULL;

}

• costruttore :

List

first last

NULL NULL

bool List::empty() const { return first==NULL; }

• empty : lista(T) → Bool

empty(l) vale "vero" se l è vuota, "falso" altrimenti

Iterator List::begin() {Iterator i;

i.position = first;

return i;

}

• begin : lista(T) → P

begin(l) restituisce un indicatore al primo elemento di l

Iterator List::end() {Iterator i;

i.position = last;

return i;

}

• end : lista(T) → P

end(l) restituisce un indicatore allʼultimo elemento di l

(14)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 27

void List::push_back(string s) {

}

crea un nuovo nodo (che contiene s)

inseriscilo in ultima posizione se (lista vuota)

caso particolare altrimenti

• push_back : lista(T) x T → lista(T)

push_back(l, t) inserisce t dopo lʼultimo elemento di l

void List::push_back(string s) {

}

"..." "..."

"..."

Node Node Node

NULL

NULL List

first last

n:

X X

Node* n = new Node(s);

{n->prec = last;

if (last == NULL) {first = n;

last = n;

} else

last->succ = n;

last= n;

}

prec:

succ:

List first last

NULL NULL

X X

NULL

X

s Node

prec: NULL succ:

(15)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 29

• insert : lista(T) x P x T → lista(T)

insert(l, p, t) inserisce t prima dellʼ elemento di l indicato da p

- caso particolare: lista vuota …

NULL s Node List

first last

NULL NULL

X X

void List::insert(Iterator p, string s) {...}

if (empty()) push_back(s);

else ...

- … altrimenti:

n: NULL

X

s Node

prec: NULL succ:

"..." "..."

"..."

Node Node Node

prec:

succ:

Node* n = new Node(s);

Node* dopo = p.position;

Node* prima = dopo->prec;

Iterator position p:

dopo:

prima:

2) si “aggancia” il nuovo nodo alla lista n->prec = prima;

n->succ = dopo;

3) si aggiornano i due nodi che precedono e seguono il nuovo nodo

dopo->prec = n;

prima->succ = n;

se p indica il 1° elemento?

occorre controllare se p indica

X X X

1) si crea il nodo da inserire, e si creano puntatori ai nodi che stanno prima e dopo il punto di inserzione

( facilita le operazioni)

if (prima==NULL) first = n;

else

(16)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 31

mettendo tutto insieme:

• insert : lista(T) x P x T → lista(T)

void List::insert(Iterator p, string s) {if (empty())

push_back(s);

else {Node* n = new Node(s);

Node* dopo = p.position;

Node* prima = dopo->prec;

n->prec = prima;

n->succ = dopo;

dopo->prec = n;

if (prima==NULL) first = n;

else prima->succ = n;

} }

• erase : lista(T) x P → lista(T)

erase(l, p) elimina da l lʼelemento indicato da p void List::erase(Iterator p)

{...}

- premessa: p deve indicare un elemento … assert (p.position != NULL);

(17)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 33

Node* da_rimuovere=p.position;

Node* dopo=da_rimuovere->succ;

Node* prima=da_rimuovere->prec;

"..." "..."

"..."

Node Node Node

prec:

succ:

X

Iterator position p:

dopo:

- … quindi … :

1) si creano puntatori al nodo da rimuovere, e ai due nodi che stanno prima e dopo di lui ( facilita le operazioni)

prima:

2) si disconnette il nodo da quello che lo precede

prima->succ = dopo;

se p indica il 1° elemento?

da_rimuovere:

if (prima==NULL) first = dopo;

else

oppure: if (da_rimuovere==first)

"..." "..."

"..."

Node Node Node

prec:

succ:

X X X

Iterator position p:

dopo:

- … infine … :

3) si disconnette il nodo da quello che lo segue (operando analogamente al punto 2)

prima:

4) si cancella il nodo rimosso delete da_rimuovere;

NOTA: p ora indica un elemento inesistente !!!

da_rimuovere:

dopo->prec = prima;

se p indica lʼultimo elemento?

if (da_rimuovere==last) last = prima;

else

(18)

V. Grassi - Fondamenti di Informatica (2a parte) L5 - 35

mettendo tutto insieme:

• erase : lista(T) x P → lista(T)

void List::erase(Iterator p) {assert (p.position != NULL);

Node* da_rimuovere = p.position;

Node* dopo = da_rimuovere->succ;

Node* prima = da_rimuovere->prec;

if (prima==NULL) first = dopo;

else prima->succ = dopo;

if (da_rimuovere==last) last = prima;

else dopo->prec = prima;

delete da_rimuovere;

}

Riferimenti

Documenti correlati

Le skill possono essere ricavate sia dalla domanda (dai siti aggregatori) sia dall'offerta (social media e sistemi che permettono l'autovalutazione), e permettono il matching

Si tratta di impostazioni debitrici, da un lato, della risalente tendenza tedesca ad attribuire al diritto di autotutela una valenza assoluta, fondata sull’idea della legittima

[r]

O GGETTO – La cautela penale personale costituisce da sempre uno dei temi processuali più sensibili al periodico oscillare delle scelte di politica criminale

che pu` o essere uguale al vettore nullo `e quella che ha coefficienti tutti nulli, quindi possiamo dire appunto che tutti i coefficienti di questa combinazione sono uguali a

In uno studio condotto da TrialNet in pazienti con diabete di tipo 1 di recente insorgenza, abatacept ha significativamente rallentato il declino della funzione beta-cellulare a un

Il Fortran ammette anche la “dichiarazione implicita” delle variabili: tutte le variabili il cui nome inizia con i,j,k,l,m,n sono automaticamente ritenute di tipo intero, mentre

Il tipo carattere è di fatto un dato di tipo numerico sul quale sono permesse tutte le operazioni definite sul tipo intero.. Il