• 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

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

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

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

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

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