Professional Documents
Culture Documents
86
Marcello Esposito
Copyright
c 2006 Marcello Esposito. Permission is granted to copy, distri-
bute and/or modify this document under the terms of the GNU Free Do-
cumentation License, Version 1.2 or any later version published by the Free
Software Foundation; with no Invariant Sections, no Front-Cover Texts, and
no Back-Cover Texts. A copy of the license is included in the section entitled
"GNU Free Documentation License".
Indice
Prefazione 5
I Esercizi 11
EL Esercizi su liste 12
EL.1 Lista Semplicemente Collegata . . . . . . . . . . . . . . . . 12
EL.2 Somma Elementi . . . . . . . . . . . . . . . . . . . . . . . . 13
EL.3 Coda Pari . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
EL.4 Min e Max . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
EL.5 Lista Statica . . . . . . . . . . . . . . . . . . . . . . . . . . 14
EL.6 È Ordinata . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
EL.7 Elimina Tutti . . . . . . . . . . . . . . . . . . . . . . . . . . 15
EL.8 Elimina Ultimi . . . . . . . . . . . . . . . . . . . . . . . . . 15
EL.9 Somma Coda . . . . . . . . . . . . . . . . . . . . . . . . . . 15
EL.10 Sposta Testa in Coda . . . . . . . . . . . . . . . . . . . . . 16
EL.11 Elimina Pari e Dispari . . . . . . . . . . . . . . . . . . . . . 16
EL.12 Lista Doppiamente Collegata . . . . . . . . . . . . . . . . . 16
EL.13 Ribalta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1
INDICE 2
EP Esercizi su pile 28
EP.1 Push Greater . . . . . . . . . . . . . . . . . . . . . . . . . . 28
EP.2 Push If . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
EC Esercizi su code 31
EC.1 Coda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
EC.2 Coda con Perdite . . . . . . . . . . . . . . . . . . . . . . . . 32
EC.3 Coda a Priorità . . . . . . . . . . . . . . . . . . . . . . . . . 33
EC.4 PopMinMax . . . . . . . . . . . . . . . . . . . . . . . . . . 34
EX Altri esercizi 36
EX.1 Accumulatore . . . . . . . . . . . . . . . . . . . . . . . . . . 36
EX.2 Cifratore . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
EX.3 Lista Della Spesa . . . . . . . . . . . . . . . . . . . . . . . . 37
EX.4 Predittore di Temperatura . . . . . . . . . . . . . . . . . . 38
EX.5 Contenitore . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
EX.6 Lista Prenotazioni . . . . . . . . . . . . . . . . . . . . . . . 41
EX.7 Classica . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
EX.8 Agenzia Matrimoniale . . . . . . . . . . . . . . . . . . . . . 43
EX.9 Parco Pattini . . . . . . . . . . . . . . . . . . . . . . . . . . 45
EX.10 Timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
EX.11 Timer Avanzato . . . . . . . . . . . . . . . . . . . . . . . . 47
EX.12 Votazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
II Soluzioni 50
SL Soluzioni degli esercizi su liste 51
SL.1 Lista Semplicemente Collegata . . . . . . . . . . . . . . . . 51
SL.2 Somma Elementi . . . . . . . . . . . . . . . . . . . . . . . . 57
SL.3 Coda Pari . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
INDICE 3
5
Prefazione 6
di interfaccia dei classici metodi di cui tali strutture sono dotate (aggiunta di
un elemento, conteggio degli elementi, svuotamento, visita, etc.). Altri eser-
cizi, basandosi sulle suddette implementazioni, richiedono la realizzazione di
funzionalità nalizzate ad eettuare particolari elaborazioni sugli elementi
contenuti (per esempio inserimenti o eliminazioni condizionate, somme, spo-
stamenti, conteggi, etc.). Inne, alcuni esercizi richiedono la realizzazione
di strutture dedicate a risolvere specici problemi, e quindi prive dei classici
requisiti di generalità.
Per ogni metodo da implementare, una traccia fornisce le seguenti infor-
mazioni:
Nel caso in cui l'insieme dei parametri di ingresso e/o di uscita fosse
vuoto, si utilizzerà il simbolo φ. Talvolta può accadere che nella descrizione
del funzionamento del metodo non si prenda in considerazione la totalità
dei casi che possono vericarsi (pre-condizioni), limitandosi a descrivere il
comportamento del metodo nei casi d'uso più comuni. In questo caso, il
programmatore può scegliere arbitrariamente un comportamento per tutti i
casi non esplicitamente considerati.
Quando l'esercizio richiede la denizione di una struttura di tipo conte-
nitore, spesso gli algoritmi da realizzare sono sucientemente indipendenti
dal tipo degli elementi contenuti, e fanno riferimento solo ad alcune loro pro-
prietà (relazione di ordinamento, uguaglianza e disuguaglianza tra elementi,
etc.). Per questo motivo, nell'ambito di tali strutture, il tipo degli elementi è
sistematicamente indicato con il generico identicatore TElem, essendo la de-
nizione del tipo TElem centralizzata e localizzata in testa all'header le del-
la classe contenitore. Questa procedura anticipa l'uso della programmazione
Prefazione 7
generica, che in C++ può essere praticata mediante il meccanismo dei tem-
plates. Grazie alla tecnica suddetta, sarà semplice la eventuale conversione
delle classi così realizzate in classi template.
Per quanto riguarda le strategie di gestione della memoria, la realizzazione
delle strutture dati può basarsi su un approccio di tipo statico (uso di vettori
allocati sullo stack) oppure dinamico (realizzazione di strutture concatenate
con puntatori ed allocate nell'heap mediante costrutto new). Questa scelta,
in alcuni casi, è lasciata alla sensibilità dello studente.
Alcune delle soluzioni presentate constano di un unico le avente estensio-
ne .cpp. In altri casi è stato presentato un approccio più modulare, mediante
separazione del codice su più les (aventi estensioni .h e .cpp), enfatizzando
in misura ancora maggiore i diversi moduli di cui l'astrazione è di volta in
volta costituita.
Per ognuno degli esercizi, oltre alla traccia, si fornisce la soluzione con-
sistente nell'implementazione dei metodi conformi all'interfaccia specicata
dalla traccia. Nel caso in cui la traccia richieda di realizzare una struttura
dati completa (e non solo i metodi basati su di essa), nella soluzione viene an-
che fornito un modulo di test (di solito rappresentato dalla funzione main())
utile esclusivamente al collaudo delle funzionalità della classe.
Al ne di preservare una maggiore generalità delle strutture dati realizza-
te, un esplicito requisito comune a tutti gli esercizi consiste nel vietare l'uso
dei meccanismi di I/O nell'implementazione dei metodi della classe. La re-
sponsabilità di prelevare i dati da tastiera e mostrare i risultati sulla console
viene pertanto delegata al modulo di test. Un'unica deroga a questa regola è
relativa al metodo di visita delle strutture (di solito contrassegnato dal nome
Stampa()): il concetto di iteratore, utile ad astrarre l'attraversamento di una
struttura contenitore, non è di solito noto agli studenti di un corso di base.
Il lettore interessato può fare riferimento alla Standard Template Library
(STL) [4], peraltro di notevole utilità in reali contesti di sviluppo software.
Per le operazioni di I/O si utilizzano le funzionalità messe a disposizione dalla
libreria standard iostream, ed in particolare dai suoi oggetti cin e cout.
Spesso nelle tracce non è richiesta l'implementazione di un costruttore
di copia oppure di un operatore di assegnazione. Questi due metodi rien-
trano tra quelli che, se non deniti in una classe, vengono automaticamente
sintetizzati dal compilatore e, se invocati dall'utente, producono una copia
superciale dell'oggetto (shallow-copy ). Se questo comportamento è scorret-
to o comunque indesiderato è possibile rendere del tutto indisponibili
le funzionalità di copia o assegnazione tra oggetti della classe. Ciò si ottiene
dichiarando nella sezione private della classe i due metodi in questione e
non fornendone alcuna implementazione [5]. Così facendo, qualsiasi costrut-
to che nisca per invocare uno di questi due metodi produrrà un errore di
Prefazione 8
compilazione. Tale tecnica viene spesso utilizzata nelle soluzioni degli esercizi
presentati.
Compilare i sorgenti
Tutti i sorgenti presentati sono stati compilati con la versione 3.3.1 del-
la suite di compilazione GNU/GCC [6], utilizzando le seguenti opzioni di
compilazione:
solo attraverso questa strada che diviene possibile scrivere applicazioni non
banali, preservandone le caratteristiche di comprensibilità, estensibilità, ma-
nutenibilità, correttezza e, in una sola parola, di qualità. Programmare uti-
lizzando l'incapsulamento, il polimorsmo, i meccanismi delle eccezioni, delle
asserzioni, dei templates, le numerose librerie più o meno standard, signica
disporre di strumenti semanticamente molto potenti, oltre che ben consolida-
ti; signica delegare al compilatore lo svolgimento di una serie di operazioni
e di controlli che, in alternativa, peserebbero sulle spalle del programmatore,
oppure non verrebbero messi in essere aatto.
Una volta che la STL sia stata acquisita, i vantaggi di un tale approccio risultano
evidenti relativamente agli aspetti di (i) tempo di stesura; (ii) correttezza del codice; (iii)
individuazione degli errori; (iv) comprensibilità; (v) manutenibilità; (vi) estensibilità; (vii)
aderenza agli standard.
Contattare l'autore
Commenti, suggerimenti e segnalazioni sono graditi. L'autore può essere
contattato al seguente indirizzo e-mail: mesposit@unina.it
1 L'opzione è: -Weffc++.
Parte I
Esercizi
11
Capitolo EL
Esercizi su liste
Si realizzi la struttura dati Lista. Il tipo TElem degli elementi contenuti sia
uguale al tipo int del linguaggio. La lista sia dotata dei metodi riportati di
seguito.
Lista() Lista φ
Costruttore di copia.
Lista() φ φ
Distruttore.
Inserisci() TElem φ
Inserimento in testa alla lista.
NumeroElementi() φ int
Restituisce il numero degli elementi contenuti nella lista.
Svuota() φ φ
Svuota la lista.
Elimina() TElem φ
Elimina un elemento dalla lista, se presente.
12
EL. Esercizi su liste 13
Stampa() φ φ
Stampa sullo standard output tutti gli elementi contenuti nella lista.
Dotare la classe Lista (vedi EL.1) del metodo Somma() secondo la seguente
specica.
CodaPari() φ bool
Restituisce true se l'elemento in coda è pari, false altrimenti.
Dotare la classe Lista (vedi EL.1) del metodo MinMax() secondo la seguente
specica.
EL. Esercizi su liste 14
Lista() φ φ
Distruttore.
InserisciInCoda() TElem φ
Inserisce un elemento in coda alla lista.
Svuota() φ φ
Svuota la lista.
Count() φ φ
Restituisce il numero degli elementi contenuti nella lista.
Stampa() φ φ
Stampa sullo standard output tutti gli elementi contenuti nella lista.
EL.6 È Ordinata
Soluzione a pag. 61
Dotare la classe Lista (vedi EL.1) dei metodi le cui interfacce sono riportate
di seguito.
Si realizzi in linguaggio C++ il tipo di dato astratto Lista mediante uso del
costrutto class del linguaggio. L'implementazione deve essere realizzata me-
diante puntatori ed allocazione dinamica della memoria secondo l'approccio
EL. Esercizi su liste 17
el el el
first last
Figura EL.1: Struttura della lista doppiamente collegata
Lista() φ φ
Distruttore.
Inserisci() TElem φ
Inserisce un elemento in coda alla lista.
Svuota() φ φ
Svuota la lista.
StampaDiretta() φ φ
Stampa il contenuto della lista sullo standard output, dall'elemento
di testa all'elemento di coda.
StampaInversa() φ φ
Stampa il contenuto della lista sullo standard output, dall'elemento
di coda all'elemento di testa.
StampaAlternata() φ φ
Stampa il contenuto della lista nel seguente ordine: primo elemen-
to, ultimo elemento, secondo elemento, penultimo elemento, terzo
elemento, terzultimo elemento...
EL. Esercizi su liste 18
Gli unici metodi della classe Lista che possono utilizzare lo standard-
output (cout) sono i metodi di stampa. Gli altri metodi (pubblici, privati o
protetti) non possono fare uso degli oggetti per l'I/O.
Si realizzi una funzione main() che permetta di eettuare il collaudo della
struttura dati realizzata.
EL.13 Ribalta
Soluzione a pag. 69
Dotare la classe Lista (vedi EL.1) del metodo Ribalta() secondo la se-
guente specica.
AlberoBinario() φ φ
Costruttore della struttura.
AlberoBinario() AlberoBinario φ
Costruttore di copia.
AlberoBinario() φ φ
Distruttore della struttura.
AggiungiElem() TElem φ
Metodo di aggiunta di un elemento all'albero.
Elimina() TElem φ
Elimina l'elemento specicato dall'albero.
Svuota() φ φ
Svuota la struttura.
19
EA. Esercizi su alberi binari 20
PreOrdine() φ φ
Eettua una visita in pre-ordine dell'albero, stampando tutti gli
elementi sullo standard output.
PostOrdine() φ φ
Eettua una visita in post-ordine dell'albero, stampando tutti gli
elementi sullo standard output.
InOrdine() φ φ
Eettua una visita in ordine dell'albero, stampando tutti gli elementi
sullo standard output.
EA.3 Occorrenze
Soluzione a pag. 79
EA.6 Somma
Soluzione a pag. 82
EA.7 Sostituisci
Soluzione a pag. 83
SommaLivello() TElem φ
Somma ad ogni elemento dell'albero un valore intero pari al livello
del corrispondente nodo. Per es.: al nodo radice verrà aggiunto 1, ai
suoi gli diretti 2. . . ecc.
Dotare la classe AlberoBinario (vedi EA.1) dei due metodi le cui interfacce
sono riportate di seguito.
a1 == a2 ;
(ad esempio in un costrutto if) dove a1 ed a2 sono due istanze della classe
AlberoBinario. In questo caso viene invocato l'operatore operator==()
sull'oggetto a1, mentre a2, parametro attuale, viene passato per riferimento
prendendo il posto del parametro formale dell'operatore.
Di seguito si riporta la specica dell'operatore di confronto da realizzare.
EA. Esercizi su alberi binari 26
Si realizzi in linguaggio C++ il tipo di dato astratto Pila mediante uso del
costrutto class del linguaggio e ricorrendo ad un'implementazione dinamica.
Il tipo TElem degli elementi della pila sia il tipo int.
Di seguito è riportata la specica dei metodi pubblici da implementare
per la classe Pila.
Pila() φ φ
Distruttore.
Push() TElem φ
Aggiunge sulla pila l'elemento specicato.
Top() φ TElem
Restituisce l'elemento di testa corrente della pila (ma non lo estrae).
In caso di pila vuota il comportamento di questo metodo è non
specicato.
28
EP. Esercizi su pile 29
Pop() φ TElem
Estrae e restituisce l'elemento di testa corrente della pila. In caso di
pila vuota il comportamento di questo metodo è non specicato.
Svuota() φ φ
Svuota la pila.
Empty() φ bool
Predicato vero se la pila è vuota, falso altrimenti.
EP.2 Push If
Soluzione a pag. 96
Pop() φ TElem
Estrae e restituisce l'elemento di testa corrente della pila. Azzera il
conteggio degli inserimenti. In caso di pila vuota il comportamento
di questo metodo è non specicato.
Svuota() φ φ
Svuota la pila ed azzera il conteggio degli inserimenti.
Capitolo EC
Esercizi su code
EC.1 Coda
Soluzione a pag. 99
Si realizzi in linguaggio C++ il tipo di dato astratto Coda mediante uso del
costrutto class del linguaggio e ricorrendo ad un'implementazione dinamica.
Il tipo TElem degli elementi della coda sia il tipo int.
Di seguito è riportata la specica dei metodi pubblici da implementare
per la classe Coda.
Coda() φ φ
Costruttore senza parametri.
Coda() φ φ
Distruttore.
Push() TElem φ
Accoda l'elemento specicato.
Top() φ TElem
Restituisce l'elemento di testa corrente della coda (ma non lo estrae).
In caso di coda vuota il comportamento di questo metodo è non
specicato.
Pop() φ TElem
Estrae e restituisce l'elemento di testa corrente presente in coda.
In caso di coda vuota il comportamento di questo metodo è non
specicato.
31
EC. Esercizi su code 32
Somma() φ TElem
Restituisce la somma di tutti gli elementi presenti in coda.
Svuota() φ φ
Svuota la coda.
Empty() φ bool
Predicato vero se la coda è vuota, falso altrimenti.
Si realizzi in linguaggio C++ il tipo di dato astratto Coda mediante uso del
costrutto class del linguaggio. Il tipo TElem degli elementi della coda sia il
tipo int.
Di seguito è riportata la specica dei metodi pubblici da implementare
per la classe Coda.
Coda() φ φ
Distruttore.
Top() φ TElem
Restituisce l'elemento di testa corrente della coda (ma non lo estrae).
In caso di coda vuota il comportamento di questo metodo è non
specicato.
Pop() φ TElem
Estrae e restituisce l'elemento di testa corrente presente in coda.
In caso di coda vuota il comportamento di questo metodo è non
specicato.
Svuota() φ φ
Svuota la coda.
Empty() φ bool
Predicato vero se la coda è vuota, falso altrimenti.
PriorityQueue() φ φ
Distruttore.
PushLow() TElem φ
Accoda un elemento a bassa priorità.
PushHigh() TElem φ
Accoda un elemento ad alta priorità.
Pop() φ TElem
Estrae e restituisce il primo elemento ad altà priorità o, in sua as-
senza, il primo elemento a bassa priorità. In caso di coda vuota il
comportamento di questo metodo è non specicato.
Svuota() φ φ
Svuota la coda.
Empty() φ bool
Predicato vero se la coda è vuota, falso altrimenti.
EC.4 PopMinMax
Soluzione a pag. 112
Dotare la classe Coda (vedi EC.1) dei metodi PopMax() e PopMin() secondo
la seguente specica.
EC. Esercizi su code 35
EX.1 Accumulatore
Soluzione a pag. 113
Accumulatore() φ φ
Costruttore della classe.
Add() float φ
Aggiunge all'accumulaotre il valore specicato dal parametro di
ingresso.
Reset() φ φ
Azzera l'accumulatore.
GetValue() φ float
Restituisce il valore corrente dell'accumulatore.
EX.2 Cifratore
Soluzione a pag. 114
36
EX. Altri esercizi 37
ListaDellaSpesa() φ φ
Distruttore.
EX. Altri esercizi 38
Svuota() φ φ
Svuota la lista.
Stampa() φ φ
Stampa il contenuto dell'intera lista nel formato Nome: Quantità,
Nome: Quantità, ...
◦
e che all'istante 5 è pari a 16 , una richiesta della stima della temperatura
◦
all'istante 10 produrrebbe come risultato 18 .
Si consideri la seguente interfaccia della classe.
SetTemp() Time,Temp φ
Fornisce al predittore un ulteriore valore di temperatura campionato
ed il relativo istante di campionamento.
EX.5 Contenitore
Soluzione a pag. 121
Contenitore() φ φ
Distruttore.
Svuota() φ φ
Svuota il contenitori di tutti gli oggetti presenti in esso.
PesoComplessivo() φ Peso
Restituisce il peso complessivo raggiunto dal contenitore.
PesoResiduo() φ Peso
Restituisce il peso residuo per il raggiungimento della capacità
massima del contenitore.
Stampa() φ φ
Stampa le coppie (Nome, Peso) di tutti gli oggetti presenti nel
contenitore.
typedef int M a t r i c o l a ;
typedef char Nome [ 3 0 ] ;
struct Prenotazione {
M a t r i c o l a mat ;
Nome nom ;
};
I metodi da implementare per la classe ListaPrenotazioni siano con-
formi alla seguente interfaccia.
ListaPrenotazioni() φ φ
Distruttore.
GetPostiDisponibili() φ int
Restituisce il numero di posti ancora disponibili.
Svuota() φ φ
Svuota la lista.
Stampa() φ φ
Stampa il contenuto dell'intera lista nel formato seguente: Matrico-
la1: Nome1, Matricola2: Nome2, Matricola3: Nome3, ...
EX.7 Classica
Soluzione a pag. 128
Classifica() φ φ
Distruttore.
EX. Altri esercizi 43
Svuota() φ φ
Svuota la struttura.
Stampa() φ φ
Stampa la classica delle squadre presenti nella struttura, in ordine
decrescente di punteggio.
AgenziaMatrimoniale () φ φ
Distruttore.
Svuota() φ φ
Svuota la struttura.
Stampa() φ φ
Stampa il contenuto della struttura (vedi esempio ???).
ParcoPattini() φ φ
Distruttore.
AggiungiPattini() Taglia φ
Aggiunge al parco un paio di pattini della misura specicata.
Svuota() φ φ
Svuota il parco pattini.
Stampa() φ φ
Stampa a video lo stato dell'intero parco pattini.
EX.10 Timer
Soluzione a pag. 142
Stop() φ φ
Arresta il conteggio del tempo.
Reset() φ φ
Arresta ed azzera il timer.
GetTime() φ Time
Restituisce il conteggio corrente del tempo.
EX. Altri esercizi 47
0 5 10 15 0 Valori conteggio
0 4 10 15 20 25 30 35 40
Suggerimenti
• La seguente riga di codice:
time t = time ( 0 ) ;
EX.12 Votazioni
Soluzione a pag. 145
Votazioni() φ φ
Distruttore.
Svuota() φ φ
Svuota la struttura.
GetSituazione() φ φ
Stampa a video un riepilogo dei voti complessivamente registrati nella
struttura.
EX. Altri esercizi 49
50
Capitolo SL
Soluzioni degli esercizi su liste
File Lista.h
1 #ifndef _LISTA_H_
2 #define _LISTA_H_
3
4 struct Record ; // forward d e c l a r a t i o n : u t i l e a d i c h i a r a r e i l t i p o PRec
5 typedef Record ∗ PRec ;
6 typedef int TElem ;
7
8 class L i s t a {
9 private :
10 PRec f i r s t ;
11 int c ount ;
12
13 L i s t a& operator =( const L i s t a &); //non implementato : i n i b i s c e l ' a s s e g n a z .
14 public :
15 L i s t a ( ) ; // c o s t r u t t o r e senza parametri
16 L i s t a ( const L i s t a& l ) ; // c o s t r u t t o r e d i c o p i a
17 ~ L i s t a ( ) ; // d i s t r u t t o r e
18
19 void I n s e r i s c i ( const TElem& e l ) ; // I n s e r i m e n t o i n testa
20 int NumeroElementi ( ) const ; // R e s t i t u i s c e i l num. d e gl i elementi nella l i s t a
21 void Svuota ( ) ; // Svuota l a l i s t a
51
SL. Soluzioni degli esercizi su liste 52
Le prime due righe del le appena mostrato, insieme con l'ultima, impe-
discono che il le Lista.h possa essere processato dal pre-compilatore più
di una volta all'atto della compilazione di un le sorgente. Ciò accade nel-
l'eventualità che, nel grafo delle inclusioni che va a formarsi all'atto della
compilazione di un le .cpp,
Lista.h risulti incluso da più di un le.
il le
Dal momento che l'header le Lista.h contiene esclusivamente dichiarazioni
(e non denizioni), una sua eventuale inclusione multipla sarebbe ininuente
ai ni della compilazione.
Si noti inoltre come l'operatore di assegnazione della lista riportato alla
riga 13 sia dichiarato tra i metodi privati della classe, nonostante non verrà
successivamente denito nel relativo le .cpp. Tale dichiarazione è esclusi-
vamente nalizzata ad impedire che tale metodo possa essere invocato dagli
utenti della classe Lista. Se ciò accadesse, infatti, verrebbe invocata l'im-
plementazione dell'operatore di assegnazione automaticamente sintetizzata
dal compilatore e consistente in una copia bit a bit dei membri della classe,
verosimilmente scorretta ai ni di un utilizzo reale della struttura (vedi [5]).
File Lista.cpp
#include <i o s t r e a m>
#include " l i s t a . h"
using namespace s t d ;
struct Record {
TElem e l ;
PRec s u c c ;
};
L i s t a : : L i s t a ( ) : f i r s t ( 0 ) , c ount ( 0 ) {
}
PRec l p = l . f i r s t ;
PRec p = f i r s t ;
while ( lp −>s u c c ) {
p−>s u c c = new Record ;
p = p−>s u c c ;
SL. Soluzioni degli esercizi su liste 53
l p = lp −>s u c c ;
p−>e l = lp −>e l ;
}
p−>s u c c = 0 ; // imposta a 0 i l succ d e l l ' u l t i m o elemento d e l l a l i s t a
}
}
c ount++;
}
void L i s t a : : Svuota ( ) {
PRec tbd ; // t b d = t o be d e l e t e d
while ( f i r s t ) {
tbd = f i r s t ;
f i r s t = f i r s t −>s u c c ;
delete tbd ;
}
c ount = 0 ;
}
trovato = true ;
c ount −−;
} else
SL. Soluzioni degli esercizi su liste 54
p = p−>s u c c ;
}
}
}
}
while (p) {
c out << p−>e l << " " ;
p = p−>s u c c ;
}
}
return trovato ;
}
File main.cpp
#include <i o s t r e a m>
#include <s t d l i b . h>
#include " l i s t a . h"
using namespace s t d ;
// P r o t o t i p i d i f u n z i o n i d i s u p p o r t o per l a v e r i f i c a d e l
// c o r r e t t o funzionamento d e i metodi d e l l a c l a s s e L i s t a .
void stampaMenu ( ) ;
void I n s e r i s c i ( L i s t a& l ) ;
void R i c e r c a ( L i s t a& l ) ;
void E limina ( L i s t a& l ) ;
void Svuota ( L i s t a& l ) ;
void NumeroElementi ( L i s t a& l ) ;
void Stampa ( L i s t a& l ) ;
void C o p i a L i s t a ( L i s t a& l ) ;
int main ( )
{
char c ;
Lista l i s t a ;
do {
stampaMenu ( ) ;
c i n >> c ;
switch (c) {
case '1 ' :
SL. Soluzioni degli esercizi su liste 55
Inserisci ( lista );
break ;
case ' 2 ' :
Ricerca ( l i s t a ) ;
break ;
case ' 3 ' :
E limina ( l i s t a ) ;
break ;
case ' 4 ' :
Svuota ( l i s t a ) ;
break ;
case ' 5 ' :
Stampa ( l i s t a ) ;
break ;
case ' 6 ' :
NumeroElementi ( l i s t a ) ;
break ;
case ' 7 ' :
CopiaLista ( l i s t a ) ;
break ;
case ' 8 ' :
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
break ;
}
} while ( c != ' 8 ' ) ;
return 0 ;
}
void stampaMenu ( ) {
c out << e n d l ;
c out << " 1 . I n s e r i s c i " << e n d l ;
c out << " 2 . R i c e r c a " << e n d l ;
c out << " 3 . E limina " << e n d l ;
c out << " 4 . Svuota " << e n d l ;
c out << " 5 . Stampa" << e n d l ;
c out << " 6 . Numero Ele me nt i " << e n d l ;
c out << " 7 . Copia " << e n d l ;
c out << " 8 . E s c i " << e n d l ;
c out << e n d l ;
c out << " S c e l t a : " ;
}
void I n s e r i s c i ( L i s t a& l) {
int i ;
c out << " I n s e r i s c i i n t e r o : " ;
c i n >> i ;
l . Inserisci ( i );
}
void R i c e r c a ( L i s t a& l) {
int i ;
c out << " I n s e r i s c i i n t e r o : " ;
c i n >> i ;
if ( l . Ricerca ( i ))
c out << " Trovato . \ n" ;
else
c out << "Non t r o v a t o . \ n" ;
}
SL. Soluzioni degli esercizi su liste 56
pp pp
first
count el succ el succ el succ
Lista
void C o p i a L i s t a ( L i s t a& l ) {
Lista lcopia ( l ) ;
trovato = true ;
count −−;
} else
pp = &(( ∗ pp)−>s u c c ) ;
}
}
}
return somma ;
}
return p;
}
SL. Soluzioni degli esercizi su liste 58
else
return 0 ; // s e l a l i s t a è vuota non e s i s t e una coda
}
La ricerca del minimo e del massimo possono essere condotte secondo un ap-
proccio iterativo. Nel listato che segue, si assume inizialmente che il minimo
ed il massimo siano entrambi rappresentati dall'elemento di testa (linee 3 e
4). Successivamente si scandiscono in sequenza gli elementi della lista. Ogni
volta che viene individuato un elemento minore del minimo corrente (linea
8), il minimo corrente viene aggiornato (linea 9). Analogo discorso vale per
il massimo (linee 10 e 11).
1void L i s t a : : MinMax ( TElem& min , TElem& max) const {
2 if ( first ) {
3 min = f i r s t −>e l ;
4 max = f i r s t −>e l ;
5 PRec p = f i r s t −>s u c c ;
6
7 while ( p ) {
8 if ( p−>e l < min )
9 min = p−>e l ;
10 if ( p−>e l > max)
11 max = p−>e l ;
12 p = p−>s u c c ;
13 }
14 }
15 }
SL. Soluzioni degli esercizi su liste 59
void I n s e r i s c i I n C o d a ( TElem el );
void Svuota ( ) ;
void Stampa ( ) const ;
int Count ( ) const ;
};
L i s t a : : L i s t a ( ) : nelem ( 0 ) {
}
void L i s t a : : I n s e r i s c i I n C o d a ( TElem e l ) {
if ( nelem < NMAX) {
v [ nelem ] = e l ;
nelem++;
}
}
void L i s t a : : Svuota ( ) {
nelem = 0 ;
}
void stampa_menu( ) {
c out << " 1 : I n s e r i s c i I n C o d a . \ n" ;
c out << " 2 : Svuota . \ n" ;
c out << " 3 : Stampa . \ n" ;
c out << " 4 : Count . \ n" ;
c out << " 5 : E s c i . \ n" ;
}
SL. Soluzioni degli esercizi su liste 60
void I n s e r i s c i I n C o d a ( L i s t a& l );
void Svuota ( L i s t a& l ) ;
void Stampa ( L i s t a& l ) ;
void Count ( L i s t a& l ) ;
int main ( )
{
Lista l ;
int s c e l t a ;
do {
stampa_menu ( ) ;
c i n >> s c e l t a ;
switch ( scelta ) {
case 1:
InserisciInCoda ( l ) ;
break ;
case 2:
Svuota ( l ) ;
break ;
case 3:
Stampa ( l ) ;
break ;
case 4:
Count ( l ) ;
break ;
case 5:
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
break ;
}
} while ( s c e l t a != 5 ) ;
return 0 ;
}
void I n s e r i s c i I n C o d a ( L i s t a& l ) {
TElem e l ;
c out << " I n s e r i s c i v a l o r e e le me nt o : " ;
c i n >> e l ;
l . InserisciInCoda ( el ) ;
}
8 3 0 0 1 0 5 4 nelem = 8
1 2 3 4 5
8 3 1 5 4 nelem = 5
SL.6 È Ordinata
Traccia a pag. 14
class L i s t a {
private :
...
TElem valoreCoda ;
...
};
void L i s t a : : I n s e r i s c i ( TElem e l ) {
// I n s e r i m e n t o i n t e s t a
PRec p = new Record ;
p−>e l = e l ;
p−>s u c c = f i r s t ;
first = p;
nelem++;
// Se q u e l l o i n s e r i t o è i l primo elemento , b i s o g n a a g g i o r n a r e
// i l v a l o r e d e l l a coda .
if ( ! f i r s t −>s u c c )
v alor e C oda = e l ;
}
void L i s t a : : SommaCoda ( ) {
if ( first ) {
// Se l a l i s t a non è vuota , l a v a r i a b i l e −membro c o n t i e n e un v a l . c o r r e t t o .
//Lo sommo a t u t t i g l i e l e m e n t i .
PRec p = f i r s t ;
while (p) {
p−>e l = p−>e l + v alor e C oda ;
p = p−>s u c c ;
}
// Metodo p r i v a t o
return p;
}
else
return 0 ; //non e s i s t e una coda s e l a l i s t a è vuota
}
// Metodo p u b b l i c o
return n;
}
f i r s t = f i r s t −>s u c c ;
delete tbd ;
n++;
return n;
}
class L i s t a {
private :
PRec f i r s t ;
PRec l a s t ;
unsigned int nelem ;
L i s t a ( const L i s t a &); // i n i b i s c e l a c o p i a mediante c o s t r u t t o r e
void operator= ( const L i s t a &); // i n i b i s c e l ' a s s e g n a z i o n e
public :
Lista ( ) ;
~Lista ( ) ;
void I n s e r i s c i ( TElem e l ) ;
void Svuota ( ) ;
void St ampaDir e t t a ( ) const ;
void St ampaInv e r s a ( ) const ;
void StampaAlter nat a ( ) const ;
unsigned int Count ( ) const ;
};
L i s t a : : L i s t a ( ) : f i r s t ( 0 ) , l a s t ( 0 ) , nelem ( 0 ) {
}
void L i s t a : : I n s e r i s c i ( TElem e l ) {
SL. Soluzioni degli esercizi su liste 67
// I n s e r i m e n t o i n coda
PRec p = new Record ;
p−>e l = e l ;
p−>s u c c = 0 ;
p−>p r e c = l a s t ;
if ( last )
l a s t −>s u c c = p ;
last = p;
if (! first )
first = p;
nelem++;
}
void L i s t a : : Svuota ( ) {
PRec tbd ; // t o be d e l e t e d
while ( f i r s t != 0) {
tbd = f i r s t ;
f i r s t = f i r s t −>s u c c ;
delete tbd ;
}
nelem = 0 ;
last = 0;
}
p = p−>s u c c ;
q = q−>p r e c ;
}
}
SL. Soluzioni degli esercizi su liste 68
void stampa_menu( ) {
c out << " 1 : I n s e r i s c i . \ n" ;
c out << " 2 : Svuota . \ n" ;
c out << " 3 : Stampa D i r e t t a . \ n" ;
c out << " 4 : Stampa I n v e r s a . \ n" ;
c out << " 5 : Stampa A l t e r n a t a . \ n" ;
c out << " 6 : Count . \ n" ;
c out << " 7 : E s c i . \ n" ;
}
void I n s e r i s c i ( L i s t a& l ) ;
void Svuota ( L i s t a& l ) ;
void St ampaDir e t t a ( L i s t a& l ) ;
void St ampaInv e r s a ( L i s t a& l ) ;
void StampaAlternat a ( L i s t a& l ) ;
void Count ( L i s t a& l ) ;
int main ( )
{
Lista l ;
int s c e l t a ;
do {
stampa_menu ( ) ;
c i n >> s c e l t a ;
switch ( scelta ) {
case 1:
Inserisci ( l );
break ;
case 2:
Svuota ( l ) ;
break ;
case 3:
St ampaDir e t t a ( l ) ;
break ;
case 4:
St ampaInv e r s a ( l ) ;
break ;
case 5:
StampaAlternat a ( l ) ;
break ;
case 6:
Count ( l ) ;
break ;
case 7:
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
break ;
}
} while ( s c e l t a != 7 ) ;
return 0 ;
}
void I n s e r i s c i ( L i s t a& l ) {
TElem e l ;
c out << " I n s e r i s c i v a l o r e e le me nt o : " ;
SL. Soluzioni degli esercizi su liste 69
c i n >> e l ;
l . Inserisci ( el );
}
SL.13 Ribalta
Traccia a pag. 18
L'approccio in generale più eciente per ribaltare la lista consiste nel modi-
care la congurazione di tutti i puntatori contenuti nella struttura, senza
pertanto eettuare spostamenti sici di elementi. Di seguito si forniscono
due soluzioni, la prima basata su un metodo iterativo, la seconda su uno
ricorsivo.
Approccio iterativo
Si consideri la Figura SL.3(a), in cui è riportata la lista di partenza. Per
ottenerne il ribaltamento è suciente che il campo succ del primo elemento
(che punta ad el2 ) passi a puntare a 0, che il campo succ del secondo elemento
(che punta ad el3 ) passi a puntare al primo, che il campo succ del terzo
elemento (che punta ad el4 ) passi a puntare al secondo. . . e così via. Inne,
il puntatore first (che punta ad el1 ) dovrà puntare all'elemento eln . Questo
procedimento può essere svolto servendosi di due puntatori che iniziano a
scorrere la lista nell'unica direzione concessa, puntando di volta in volta a
SL. Soluzioni degli esercizi su liste 70
p1 p2
(b) Prima dell'i-esima iterazione
p1 p2 temp
(c) Dopo l'i-esima iterazione
// Versione i t e r a t i v a d e l metodo R i b a l t a ( )
// Metodo P u b b l i c o
void Lista : : Ribalta () {
if ( f i r s t && f i r s t −>s u c c ) { // s e l a l i s t a c o n t i e n e almeno 2 e l e m e n t i
PRec p1 = f i r s t ; // memorizzo i n p1 i l primo
PRec p2 = p1−>s u c c ; // memorizzo i n p2 i l secondo
p1−>s u c c = 0 ; // p1 , d i v e n t a n d o l ' u l t i m o elemento , deve puntare a z e r o
p1 = p2 ; // p1 d i v e n t a p2 ;
p2 = temp ; // p2 d i v e n t a temp
}
// i n q u e s t o punto d e l c o d i c e p1 e p2 puntano a g l i u l t i m i
// due e l e m e n t i d e l l a l i s t a .
p2−>s u c c = p1 ; // i l s u c c e s s i v o d i p2 è ora p1
f i r s t = p2 ; // p2 ora è l a nuova t e s t a
}
}
Approccio ricorsivo
Il ribaltamento della lista può essere approcciato come un problema ricorsivo.
Infatti, avendo una lista, la sua versione ribaltata si ottiene isolando il primo
elemento, ribaltando la restante parte della lista, e posponendo a questa
l'elemento isolato. Il problema del ribaltamento di una lista si riconduce
dunque al ribaltamento di una seconda lista costituita da un elemento in
meno. Di questo passo ci si troverà a ribaltare una lista costituita da un unico
elemento, la cui versione ribaltata è uguale a sé stessa. Durante il processo
di ribaltamento bisogna anche prestare attenzione a redirigere correttamente
la testa della (sotto)lista di volta in volta considerata. A questo proposito, il
metodo ricorsivo _Ribalta() riceve in ingresso il puntatore alla testa della
lista da ribaltare e restituisce la testa della lista ribaltata.
// Versione r i c o r s i v a d e l metodo R i b a l t a ( )
// Metodo p r i v a t o
PRec L i s t a : : _ r i b a l t a ( PRec p ) {
if( ( ! p ) | | ( ! p−>s u c c ) ) // s e l a l i s t a è formata da 0 o 1 e l e m e n t i
//non f a c c i o n i e n t e
return p;
else {
SL. Soluzioni degli esercizi su liste 72
// memorizzo i n v e c c h i a _ t e s t a l a v e c c h i a t e s t a
PRec v e c c h i a _ t e s t a = p ;
// memorizzo i n vecchio_secondo i l v e c c h i o secondo elemento
PRec v e c c hio_s e c ondo = p−>s u c c ;
// r i b a l t o l a s o t t o l i s t a con t e s t a i n vecchio_secondo . . .
// . . . e memorizzo i n nuova_testa l a nuova t e s t a .
PRec nuova_testa = _ r i b a l t a ( v e c c hio_se c ondo ) ;
// Metodo p u b b l i c o
void Lista : : Ribalta () {
f i r s t = _ribalta ( f i r s t ) ;
}
Capitolo SA
Soluzioni degli esercizi su alberi
binari
File AlberoBinario.h
#ifndef _ALBEROBINARIO_H_
#define _ALBEROBINARIO_H_
struct Nodo ; // Forward d e c l a r a t i o n
typedef Nodo ∗ PNodo ;
typedef int TElem ; //L ' a l b e r o c o n t i e n e interi
class A l b e r o B i n a r i o {
private :
PNodo r o o t ; // r a d i c e d e l l ' a l b e r o
// Metodi r i c o r s i v i d i s u p p o r t o
void_CopiaAlbero ( PNodo& de st , const PNodo& s o u r c e ) ;
void_Svuota ( const PNodo& n ) ;
void_AggiungiElem ( PNodo& n , const TElem& e l ) ;
void_ S o s t i t u i s c e ( PNodo& n , PNodo& p ) ;
bool_InAlb ( const const
PNodo& n , TElem& e l ) ; const
void_Elimina ( PNodo& n , const TElem& e l ) ;
void_PreOrdine ( const const
PNodo& n ) ;
void_PostOrdine ( const const
PNodo& n ) ;
void_InOrdine ( const const
PNodo& n ) ;
// o p e r a t o r e d i a s s e g n a z i o n e p r i v a t o : i n i b i s c e l ' a s s e g n a z i o n e
// che p r o v o c h e r e b b e una c o p i a s u p e r f i c i a l e
AlberoBinario& operator const =( A l b e r o B i n a r i o &);
public :
A l b e r o B i n a r i o ( ) ; // c o s t r u t t o r e senza parametri
73
SA. Soluzioni degli esercizi su alberi binari 74
#endif / ∗ _ALBEROBINARIO_H_ ∗ /
File AlberoBinario.cpp
#include <i o s t r e a m>
#include " A l b e r o B i n a r i o . h"
using namespace s t d ;
struct Nodo { // S t r u t t u r a Nodo
TElem e l ;
PNodo s i n ;
PNodo de s ;
};
AlberoBinario : :~ AlberoBinario () {
Svuota ( ) ;
}
// Metodi p r i v a t i r i c o r s i v i d i s u p p o r t o
//Ora b i s o g n a r i c r e a r e i l s o t t o a l b e r o s i n i s t r o ed i l s o t t o a l b e r o d e s t r o
// d e l nodo p u n t a t o da d e s t r i c o p i a n d o i r i s p e t t . s o t t o a l b e r i p u n t a t i da
// s o u r c e . R i f l e t t e n d o , l ' o p e r a z i o n e d e s i d e r a t a è d e l t u t t o analoga a q u e l l a
// g i à i n v o c a t a a p a r t i r e d a l l a r a d i c e . E ' q u i n d i p o s s i b i l e s f r u t t a r e l a
// r i c o r s i o n e ed i n v o c a r e l o s t e s s o " s e r v i z i o " _CopiaAlbero ( ) c o n s i d .
// source −>des e source −>s i n come r a d i c i d i due d i s t i n t i a l b e r i .
} else
if ( e l > n−>e l )
_Elimina ( n−>des , el );
else
_Elimina ( n−>s i n , e l ) ;
}
}
// Metodi p u b b l i c i
void A l b e r o B i n a r i o : : Svuota ( ) {
_Svuota ( r o o t ) ;
root = 0;
}
File main.cpp
#include <i o s t r e a m>
#include " A l b e r o B i n a r i o . h"
using namespace s t d ;
// P r o t o t i p i d i f u n z i o n i d i s u p p o r t o per l a v e r i f i c a d e l c o r r e t t o f u n z i o n .
// d e i metodi d e l l a c l a s s e A l b e r o B i n a r i o .
void stampaMenu ( ) ;
void I n s e r i s c i ( AlberoBinario& a ) ;
void Ricerca ( AlberoBinario& a ) ;
void E limina ( A l b e r o B i n a r i o & a ) ;
void Svuota ( A l b e r o B i n a r i o & a ) ;
void PreOrdine ( A l b e r o B i n a r i o & a ) ;
void InOr dine ( A l b e r o B i n a r i o & a ) ;
void P os t Or dine ( A l b e r o B i n a r i o & a ) ;
void Copia ( A l b e r o B i n a r i o & a ) ;
int main ( ) {
char c ;
AlberoBinario albero ;
do {
stampaMenu ( ) ;
c i n >> c ;
switch ( c ) {
case ' 1 ' :
I n s e r i s c i ( albero ) ;
break ;
case ' 2 ' :
Ricerca ( albero ) ;
break ;
case ' 3 ' :
E limina ( a l b e r o ) ;
break ;
case ' 4 ' :
Svuota ( a l b e r o ) ;
break ;
case ' 5 ' :
PreOrdine ( a l b e r o ) ;
break ;
case ' 6 ' :
InOr dine ( a l b e r o ) ;
break ;
case ' 7 ' :
P os t Or dine ( a l b e r o ) ;
break ;
case ' 8 ' :
Copia ( a l b e r o ) ;
SA. Soluzioni degli esercizi su alberi binari 78
break ;
case ' 9 ' :
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
break ;
}
} while ( c != ' 9 ' ) ;
return 0 ;
}
void stampaMenu ( ) {
c out << e n d l ;
c out << " 1 . I n s e r i s c i " << e n d l ;
c out << " 2 . R i c e r c a " << e n d l ;
c out << " 3 . E limina " << e n d l ;
c out << " 4 . Svuota " << e n d l ;
c out << " 5 . Pre − o r d i n e " << e n d l ;
c out << " 6 . InOr dine " << e n d l ;
c out << " 7 . Post −Ordine " << e n d l ;
c out << " 8 . Copia a l b e r o " << e n d l ;
c out << " 9 . E s c i " << e n d l ;
c out << e n d l ;
c out << " S c e l t a : " ;
}
void I n s e r i s c i ( A l b e r o B i n a r i o & a ) {
int i ;
c out << " I n s e r i s c i i n t e r o : " ;
c i n >> i ;
a . AggiungiElem ( i ) ;
}
void R i c e r c a ( A l b e r o B i n a r i o & a ) {
int i ;
c out << " I n s e r i s c i i n t e r o : " ;
c i n >> i ;
if ( a . InAlb ( i ) )
c out << " Trovato . \ n" ;
else
c out << "Non t r o v a t o . \ n" ;
}
// a l termine d i q u e s t a f u n z i o n e , l ' i s t a n z a d i A l b e r o B i n a r i o b v i e n e
// d i s t r u t t a e rimossa d a l l o s t a c k .
}
// Metodo p r i v a t o
unsigned int A l b e r o B i n a r i o : : _NumElem( const PNodo& n ) const {
if ( n )
return 1 + _NumElem( n−>s i n ) + _NumElem( n−>de s ) ;
else
return 0 ;
}
// Metodo p u b b l i c o
unsigned int A l b e r o B i n a r i o : : NumElem ( ) const {
return _NumElem( r o o t ) ;
}
SA.3 Occorrenze
Traccia a pag. 20
SA. Soluzioni degli esercizi su alberi binari 80
// Metodo p r i v a t o
return oc c ;
}
// Metodo p u b b l i c o
...
...
// Metodo p r i v a t o r i c o r s i v o d i s u p p o r t o
bool A l b e r o B i n a r i o : : _ I n s e r i s c i ( PNodo& n ,const int
TElem& e l , c ur r _oc c ) {
if ( ! n ) { // s e l ' a l b e r o è vuoto i n s e r i s c o certamente
n = new Nodo ;
n−>e l = e l ;
n−>s i n = 0 ;
n−>de s = 0 ;
return true ;
}
else {
if ( e l == n−>e l ) { // s e l ' elemento c o r r e n t e è p a r i ad e l . . .
c ur r _oc c++; // . . . incremento curr_occ . . .
if ( c ur r _oc c >= maxocc ) // . . . e s e ha r a g g i u n t o i l l i m i t e . . .
return false ; // . . . e s c o con i l v a l o r e f a l s e .
}
// Se sono q u i i l l i m i t e non è s t a t o r a g g i u n t o .
if ( e l > n−>e l )
return _ I n s e r i s c i ( n−>des , e l , c ur r _oc c ) ;
else
return _ I n s e r i s c i ( n−>s i n , e l , c ur r _oc c ) ;
}
}
// Metodo p u b b l i c o I n s e r i s c i ( )
bool A l b e r o B i n a r i o : : I n s e r i s c i ( const TElem& e l ) {
if ( maxocc > 0)
return _ I n s e r i s c i ( r oot , e l , 0 ) ;
else
return false ;
}
class AlberoBinario {
SA. Soluzioni degli esercizi su alberi binari 82
private :
...
const unsigned int maxDepth ;
...
public :
A l b e r o B i n a r i o ( unsigned int _maxDepth ) ;
...
bool I n s e r i s c i ( const TElem& e l ) ;
...
};
return true ;
}
else
if ( e l > n−>e l )
return _ I n s e r i s c i ( n−>des , e l , _maxDepth − 1 ) ;
else
return _ I n s e r i s c i ( n−>s i n , e l , _maxDepth − 1 ) ;
}
return false ;
}
// Metodi p u b b l i c i
AlberoBinario : : AlberoBinario ( unsigned int _maxDepth ) : r o o t ( 0 ) ,
maxDepth ( _maxDepth ) {
}
SA.6 Somma
Traccia a pag. 22
// Metodo p r i v a t o
// Metodo P u b b l i c o
SA.7 Sostituisci
Traccia a pag. 22
// Metodo p r i v a t o
// . . . p o i n e l l a r a d i c e
if ( n−>e l == i ) {
n−>e l = j ;
s o s t i t u z i o n i ++;
}
}
return sostituzioni ;
}
// Metodo p u b b l i c o
Il conteggio degli elementi compresi entro un certo intervallo può essere svolto
mediante una visita dell'albero. Data la proprietà di ordinamento dell'albero,
non è peraltro necessario visitare completamente la struttura. Si consideri
per esempio il caso in cui si debbano conteggiare gli elementi compresi nel-
l'intervallo (10, 20). In occasione della visita di un ipotetico elemento pari a
5, è inutile procedere verso il sottoalbero sinistro di tale elemento, che non
ha possibilità di fornire un contributo al conteggio in corso.
// Metodo p r i v a t o
unsigned int A l b e r o B i n a r i o : : _ContaMinMax ( const PNodo& n , TElem Min ,
SA. Soluzioni degli esercizi su alberi binari 84
return c ount ;
} else
return 0 ; //L ' a l b e r o è vuoto .
}
// Metodo p u b b l i c o
unsigned int A l b e r o B i n a r i o : : ContaMinMax ( TElem Min , TElem Max) const {
return _ContaMinMax ( r oot , Min , Max ) ;
}
// Metodo p r i v a t o
bool A l b e r o B i n a r i o : : _ProfMaggioreDi ( const
PNodo& n , unsigned int p) const {
if ( n ) { // s e l ' a l b e r o è non vuoto . . .
if
( p == 0) // s e i l c o n t a t o r e è ( s c e s o f i n o a ) z e r o . . .
SA. Soluzioni degli esercizi su alberi binari 85
// Metodo p u b b l i c o
bool A l b e r o B i n a r i o : : Pr of Maggior e Di ( unsigned int p) const {
return _ProfMaggioreDi ( r oot , p ) ;
}
// Metodo p r i v a t o
if (n) {
n−>e l += i ;
_SommaLivello ( n−>s i n , i +1);
_SommaLivello ( n−>des , i +1);
}
}
// Metodo p u b b l i c o
void A l b e r o B i n a r i o : : SommaLivello ( ) {
_SommaLivello ( r oot , 1 ) ;
}
// Metodi p r i v a t i
inline bool A l b e r o B i n a r i o : : EUnaFoglia ( const
PNodo& n ) {
// metodo d i s u p p o r t o che v e r i f i c a s e i l nodo
// p u n t a t o da n è o meno una f o g l i a .
return ( ! n−>s i n && ! n−>de s ) ;
}
return false ;
}
// Metodo p u b b l i c o
bool AlberoBinario : : EliminaFoglia( const TElem& e l ) {
if ( _E liminaF oglia ( r oot , e l ) ) {
numelem−−;
return true ;
} else
return false ;
}
// Metodi p r i v a t i
inline bool A l b e r o B i n a r i o : : EUnaFoglia ( const
PNodo& n ) {
// metodo d i s u p p o r t o che v e r i f i c a s e i l nodo
// p u n t a t o da n è o meno una f o g l i a .
return ( ! n−>s i n && ! n−>de s ) ;
}
return 0;
}
// Metodo p u b b l i c o
unsigned int A l b e r o B i n a r i o : : E l i m i n a F o g l i e ( ) {
unsigned int n = _EliminaF oglie ( r o o t ) ;
numelem = numelem − n ;
return n ;
//La s t e s s a o p e r a z i o n e può e s s e r e s i n t e t i z z a t a ( a s c a p i t o
// d e l l a l e g g i b i l i t à ) con l a s e g u e n t e r i g a d i c o d i c e :
// r e t u r n ( numelem −= _EliminaFoglie ( r o o t ) ) ;
}
// Metodi p r i v a t i
inline bool A l b e r o B i n a r i o : : EUnaFoglia ( const PNodo& n ) const {
return ( ! n−>de s && ! n−>s i n ) ;
}
// Metodi r i c o r s i v i d i s u p p o r t o
bool A l b e r o B i n a r i o : : _C e r c aF oglia ( const PNodo& n , TElem e l ,
bool
& foglia ) const {
if ( ! n)
return false ;
bool t r o v a t o ;
// Cerco s u b i t o p i ù i n b a s s o .
if ( e l > n−>e l )
t r o v a t o = _C e r c aF oglia ( n−>des , e l , f o g l i a ) ;
else
t r o v a t o = _C e r c aF oglia ( n−>s i n , e l , f o g l i a ) ;
if ( ! t r o v a t o ) { // Se p i ù i n b a s s o non l ' ho t r o v a t o . . .
SA. Soluzioni degli esercizi su alberi binari 88
if ( n−>e l == e l ) { // . . . e sono p r o p r i o i o . . .
trovato = true
; // . . . imposto t r o v a t o a t r u e . . .
f o g l i a = EUnaFoglia ( n ) ; // . . . e v e r i f i c o s e è una f o g l i a .
}
}
return trovato ;
}
// Metodi p u b b l i c i
boolA l b e r o B i n a r i o : : C e r c a F o g l i a ( TElem e l , bool& foglia ) const {
return _C e r c aF oglia ( r oot , e l , f o g l i a ) ;
}
// Metodo p r i v a t o
bool A l b e r o B i n a r i o : : _uguale ( const PNodo& n1 , const
PNodo& n2 ) { const
if ( n1 == n2 ) // Se i p u n t a t o r i a l l e r a d i c i coincidono , g l i a l b e r i
return true ; // sono u g u a l i .
// Abbiamo g e s t i t o anche l ' e v e n t u a l i t à che
// g l i a l b e r i s i a n o entrambi v u o t i .
// Metodo p u b b l i c o
bool AlberoBinario : : operator const
==( AlberoBinario& rhs ) { const
// Chiamo i l metodo p r i v a t o _uguale ( ) e g l i passo l a mia r a d i c e
// e l a r a d i c e d e l l ' a l b e r o r h s .
return_uguale ( r oot , r h s . r o o t ) ;
}
// Metodo p r i v a t o
unsigned int A l b e r o B i n a r i o : : _ContaNodiNonFoglia ( const PNodo& n ) const {
if ( ! n )
return 0 ;
unsigned int c ount = 0 ;
// e v e n t u a l e c o n t r i b u t o s o t t o a l b e r o s i n i s t r o
if ( n−>s i n )
c ount = c ount + _ContaNodiNonFoglia ( n−>s i n ) ;
// e v e n t u a l e c o n t r i b u t o s o t t o a l b e r o d e s t r o
if ( n−>de s )
c ount = c ount + _ContaNodiNonFoglia ( n−>de s ) ;
// e v e n t u a l e c o n t r i b u t o d e l p r e s e n t e nodo
if ( n−>s i n | | n−>de s )
c ount++;
return c ount ;
}
// Metodo p u b b l i c o
unsigned int A l b e r o B i n a r i o : : ContaNodiNonFoglia ( ) const {
return _ContaNodiNonFoglia ( r o o t ) ;
}
// Metodo p r i v a t o
void A l b e r o B i n a r i o : : _ContaNodi ( const PNodo& n , unsigned int& z e r o ,
unsigned int& uno , unsigned int& due ) const {
if (n) {
_ContaNodi ( n−>s i n , z e r o , uno , due ) ;
_ContaNodi ( n−>des , z e r o , uno , due ) ;
// Metodo p u b b l i c o
void A l b e r o B i n a r i o : : ContaNodi ( unsigned int& zero , unsigned int& uno ,
unsigned int& due ) const {
zero = 0;
uno = 0 ;
due = 0 ;
_ContaNodi ( r oot , z e r o , uno , due ) ;
}
class A l b e r o B i n a r i o {
private :
...
if ( r e s u l t ) // Se l ' ho t r o v a t o . . .
return r e s u l t ; // . . . l o r e s t i t u i s c o . . .
else
if ( n−>e l == e l ) // . . . a l t r i m e n t i v e r i f i c o d i non e s s e r e l ' elem . c e r c a t o .
return n ; // Se sono io , r e s t i t u i s c o i l p u n t a t o r e a me stesso . . .
else
return 0 ; // . . . a l t r i m e n t i r e s t i t u i s c o 0 .
} else
return 0 ;
}
// Metodi p u b b l i c i
unsigned int A l b e r o B i n a r i o : : ContaNodiSottoalb_Min ( const TElem& e l ) const {
PNodo n = _CercaOccorrenzaMin ( r oot , e l ) ;
if ( n ) //C ' è almeno un elemento p a r i ad e l ?
return _ContaNodi ( n ) ;
else
return 0 ;
SA. Soluzioni degli esercizi su alberi binari 92
class P i l a {
private :
PRec top ;
int nelem ;
public :
P i l a ( unsigned int p = 0);
~Pila ( ) ;
P i l a : : P i l a ( ) : top ( 0 ) , nelem ( 0 ) {
}
93
SP. Soluzioni degli esercizi su pile 94
TElem P i l a : : Pop ( ) {
if
( top ) {
TElem e = top −>e l ; // memorizza i l v a l o r e d i t e s t a per r e s t i t . a l l a f i n e
// memorizza i l p u n t a t o r e a l l a t e s t a : e s s a dovrà e s s e r e c a n c e l l a t a
PRec p = top ;
top = top −>s u c c ; // p o r t a l a t e s t a a l s u c c e s s i v o
delete p ; // e l i m i n a l a v e c c h i a t e s t a
nelem −−;
return e;
}
void P i l a : : Svuota ( ) {
while ( top ) {
PRec p = top ;
top = top −>s u c c ;
delete p;
}
nelem = 0 ;
}
void stampaMenu ( ) ;
void Push ( P i l a& p ) ;
void PushGreater ( P i l a& p ) ;
void Top ( P i l a& p ) ;
void Pop ( P i l a& p ) ;
SP. Soluzioni degli esercizi su pile 95
do {
stampaMenu ( ) ;
c i n >> c ;
cin . ignore ( ) ;
switch ( c ) {
case ' 1 ' :
Push ( p i l a ) ;
break ;
case ' 2 ' :
PushGreater ( p i l a ) ;
break ;
case ' 3 ' :
Top ( p i l a ) ;
break ;
case ' 4 ' :
Pop ( p i l a ) ;
break ;
case ' 5 ' :
Svuota ( p i l a ) ;
break ;
case ' 6 ' :
Count ( p i l a ) ;
break ;
case ' 7 ' :
Empty ( p i l a ) ;
break ;
case ' 8 ' :
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
break ;
}
} while ( c != ' 8 ' ) ;
return 0 ;
}
void stampaMenu ( ) {
c out << e n d l ;
c out << " 1 . Push" << e n d l ;
c out << " 2 . PushGreater " << e n d l ;
c out << " 3 . Top" << e n d l ;
c out << " 4 . Pop" << e n d l ;
c out << " 5 . Svuota " << e n d l ;
c out << " 6 . Count " << e n d l ;
c out << " 7 . Empty" << e n d l ;
c out << " 8 . E s c i " << e n d l ;
c out << e n d l ;
c out << " S c e l t a : " ;
}
TElem e l ;
c out << " I n s e r i r e e le me nt o : " ;
c i n >> e l ;
p . Push ( e l ) ;
}
SP.2 Push If
Traccia a pag. 29
class P i l a {
private :
...
const unsigned int _maxpush ;
unsigned int _currpush ;
void _Push ( const TElem& e ) ;
SP. Soluzioni degli esercizi su pile 97
...
};
La variabile membro _maxpush tiene memoria di qual è il numero di
inserimenti massimi consecutivi ammessi; il suo valore è inizializzato dal co-
struttore al valore del parametro di ingresso e mai più variato durante il ciclo
di vita delle istanze della classe. La variabile membro _currpush tiene me-
moria del numero di inserimenti consecutivi correntemente eettuati. Ogni
chiamata al metodo Push() deve vericare che questo parametro non ecce-
da il valore massimo consentito. Il metodo privato _Push() è implementato
come una classica Push().
Di seguito si riporta l'implementazione dei metodi richiesti dalla traccia.
Pila : : Pila ( unsigned int
maxpush ) :
top ( 0 ) , nelem ( 0 ) , _maxpush( maxpush ) , _currpush ( 0 ) {
}
return false ;
}
TElem P i l a : : Pop ( ) {
if
( top ) {
// memorizza i l v a l o r e d i t e s t a per r e s t i t u i r l o a l l a f i n e
TElem e = top −>e l ;
// memorizza i l p u n t a t o r e a l l a t e s t a : e s s a dovrà e s s e r e c a n c e l l a t a
PRec p = top ;
top = top −>s u c c ; // p o r t a l a t e s t a a l s u c c e s s i v o
delete p ; // e l i m i n a l a v e c c h i a t e s t a
nelem −−;
_currpush = 0 ; // a z z e r o i l c o n t e g g i o d e g l i i n s e r i m e n t i
return e;
}
// q u e s t o metodo r e s t i t u i s c e un v a l o r e non
// s p e c i f i c a t o n e l caso l a p i l a s i a vuota
}
void P i l a : : Svuota ( ) {
while ( top ) {
PRec p = top ;
SP. Soluzioni degli esercizi su pile 98
SC.1 Coda
Traccia a pag. 31
class Coda {
private :
PRec head ;
PRec t a i l ;
int nelem ;
public :
Coda ( ) ;
~Coda ( ) ;
void const
Push ( TElem& e ) ;
TElem Top ( )const ;
TElem Pop ( ) ;
TElem Somma ( )const ;
void Svuota ( ) ;
unsigned int const
Count ( ) ;
bool Empty ( )const ;
};
Coda : : ~ Coda ( ) {
Svuota ( ) ;
99
SC. Soluzioni degli esercizi su code 100
nelem++;
}
nelem −−;
delete temp ;
return el_temp ;
}
}
return sum ;
}
head = t a i l = 0 ;
nelem = 0 ;
}
void stampaMenu ( ) ;
void Push ( Coda& c ) ;
void Top ( Coda& c ) ;
void Pop ( Coda& c ) ;
void Somma( Coda& c ) ;
void Svuota ( Coda& c ) ;
void Count ( Coda& c ) ;
void Empty ( Coda& c ) ;
int main ( )
{
char c ;
Coda coda ;
do {
stampaMenu ( ) ;
c i n >> c ;
cin . ignore ( ) ;
switch ( c ) {
case ' 1 ' :
Push ( coda ) ;
break ;
case ' 2 ' :
Top ( coda ) ;
break ;
case ' 3 ' :
Pop ( coda ) ;
break ;
case ' 4 ' :
Somma( coda ) ;
break ;
case ' 5 ' :
Svuota ( coda ) ;
break ;
case ' 6 ' :
Count ( coda ) ;
break ;
case ' 7 ' :
Empty ( coda ) ;
break ;
case ' 8 ' :
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
break ;
}
} while ( c != ' 8 ' ) ;
return 0 ;
SC. Soluzioni degli esercizi su code 102
void stampaMenu ( ) {
c out << e n d l ;
c out << " 1 . Push" << e n d l ;
c out << " 2 . Top" << e n d l ;
c out << " 3 . Pop" << e n d l ;
c out << " 4 . Somma" << e n d l ;
c out << " 5 . Svuota " << e n d l ;
c out << " 6 . Count " << e n d l ;
c out << " 7 . Empty" << e n d l ;
c out << " 8 . E s c i " << e n d l ;
c out << e n d l ;
c out << " S c e l t a : " ;
}
class Coda {
private :
PRec head ;
PRec t a i l ;
const unsigned int p o s t i ;
int nelem ;
public :
Coda ( unsigned int _post i ) ;
~Coda ( ) ;
bool const
Push ( TElem& e ) ;
TElem Top ( )const ;
TElem Pop ( ) ;
unsigned int
TElem Pop ( n);
void Svuota ( ) ;
unsigned int const
Count ( ) ;
bool Empty ( )const ;
};
Coda : : ~ Coda ( ) {
Svuota ( ) ;
}
nelem++;
return true ;
}
nelem −−;
delete temp ;
return el_temp ;
}
}
return el ;
}
}
head = t a i l = 0 ;
nelem = 0 ;
}
void stampaMenu ( ) ;
void Push ( Coda& c ) ;
void Top ( Coda& c ) ;
void Pop ( Coda& c ) ;
void PopMany( Coda& c ) ;
void Svuota ( Coda& c ) ;
void Count ( Coda& c ) ;
void Empty ( Coda& c ) ;
int main ( )
{
char c ;
unsigned int i ;
c out << " I n s e r i r e i l numero massimo d i e l e m e n t i i n coda : " ;
c i n >> i ;
Coda coda ( i ) ;
do {
stampaMenu ( ) ;
c i n >> c ;
cin . ignore ( ) ;
switch ( c ) {
case ' 1 ' :
Push ( coda ) ;
break ;
case ' 2 ' :
Top ( coda ) ;
break ;
case ' 3 ' :
Pop ( coda ) ;
break ;
case ' 4 ' :
PopMany( coda ) ;
break ;
case ' 5 ' :
Svuota ( coda ) ;
break ;
case ' 6 ' :
Count ( coda ) ;
break ;
case ' 7 ' :
Empty ( coda ) ;
break ;
case ' 8 ' :
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
break ;
}
} while ( c != ' 8 ' ) ;
return 0 ;
}
void stampaMenu ( ) {
c out << e n d l ;
c out << " 1 . Push" << e n d l ;
SC. Soluzioni degli esercizi su code 106
if ( ! c . Empty ( ) )
c out << " Elemento d i t e s t a : " << c . Pop ( i ) << e n d l ;
else
c out << "Coda vuota . " << e n d l ;
}
Si vuole una coda in cui gli elementi possano essere liberamente accodati
e siano connotati da uno tra due possibili livelli di priorità. Il prelievo di
un elemento dalla coda dovrà rispettare, in primis, il livello di priorità e,
nell'ambito degli elementi aventi la stessa priorità, la disciplina rst-in-rst-
out (FIFO) di una coda.
La traccia specica esclusivamente il comportamento esteriore della
struttura dati, senza denire alcun dettaglio di natura implementativa. Per
ottenere una struttura avente il comportamento specicato è possibile seguire
diverse strade. Di seguito sono riportate alcune possibilità.
Approccio 1
La coda a priorità può essere immaginata formata da una sequenza di ele-
menti costituita a sua volta da due sotto-sequenze (vedi Figura SC.1):
• una prima sotto-sequenza, che parte dalla testa, che comprende gli
elementi a priorità alta;
• una successiva sotto-sequenza, che si estende no alla coda, che com-
prende gli elementi a priorità bassa.
File PriorityQueue.h
typedef int TElem ;
struct Record ;
typedef Record ∗ PRec ;
class P r i o r i t y Q u e u e {
SC. Soluzioni degli esercizi su code 108
H H H H L L L L L
t h c
private :
PRec head ;
PRec t a i l ; // p u n t a t o r e a l l a coda
PRec t a i l _ h ; // p u n t a t o r e a l l a coda d e l l a s o t t o s e q u e n z a ad a l t a p r i o r i t à
void Push ( const TElem& e ) ; // c l a s s i c o Push i n coda
public :
PriorityQueue ( ) ;
~PriorityQueue ( ) ;
File PriorityQueue.cpp
#include " P r i o r i t y Q u e u e . h"
typedef struct Record {
TElem e l ;
PRec s u c c ;
};
P r i o r i t y Q u e u e : : P r i o r i t y Q u e u e ( ) : head ( 0 ) , t a i l ( 0 ) , t a i l _ h ( 0 ) {}
PriorityQueue : :~ PriorityQueue () {
Clear ( ) ;
}
void const
P r i o r i t y Q u e u e : : Push ( TElem& e ) { // c l a s s i c o Push i n coda
// Creo un nuovo elemento n e l l ' heap
PRec temp = new Record ;
temp−>e l = e ;
temp−>s u c c = 0 ;
if ( ! head )
head = temp ;
}
//non c i sono e l e m e n t i ad a l t a p r i o r i t à : a g g i u n t a i n t e s t a
if ( ! head ) // l a coda è vuota ?
Push ( e ) ; // i n s e r i s c o con Push ( )
else {
PRec temp = new Record ;
temp−>e l = e ;
temp−>s u c c = head ;
head = temp ;
}
} else {
// i n s e r i s c o
PRec temp = new
Record ;
temp−>e l = e ;
temp−>s u c c = t ail_h −>s u c c ;
t ail_h −>s u c c = temp ;
t a i l _ h = temp ; // a g g i o r n o i l p u n t a t o r e t a i l _ h
// a g g i o r n o t a i l s e l ' elemento a g g i u n t o è i n u l t i m a p o s i z i o n e
if ( ! t ail_h −>s u c c )
t a i l = tail_h ;
}
}
TElem P r i o r i t y Q u e u e : : Pop ( ) {
if
( head ) {
PRec temp = head ;
TElem el_temp = temp−>e l ;
delete temp ;
return el_temp ;
}
}
SC. Soluzioni degli esercizi su code 110
CODA A PRIORITÀ
t c
SOTTO-CODA AD
H H H H ALTA PRIORITÀ
SOTTO-CODA A
L L L L L BASSA PRIORITÀ
t c
void P r i o r i t y Q u e u e : : C l e a r ( ) {
while ( head != 0) {
PRec tbd = head ;
head = head −>s u c c ;
deletetbd ;
}
head = t a i l = t a i l _ h = 0 ;
}
Approccio 2
La coda a priorità può essere immaginata composta di due classiche code
aancate (vedi Figura SC.2), ciascuna destinata a contenere gli elementi di
una singola classe. Il metodo PushLow() accoda nella coda a bassa priorità.
Il metodo PushHigh(), viceversa, in quella ad alta priorità. Il metodo Pop()
restituisce l'elemento di testa nella coda ad alta priorità, se esiste; in caso
contrario restituisce l'elemento di testa nella coda a bassa priorità.
Servendosi del meccanismo dell'aggregazione stretta tra classi, le due co-
de aancate risultano istanze della classe Coda (vedi EC.1). Denendo tali
istanze come membri privati della classe PriorityQueue esse non risulteran-
no visibili dall'esterno della struttura (information hiding ), la quale conti-
nuerà ad apparire ai suoi utenti come una singola coda dotata dei meccanismi
di priorità richiesti.
#include " coda . h"
class P r i o r i t y Q u e u e {
private :
Coda coda_l ;
Coda coda_h ;
SC. Soluzioni degli esercizi su code 111
TElem P r i o r i t y Q u e u e : : Pop ( ) {
if
( ! coda_h . Empty ( ) )
return coda_h . Pop ( ) ;
else
return coda_l . Pop ( ) ;
}
Approccio 3
La coda a priorità può essere una normale coda in cui i record, disposti
1
secondo l'ordine di inserimento, vengono etichettati con la loro priorità (ve-
di Figura SC.3). In questo caso sia il metodo PushHigh() che il metodo
PushLow(), previa opportuna etichettatura, eettuano un'aggiunta in coda.
È il metodo Pop() in questo caso a prendersi carico della restituzione del
giusto elemento. Tale operazione viene eettuata scorrendo tutta la strut-
tura alla ricerca del primo elemento ad alta priorità e restituendolo dopo
averlo eliminato dalla coda. In assenza di un elemento ad alta priorità viene
restituito l'eventuale elemento di testa.
1 Questo
è possibile previa denizione di un'opportuna struct che contenga un TElem
ed un bool indicante la relativa priorità.
SC. Soluzioni degli esercizi su code 112
el el el el el el el el el
L L H H L H L L H
t c
SC.4 PopMinMax
Traccia a pag. 34
// Metodo p r i v a t o
unsigned int i = 1;
// c o n f r o n t o con g l i a l t r i n−1 e l e m e n t i s e g u e n t i : n−1 i t e r a z i o n i
// ( s e l a coda non s i s v u o t a prima )
while ( ( i < n ) && ! Empty ( ) ) {
TElem e l = Pop ( ) ;
if ( e l < min )
min = e l ;
if ( e l > max)
max = e l ;
i ++;
}
}
// Metodi p u b b l i c i
SX.1 Accumulatore
Traccia a pag. 36
int main ( )
{
Accumulatore a ;
floatf;
charch ;
do {
c i n >> ch ;
switch ( ch ) {
case 'a ' :
c out << " I n s e r t v a l u e : " ;
c i n >> f ;
a . Add( f ) ;
c out << " Value added . \ n" ;
break ;
case 'r ':
a . Reset ( ) ;
c out << " R e se t . \ n" ;
113
SX. Soluzioni degli altri esercizi 114
break ;
case ' s ' :
c out << "The v a l u e i s " << a . GetValue ( ) << e n d l ;
break ;
case ' e ' :
break ;
default :
c out << " I n v a l i d command . \ n" ;
}
} while ( ch != ' e ' ) ;
return 0 ;
}
SX.2 Cifratore
Traccia a pag. 36
int main ( )
{
char s t r [ 1 0 0 ] ;
int c h i a v e ;
c out << " I n s e r i s c i l a p a r o l a da c i f r a r e : " ;
c i n >> s t r ;
c out << " I n s e r i s c i l a c h i a v e d i c i f r a t u r a : " ;
c i n >> c h i a v e ;
Cifratore c ( chiave ) ;
system ( "PAUSE" ) ;
return 0;
}
struct Record ;
typedef Record ∗ PRec ;
struct Record {
Articolo art ;
PRec s u c c ;
};
class L i s t a D e l l a S p e s a {
private :
PRec f i r s t ;
bool R i c e r c a ( const Nome n , PRec& p ) const ;
SX. Soluzioni degli altri esercizi 116
// i n i b i s c e l a c o p i a mediante c o s t r u t t o r e
const
ListaDellaSpesa ( L i s t a D e l l a S p e s a &) { } ;
// i n i b i s c e l a c o p i a mediante a s s e g n a z i o n e
void operator const = ( L i s t a D e l l a S p e s a &) { } ;
public :
ListaDellaSpesa ( ) ;
~ListaDellaSpesa ( ) ;
return false ;
}
return false ;
}
SX. Soluzioni degli altri esercizi 117
if ( R i c e r c a ( n , p ) ) { // e s i s t e n e l l a l i s t a un elemento a v e n t e i l nome n?
// t r o v a t o => ora p punta a l l ' elemento a v e n t e nome n
p−>a r t . q += q ;
}
else {
// non t r o v a t o => ora p punta a l l ' u l t i m o elemento d e l l a l i s t a
p−>s u c c = new Record ;
p = p−>s u c c ;
s t r c p y ( p−>a r t . n , n ) ;
p−>a r t . q = q ;
p−>s u c c = 0 ;
}
return p−>a r t . q ;
}
}
void L i s t a D e l l a S p e s a : : Svuota ( ) {
if ( first ) {
PRec tbd = f i r s t ;
PRec p ;
while ( tbd ) {
p = tbd −>s u c c ;
delete tbd ;
tbd = p ;
}
}
f i r s t = 0;
}
void stampa_menu( ) {
c out << " 1 : A ggiungi a r t i c o l o . \ n" ;
c out << " 2 : E limina a r t i c o l o . \ n" ;
c out << " 3 : Quant it a ' a r t i c o l o . \ n" ;
c out << " 4 : Svuota l i s t a . \ n" ;
c out << " 5 : Stampa l i s t a . \ n" ;
c out << " 6 : E s e g u i t e s t v e l o c e . \ n" ;
c out << " 7 : E s c i . \ n" ;
}
int s c e l t a ;
do {
stampa_menu ( ) ;
c i n >> s c e l t a ;
switch ( scelta ) {
case 1:
A ggiungi ( l ) ;
break ;
case 2:
E limina ( l ) ;
break ;
case 3:
GetQuantita ( l ) ;
break ;
case 4:
Svuota ( l ) ;
break ;
case 5:
Stampa ( l ) ;
break ;
case 6:
TestVeloce ( l ) ;
break ;
case 7:
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
break ;
}
} while ( s c e l t a != 7 ) ;
return 0 ;
}
c i n >> q ;
qq = l . A ggiungi ( n , q ) ;
c out << "Ora l a q u a n t i t a ' e ' " << qq << e n d l ;
}
if ( l . E limina ( n ) )
c out << " A r t i c o l o e l i m i n a t o . " << e n d l ;
else
c out << " A r t i c o l o non e l i m i n a t o . " << e n d l ;
}
void T e s t V e l o c e ( L i s t a D e l l a S p e s a& l ) {
l . Svuota ( ) ;
l . A ggiungi ( "Pane " , 1 ) ;
l . A ggiungi ( " L a t t e " , 1 . 5 ) ;
l . A ggiungi ( " Z uc c he r o " , 1 ) ;
l . A ggiungi ( " P r o s c i u t t o " , 0 . 3 ) ;
l . Stampa ( ) ;
c out << " L a t t e : " << l . Aggiungi ( " L a t t e " , 0 . 5 ) << e n d l ;
l . E limina ( "Pane " ) ;
l . E limina ( " Z uc c he r o " ) ;
l . E limina ( " P r o s c i u t t o " ) ;
c out << " L a t t e : " << l . Aggiungi ( " L a t t e " , 0 . 5 ) << e n d l ;
l . Svuota ( ) ;
l . Stampa ( ) ;
}
T2 − T1
T̂ = (t − t1 ) + T1 ;
t2 − t1
dove T̂ è la stima della temperatura all'istante t; T1 , T2 , t1 e t2 sono
le ultime due letture della temperatura ed i relativi due istanti di lettura,
rispettivamente.
int main ( )
{
c out << " L e t t u r a : a l l ' i s t a n t e 0 : l a t e mpe r at ur a v a l e 14\ n" ;
SX. Soluzioni degli altri esercizi 121
// Posso c o s t r u i r e i l p r e d i t t o r e con q u e s t i d a t i .
TempPredictor tp ( 0 , 1 4 ) ;
//Comunico l a l e t t u r a a l p r e d i t t o r e
tp . SetTemp ( 5 , 1 6 ) ;
//Comunico l a l e t t u r a a l p r e d i t t o r e
tp . SetTemp ( 1 0 , 1 6 ) ;
system ( "PAUSE" ) ;
return 0;
}
SX.5 Contenitore
Traccia a pag. 39
struct Oggetto {
Nome n ;
Peso p ;
};
struct C e l l a ;
typedef C e l l a ∗ P C e lla ;
struct C e l l a {
Oggetto elem ;
P C e lla s u c c ;
};
class Contenitore {
SX. Soluzioni degli altri esercizi 122
private :
P C e lla f i r s t ;
Peso c a p a c i t a ;
Peso somma_pesi ;
unsigned int nelem ;
public :
C o n t e n i t o r e ( Peso max ) ;
~Contenitore ( ) ;
Contenitore : : ~ Contenitore () {
Svuota ( ) ;
}
return true ;
}
return false ;
}
void C o n t e n i t o r e : : Svuota ( ) {
while ( f i r s t ) {
P C e lla tbd = f i r s t ;
f i r s t = f i r s t −>s u c c ;
delete tbd ;
}
somma_pesi = 0 ;
nelem = 0 ;
}
return nelem ;
}
void I n s e r i s c i ( Contenitore& c ) ;
void Svuota ( C o n t e n i t o r e & c ) ;
void P e s oC omple s s iv o ( C o n t e n i t o r e & c ) ;
void P e s oR e s iduo ( C o n t e n i t o r e & c ) ;
void NumeroElementi ( C o n t e n i t o r e & c ) ;
void Stampa ( C o n t e n i t o r e & c ) ;
void stampa_menu( ) {
c out << " 1 : I n s e r i s c i . \ n" ;
c out << " 2 : Svuota . \ n" ;
c out << " 3 : Peso C omple ssiv o . \ n" ;
c out << " 4 : Peso Residuo . \ n" ;
c out << " 5 : Numero Ele me nt i . \ n" ;
c out << " 6 : Stampa . \ n" ;
c out << " 7 : E s c i . \ n" ;
}
int main ( )
{
Peso p ;
c out << " I n s e r i s c i pe so MAX c o n t e n i t o r e : " ;
c i n >> p ;
Contenitore c (p ) ;
int s c e l t a ;
do {
stampa_menu ( ) ;
c i n >> s c e l t a ;
switch ( scelta ) {
case 1:
Inserisci (c );
break ;
case 2:
Svuota ( c ) ;
break ;
case 3:
P e s oC omple s siv o ( c ) ;
break ;
case 4:
P e s oR e s iduo ( c ) ;
break ;
case 5:
NumeroElementi ( c ) ;
break ;
case 6:
Stampa ( c ) ;
break ;
case 7:
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
SX. Soluzioni degli altri esercizi 124
break ;
}
} while ( s c e l t a != 7 ) ;
return 0 ;
}
void I n s e r i s c i ( C o n t e n i t o r e & c) {
char n [NMAX] ;
Peso p ;
Nome nom ;
};
class L i s t a P r e n o t a z i o n i {
private :
P r e n o t a z i o n e ∗ pv ; // p u n t a t o r e a v e t t o r e p r e n o t a z . dinamicam . a l l o c a t o
int p o s t i ; //numero d i p o s t i d i s p o n i b i l i
int nelem ; // riempimento d e l v e t t o r e
int R i c e r c a ( M a t r i c o l a m) const ;
public :
L i s t a P r e n o t a z i o n i ( int n ) ;
~ListaPrenotazioni ( ) ;
int L i s t a P r e n o t a z i o n i : : R i c e r c a ( M a t r i c o l a m) const {
for ( int i = 0 ; i < nelem ; i ++)
if ( pv [ i ] . mat == m)
return i ;
return −1;
}
nelem++;
return true ;
}
return false ;
}
bool L i s t a P r e n o t a z i o n i : : E l i m i n a P r e n o t a z i o n e ( M a t r i c o l a m) {
int i = R i c e r c a (m) ;
if ( i >= 0) {
for ( int j = i ; j < nelem − 1 ; j ++)
pv [ j ] = pv [ j + 1 ] ;
nelem −−;
return true ;
}
SX. Soluzioni degli altri esercizi 126
return false ;
}
int L i s t a P r e n o t a z i o n i : : G e t P o s t i D i s p o n i b i l i ( ) const {
return p o s t i − nelem ;
}
bool L i s t a P r e n o t a z i o n i : : E s i s t e P r e n o t a z i o n e ( M a t r i c o l a m) const {
return ( R i c e r c a (m) >= 0 ) ;
}
void L i s t a P r e n o t a z i o n i : : Svuota ( ) {
nelem = 0 ;
}
void L i s t a P r e n o t a z i o n i : : Stampa ( ) {
for ( int i = 0 ; i < nelem ; i ++)
c out << pv [ i ] . mat << " : " << pv [ i ] . nom << e n d l ;
c out << e n d l ;
}
void stampa_menu( ) {
c out << " 1 : P r e not a . \ n" ;
c out << " 2 : E limina p r e n o t a z i o n e . \ n" ;
c out << " 3 : P o s t i d i s p o n i b i l i . \ n" ;
c out << " 4 : E s i s t e P r e n o t a z i o n e . \ n" ;
c out << " 5 : Svuota . \ n" ;
c out << " 6 : Stampa . \ n" ;
c out << " 7 : E s c i . \ n" ;
}
ListaPrenotazioni l (n ) ;
int s c e l t a ;
do {
stampa_menu ( ) ;
c i n >> s c e l t a ;
switch ( scelta ) {
case 1:
P r e not a ( l ) ;
break ;
case 2:
E limina ( l ) ;
break ;
case 3:
GetPostiDisponibili ( l );
break ;
case 4:
SX. Soluzioni degli altri esercizi 127
EsistePrenotazione ( l ) ;
break ;
case 5 :
Svuota ( l ) ;
break ;
case 6 :
Stampa ( l ) ;
break ;
case 7 :
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
break ;
}
} while ( s c e l t a != 7 ) ;
return 0 ;
}
if ( l . P r e not a (m, n ) )
c out << " P r e n o t a z i o n e e f f e t t u a t a . \ n" ;
else
c out << " P r e n o t a z i o n e non e f f e t t u a t a . \ n" ;
}
if ( l . E l i m i n a P r e n o t a z i o n e (m) )
c out << " P r e n o t a z i o n e e l i m i n a t a . \ n" ;
else
c out << " P r e n o t a z i o n e non e l i m i n a t a . \ n" ;
}
void G e t P o s t i D i s p o n i b i l i ( L i s t a P r e n o t a z i o n i& l ) {
c out << " I p o s t i d i s p o n i b i l i sono : " ;
c out << l . G e t P o s t i D i s p o n i b i l i ( ) << e n d l ;
}
void E s i s t e P r e n o t a z i o n e ( L i s t a P r e n o t a z i o n i& l ) {
M a t r i c o l a m;
if ( l . E s i s t e P r e n o t a z i o n e (m) )
c out << " P r e n o t a z i o n e e s i s t e n t e . \ n" ;
else
c out << " P r e n o t a z i o n e non e s i s t e n t e . \ n" ;
}
SX. Soluzioni degli altri esercizi 128
SX.7 Classica
Traccia a pag. 42
class C l a s s i f i c a {
private :
PRec f i r s t ;
unsigned int nelem ;
C l a s s i f i c a ( const C l a s s i f i c a &); // i n i b i s c e l a c o p i a mediante c o s t r u t t o r e
void operator= ( const C l a s s i f i c a &); // i n i b i s c e l ' a s s e g n a z i o n e
unsigned int E limina ( const Nome& n ) ;
void I n s e r i m e n t o O r d i n a t o ( const Nome& n , unsigned int p u n t i ) ;
public :
Classifica ();
~Classifica ();
C l a s s i f i c a : : C l a s s i f i c a ( ) : f i r s t ( 0 ) , nelem ( 0 ) {
SX. Soluzioni degli altri esercizi 129
p = p−>s u c c ;
}
// Elemento non t r o v a t o
return 0;
}
// In o g n i caso a l l o c o un nuovo r e c o r d
PRec nuovo = new Record ;
s t r c p y ( nuovo−>e l . n , n ) ;
nuovo−>e l . p u n t e g g i o = p u n t i ;
nelem++;
if ( ! f i r s t ) { // Se l a l i s t a è vuota
f i r s t = nuovo ; // I n s e r i s c o a l l a t e s t a
nuovo−>s u c c = 0 ;
} else {
// Se i l p u n t e g g i o d e l l a nuova squadra è maggiore d e l l a t e s t a
if ( p u n t i >= f i r s t −>e l . p u n t e g g i o ) {
nuovo−>s u c c = f i r s t ; // I n s e r i s c o i n t e s t a
SX. Soluzioni degli altri esercizi 130
f i r s t = nuovo ;
} else { //Devo c e r c a r e i l punto d i i n s e r z i o n e
PRec p = f i r s t ;
while ( p && p−>s u c c ) {
//Devo i n s e r i r e dopo l ' elemento p u n t a t o da p?
if ( p u n t i >= p−>suc c −>e l . p u n t e g g i o ) {
nuovo−>s u c c = p−>s u c c ;
p−>s u c c = nuovo ;
return ;
}
p = p−>s u c c ;
}
return p u n t i + p ; // R e s t i t u i s c e i l g i u s t o p u n t e g g i o
}
void C l a s s i f i c a : : Svuota ( ) {
while ( f i r s t ) {
PRec tbd = f i r s t ;
f i r s t = f i r s t −>s u c c ;
delete tbd ;
}
nelem = 0 ;
}
void stampa_menu( ) {
c out << " 1 : I n s e r i s c i . \ n" ;
c out << " 2 : Svuota . \ n" ;
c out << " 3 : Stampa . \ n" ;
c out << " 4 : Count . \ n" ;
c out << " 5 : E s c i . \ n" ;
}
int main ( )
{
Classifica l ;
int s c e l t a ;
do {
stampa_menu ( ) ;
c i n >> s c e l t a ;
switch ( scelta ) {
case 1:
A ggiungi ( l ) ;
break ;
case 2:
Svuota ( l ) ;
break ;
case 3:
Stampa ( l ) ;
break ;
case 4:
Count ( l ) ;
break ;
case 5:
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
break ;
}
} while ( s c e l t a != 5 ) ;
return 0 ;
}
struct p e r s o n a ;
typedef struct Persona {
Nome n ;
bool maschio ;
Persona ∗ c o n i u g e ;
};
struct Record ;
typedef Record ∗ PRec ;
struct Record { // S i n g o l o elemento ( c e l l a ) d e l l a s t r u t t u r a
TElem e l ;
PRec s u c c ;
};
return p;
p = p−>s u c c ;
}
return 0;
}
// I n s e r i m e n t o i n t e s t a
PRec p = new Record ;
s t r c p y ( p−>e l . n , n ) ;
p−>e l . maschio = maschio ;
p−>e l . c o n i u g e = 0 ;
p−>s u c c = f i r s t ;
first = p;
return true ;
}
PRec p2 = Cerca ( n2 ) ;
// s e i l secondo nome non è s t a t o t r o v a t o r e s t i t u i s c e f a l s e
if ( ! p2 )
return false;
// s e i l s e s s o è u g u a l e r e s t i t u i s c e f a l s e
if ( p1−>e l . maschio == p2−>e l . maschio )
return false ;
p1−>e l . c o n i u g e = &p2−>e l ;
p2−>e l . c o n i u g e = &p1−>e l ;
return true ;
}
if ( ! p)
return false ;
c o n i u g a t o = ( p−>e l . c o n i u g e != 0 ) ;
return true ;
}
while ( p ) {
if ( p−>e l . c o n i u g e != 0)
c ount++;
p = p−>s u c c ;
}
return c ount ;
}
if ( p−>e l . c o n i u g e )
c out << " c o n i u g e : " << p−>e l . c oniuge −>n << " . " ;
c out << e n d l ;
p = p−>s u c c ;
}
}
void stampa_menu( ) {
c out << " 1 : A ggiungiPe r sona . \ n" ;
c out << " 2 : Sposa . \ n" ;
c out << " 3 : Coniugato . \ n" ;
c out << " 4 : NumeroSposi . \ n" ;
c out << " 5 : NumeroCoppie . \ n" ;
c out << " 6 : Svuota . \ n" ;
c out << " 7 : Stampa . \ n" ;
c out << " 8 : E s c i . \ n" ;
}
int main ( )
{
A ge nz iaMat r imoniale am;
int s c e l t a ;
do {
stampa_menu ( ) ;
c i n >> s c e l t a ;
switch ( scelta ) {
case 1:
A ggiungiP e r s ona (am ) ;
break ;
case 2:
Sposa (am ) ;
break ;
case 3:
Coniugato (am ) ;
break ;
case 4:
NumeroSposi (am ) ;
break ;
case 5:
NumeroCoppie (am ) ;
break ;
case 6:
Svuota (am ) ;
break ;
case 7:
Stampa (am ) ;
break ;
case 8:
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
break ;
}
} while ( s c e l t a != 8 ) ;
return 0 ;
}
if (am. Sposa ( n1 , n2 ) )
c out << " Matrimonio r e g i s t r a t o . \ n" ;
else
c out << " Matrimonio non r e g i s t r a t o . \ n" ;
}
La struttura dati può essere realizzata come una lista dinamica semplicemen-
te collegata in cui ogni elemento rappresenta lo stato di tutti i pattini di una
data taglia. La generica cella della struttura contiene dunque:
first 44 1 1 43 1 1 42 2 1
Numero pattini
Taglia dei pattini disponibili
Numero pattini
complessivo
struct Record ;
typedef Record ∗ PRec ;
typedef struct Record {
Pattini pattini ;
PRec s u c c ;
};
class P a r c o P a t t i n i {
private :
PRec f i r s t ;
unsigned int t o t ;
PRec GetRecordByTaglia ( T a g l i a t ) const ;
ParcoPattini ( const P a r c o P a t t i n i &); // i n i b i s c e l a c o p i a mediatne c o s t r .
operator const
P a r c o P a t t i n i& =( P a r c o P a t t i n i &); // i n i b i s c e l ' a s s e g n a z i o n e
public :
ParcoPattini ( ) ;
~ParcoPattini ( ) ;
void AggiungiPattini ( Taglia t ) ;
void Svuota ( ) ;
unsigned int NumeroTotPattini ( ) const ;
bool Fitta ( Taglia t ) ;
SX. Soluzioni degli altri esercizi 138
P a r c o P a t t i n i : : P a r c o P a t t i n i ( ) : f i r s t ( 0 ) , t o t ( 0 ) {}
PRec p = f i r s t ;
while ( p ) {
if ( p−>p a t t i n i . t a g l i a == t ) // t r o v a t o ?
return p ; // r e s t i t u i s c e i l p u n t a t o r e alla cella della lista
else
p = p−>s u c c ; // a l t r i m e n t i avanza d i una c e l l a
}
return 0 ; // non t r o v a t o .
}
if (p) {
p−>p a t t i n i . t o t a l i ++;
p−>p a t t i n i . d i s p o n i b i l i ++;
}
else {
PRec p = new Record ;
p−>p a t t i n i . taglia = t ;
p−>p a t t i n i . t o t a li = 1;
p−>p a t t i n i . disponibili = 1;
p−>s u c c = first ;
first = p;
}
t o t ++;
}
void P a r c o P a t t i n i : : Svuota ( ) {
while ( f i r s t ) {
PRec tbd = f i r s t ;
f i r s t = f i r s t −>s u c c ;
delete tbd ;
}
tot = 0;
}
// c i sono p a t t i n i d e l l a t a g l i a s p e c i f i c a t a , e s e s ì , ce ne sono d i d i s p . ?
if ( p && ( p−>p a t t i n i . d i s p o n i b i l i > 0 ) ) {
p−>p a t t i n i . d i s p o n i b i l i −−; // decrementa l a d i s p o n i b i l i t à
return true ;
}
else
return false ;
}
if ( p )
return p−>p a t t i n i . d i s p o n i b i l i ;
else
return 0;
}
if ( p )
return p−>p a t t i n i . t o t a l i ;
else
return 0;
}
// c i sono p a t t i n i d e l l a t a g l i a s p e c i f . , e s e s ì , ce ne sono d i f i t t a t i ?
if ( p && ( p−>p a t t i n i . d i s p o n i b i l i < p−>p a t t i n i . t o t a l i ) ) {
p−>p a t t i n i . d i s p o n i b i l i ++;
return true ;
}
else
return false ;
}
while (p) {
c out << " T a g l i a " << p−>p a t t i n i . t a g l i a << " : " ;
c out << " T o t a l e : " << p−>p a t t i n i . t o t a l i << " " ;
c out << " F i t t a t i : " << p−>p a t t i n i . t o t a l i − p−>p a t t i n i . d i s p o n i b i l i
<< " . \ n" ;
p = p−>s u c c ;
}
}
void A g g i u n g i P a t t i n i ( P a r c o P a t t i n i& p ) ;
void Svuota ( P a r c o P a t t i n i& p ) ;
void NumeroTotPattini ( P a r c o P a t t i n i& p ) ;
void F i t t a ( P a r c o P a t t i n i& p ) ;
void D i s p o n i b i l i t a ( P a r c o P a t t i n i& p ) ;
void NumeroPattini ( P a r c o P a t t i n i& p ) ;
void R e s t i t u z i o n e ( P a r c o P a t t i n i& p ) ;
void Stampa ( P a r c o P a t t i n i& p ) ;
SX. Soluzioni degli altri esercizi 140
void stampa_menu( ) {
c out << " \n" ;
c out << " 1 : A g g i u n g i P a t t i n i . \ n" ;
c out << " 2 : Svuota . \ n" ;
c out << " 3 : NumeroTotPattini . \ n" ;
c out << " 4 : F i t t a . \ n" ;
c out << " 5 : D i s p o n i b i l i t a . \ n" ;
c out << " 6 : NumeroPattini . \ n" ;
c out << " 7 : R e s t i t u z i o n e . \ n" ;
c out << " 8 : Stampa . \ n" ;
c out << " 9 : E s c i . \ n" ;
c out << " S c e l t a : " ;
}
int main ( )
{
P a r c o P a t t i n i par c o ;
int s c e l t a ;
do {
stampa_menu ( ) ;
c i n >> s c e l t a ;
switch ( scelta ) {
case 1:
A g g i u n g i P a t t i n i ( par c o ) ;
break ;
case 2:
Svuota ( par c o ) ;
break ;
case 3:
NumeroTotPattini ( par c o ) ;
break ;
case 4:
F i t t a ( par c o ) ;
break ;
case 5:
D i s p o n i b i l i t a ( par c o ) ;
break ;
case 6:
NumeroPattini ( par c o ) ;
break ;
case 7:
R e s t i t u z i o n e ( par c o ) ;
break ;
case 8:
Stampa ( par c o ) ;
break ;
case 9:
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
break ;
}
} while ( s c e l t a != 9 ) ;
return 0 ;
}
void A g g i u n g i P a t t i n i ( P a r c o P a t t i n i& p ) {
Taglia t ;
SX. Soluzioni degli altri esercizi 141
void F i t t a ( P a r c o P a t t i n i& p ) {
Taglia t ;
void D i s p o n i b i l i t a ( P a r c o P a t t i n i& p ) {
Taglia t ;
void R e s t i t u z i o n e ( P a r c o P a t t i n i& p ) {
Taglia t ;
SX.10 Timer
Traccia a pag. 46
Timer : : Timer ( ) {
reset ();
}
void Timer : : s t a r t ( ) {
s t ar t T ime = time ( 0 ) ;
stopTime = 0 ;
}
void Timer : : s t o p ( ) {
stopTime = time ( 0 ) ;
}
void Timer : : r e s e t ( ) {
s t ar t T ime = 0 ;
stopTime = 0 ;
}
int main ( )
{
Timer t ;
char ch ;
do {
c i n >> ch ;
switch ( ch ) {
case 's ':
t . start ();
c out << " Timer s t a r t e d . \ n" ;
break ;
case 'x ' :
t . stop ( ) ;
c out << " Timer st oppe d . \ n" ;
break ;
case 'r ':
t . reset ();
c out << " Timer r e s e t . \ n" ;
break ;
case 'p ' :
c out << " Timer shows : " << t . getTime ( ) << e n d l ;
break ;
case 'e ' :
break ;
default :
c out << " I n v a l i d command . \ n" ;
}
} while ( ch != ' e ' ) ;
return 0 ;
}
È dunque possibile pensare al timer come una classe dotata di due membri
privati:
Timer : : Timer ( ) {
reset ();
}
void Timer : : s t a r t ( ) {
if ( ! is R unning ( ) )
s t ar t T ime = time ( 0 ) ;
}
void Timer : : s t o p ( ) {
if ( is R unning ( ) ) {
s t or e dT ime += time ( 0 ) − st ar t T ime ; // accumula i l tempo d e l cont . i n c o r s o
s t ar t T ime = 0 ; // ferma i l c o n t e g g i o
}
}
void Timer : : r e s e t ( ) {
s t or e dT ime = 0 ;
s t ar t T ime = 0 ;
}
if ( is R unning ( ) )
t += time ( 0 ) − s t ar t T ime ; // a g g i u n g e i l c o n t r i b u t o d e l cont . i n c o r s o
return t;
}
int main ( )
{
Timer t ;
char ch ;
do {
c i n >> ch ;
switch ( ch ) {
case 's ':
t . start ();
c out << " Timer s t a r t e d . \ n" ;
break ;
case 'x ' :
t . stop ( ) ;
c out << " Timer st oppe d . \ n" ;
break ;
case 'r ':
t . reset ();
c out << " Timer r e s e t . \ n" ;
break ;
case 'p ' :
c out << " Timer shows : " << t . getTime ( ) << e n d l ;
break ;
case 'e ' :
break ;
default :
c out << " I n v a l i d command . \ n" ;
}
} while ( ch != ' e ' ) ;
return 0 ;
}
SX.12 Votazioni
Traccia a pag. 48
struct Oggetto {
C odic e i d ;
unsigned int voti ;
};
struct C e l l a ;
typedef C e l l a ∗ P C e lla ;
struct C e l l a {
Oggetto elem ;
P C e lla s u c c ;
};
class V o t a z i o n i {
private :
P C e lla f i r s t ;
unsigned int numVoti ;
P C e lla C e r c a P a r t i t o ( C odic e id ) const ;
public :
Votazioni ( ) ;
~Votazioni ( ) ;
V o t a z i o n i : : V o t a z i o n i ( ) : f i r s t ( 0 ) , numVoti ( 0 ) {
}
while ( ( p ) && ! t r o v a t o ) {
if ( p−>elem . i d == i d )
t r o v a t o = true ;
else
p = p−>s u c c ;
}
if (p) {
p−>elem . v o t i ++;
return p−>elem . v o t i ;
SX. Soluzioni degli altri esercizi 147
} else {
P C e lla p = new Cella ;
p−>elem . i d = i d ;
p−>elem . v o t i = 1 ;
p−>s u c c = f i r s t ;
first = p;
return 1;
}
}
void V o t a z i o n i : : Svuota ( ) {
while ( f i r s t ) {
P C e lla tbd = f i r s t ;
f i r s t = f i r s t −>s u c c ;
delete tbd ;
}
numVoti = 0 ;
}
if ( p )
return p−>elem . v o t i ;
else
return 0;
}
while (p) {
c out << " P a r t i t o " << p−>elem . i d << " : v o t i " << " " << p−>elem . v o t i ;
c out << " ( " << ( float
) p−>elem . v o t i /numVoti ∗ 100 << "%)" << e n d l ;
p = p−>s u c c ;
}
}
void stampa_menu( ) {
c out << " 1 : A ggiungi v ot o . \ n" ;
c out << " 2 : Svuota . \ n" ;
c out << " 3 : V ot i p a r t i t o . \ n" ;
c out << " 4 : Numero v o t i . \ n" ;
c out << " 5 : S i t u a z i o n e . \ n" ;
c out << " 6 : E s c i . \ n" ;
}
int main ( )
{
Votazioni v ;
SX. Soluzioni degli altri esercizi 148
int s c e l t a ;
do {
stampa_menu ( ) ;
c i n >> s c e l t a ;
switch ( scelta ) {
case 1:
AggiungiVoto ( v ) ;
break ;
case 2:
Svuota ( v ) ;
break ;
case 3:
GetVotiPartito ( v ) ;
break ;
case 4:
GetNumeroVoti ( v ) ;
break ;
case 5:
GetSituazione (v ) ;
break ;
case 6:
break ;
default :
c out << " S c e l t a non v a l i d a . \ n" ;
break ;
}
} while ( s c e l t a != 6 ) ;
return 0 ;
}
void G e t V o t i P a r t i t o ( V o t a z i o n i& v ) {
C odic e i d ;
c out << " I n d i c a r e i l p a r t i t o : " ;
c i n >> i d ;
c out << " I l p a r t i t o " << i d << " ha o t t e n u t o v o t i " <<
v . G e t V o t i P a r t i t o ( i d ) << " . \ n" ;
}
void G e t S i t u a z i o n e ( V o t a z i o n i& v ) {
v . GetSituazione ( ) ;
}
Appendice A
GNU Free Documentation License
Version 1.2, November 2002
c 2000,2001,2002 Free Software Foundation, Inc.
Copyright
Everyone is permitted to copy and distribute verbatim copies of this license document,
but changing it is not allowed.
Preamble
The purpose of this License is to make a manual, textbook, or other functional and
useful document free in the sense of freedom: to assure everyone the eective freedom to
copy and redistribute it, with or without modifying it, either commercially or noncommer-
cially. Secondarily, this License preserves for the author and publisher a way to get credit
for their work, while not being considered responsible for modications made by others.
This License is a kind of copyleft, which means that derivative works of the document
must themselves be free in the same sense. It complements the GNU General Public
License, which is a copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software, because
free software needs free documentation: a free program should come with manuals provi-
ding the same freedoms that the software does. But this License is not limited to software
manuals; it can be used for any textual work, regardless of subject matter or whether it
is published as a printed book. We recommend this License principally for works whose
purpose is instruction or reference.
149
A. GNU Free Documentation License 150
accept the license if you copy, modify or distribute the work in a way requiring permission
under copyright law.
A Modied Version of the Document means any work containing the Document
or a portion of it, either copied verbatim, or with modications and/or translated into
another language.
A Secondary Section is a named appendix or a front-matter section of the Document
that deals exclusively with the relationship of the publishers or authors of the Document
to the Document's overall subject (or to related matters) and contains nothing that could
fall directly within that overall subject. (Thus, if the Document is in part a textbook of
mathematics, a Secondary Section may not explain any mathematics.) The relationship
could be a matter of historical connection with the subject or with related matters, or of
legal, commercial, philosophical, ethical or political position regarding them.
The Invariant Sections are certain Secondary Sections whose titles are designated,
as being those of Invariant Sections, in the notice that says that the Document is released
under this License. If a section does not t the above denition of Secondary then it is not
allowed to be designated as Invariant. The Document may contain zero Invariant Sections.
If the Document does not identify any Invariant Sections then there are none.
The Cover Texts are certain short passages of text that are listed, as Front-Cover
Texts or Back-Cover Texts, in the notice that says that the Document is released under
this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may
be at most 25 words.
A Transparent copy of the Document means a machine-readable copy, represented
in a format whose specication is available to the general public, that is suitable for re-
vising the document straightforwardly with generic text editors or (for images composed
of pixels) generic paint programs or (for drawings) some widely available drawing editor,
and that is suitable for input to text formatters or for automatic translation to a variety
of formats suitable for input to text formatters. A copy made in an otherwise Transpa-
rent le format whose markup, or absence of markup, has been arranged to thwart or
discourage subsequent modication by readers is not Transparent. An image format is not
Transparent if used for any substantial amount of text. A copy that is not Transparent is
called Opaque.
Examples of suitable formats for Transparent copies include plain ASCII without mar-
kup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available
DTD, and standard-conforming simple HTML, PostScript or PDF designed for human
modication. Examples of transparent image formats include PNG, XCF and JPG. Opa-
que formats include proprietary formats that can be read and edited only by proprietary
word processors, SGML or XML for which the DTD and/or processing tools are not gene-
rally available, and the machine-generated HTML, PostScript or PDF produced by some
word processors for output purposes only.
The Title Page means, for a printed book, the title page itself, plus such following
pages as are needed to hold, legibly, the material this License requires to appear in the title
page. For works in formats which do not have any title page as such, Title Page means
the text near the most prominent appearance of the work's title, preceding the beginning
of the body of the text.
A section Entitled XYZ means a named subunit of the Document whose title either
is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in
another language. (Here XYZ stands for a specic section name mentioned below, such as
Acknowledgements, Dedications, Endorsements, or History.) To Preserve the
A. GNU Free Documentation License 151
Title of such a section when you modify the Document means that it remains a section
Entitled XYZ according to this denition.
The Document may include Warranty Disclaimers next to the notice which states that
this License applies to the Document. These Warranty Disclaimers are considered to be
included by reference in this License, but only as regards disclaiming warranties: any other
implication that these Warranty Disclaimers may have is void and has no eect on the
meaning of this License.
A.4 Modications
You may copy and distribute a Modied Version of the Document under the conditions
of sections 2 and 3 above, provided that you release the Modied Version under precisely
this License, with the Modied Version lling the role of the Document, thus licensing
distribution and modication of the Modied Version to whoever possesses a copy of it.
In addition, you must do these things in the Modied Version:
A. Use in the Title Page (and on the covers, if any) a title distinct from that of the
Document, and from those of previous versions (which should, if there were any,
be listed in the History section of the Document). You may use the same title as a
previous version if the original publisher of that version gives permission.
B. List on the Title Page, as authors, one or more persons or entities responsible for
authorship of the modications in the Modied Version, together with at least ve
of the principal authors of the Document (all of its principal authors, if it has fewer
than ve), unless they release you from this requirement.
C. State on the Title page the name of the publisher of the Modied Version, as the
publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modications adjacent to the other
copyright notices.
F. Include, immediately after the copyright notices, a license notice giving the public
permission to use the Modied Version under the terms of this License, in the form
shown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections and required Cover
Texts given in the Document's license notice.
H. Include an unaltered copy of this License.
I. Preserve the section Entitled History, Preserve its Title, and add to it an item
stating at least the title, year, new authors, and publisher of the Modied Version
as given on the Title Page. If there is no section Entitled History in the Document,
create one stating the title, year, authors, and publisher of the Document as given
on its Title Page, then add an item describing the Modied Version as stated in
the previous sentence.
J. Preserve the network location, if any, given in the Document for public access to
a Transparent copy of the Document, and likewise the network locations given in
the Document for previous versions it was based on. These may be placed in the
History section. You may omit a network location for a work that was published
at least four years before the Document itself, or if the original publisher of the
version it refers to gives permission.
K. For any section Entitled Acknowledgements or Dedications, Preserve the Title of
the section, and preserve in the section all the substance and tone of each of the
contributor acknowledgements and/or dedications given therein.
L. Preserve all the Invariant Sections of the Document, unaltered in their text and in
their titles. Section numbers or the equivalent are not considered part of the section
titles.
A. GNU Free Documentation License 153
M. Delete any section Entitled Endorsements. Such a section may not be included in
the Modied Version.
N. Do not retitle any existing section to be Entitled Endorsements or to conict in
title with any Invariant Section.
O. Preserve any Warranty Disclaimers.
If the Modied Version includes new front-matter sections or appendices that qualify
as Secondary Sections and contain no material copied from the Document, you may at
your option designate some or all of these sections as invariant. To do this, add their titles
to the list of Invariant Sections in the Modied Version's license notice. These titles must
be distinct from any other section titles.
You may add a section Entitled Endorsements, provided it contains nothing but en-
dorsements of your Modied Version by various partiesfor example, statements of peer
review or that the text has been approved by an organization as the authoritative denition
of a standard.
You may add a passage of up to ve words as a Front-Cover Text, and a passage of
up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modied
Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added
by (or through arrangements made by) any one entity. If the Document already includes
a cover text for the same cover, previously added by you or by arrangement made by the
same entity you are acting on behalf of, you may not add another; but you may replace
the old one, on explicit permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License give permission
to use their names for publicity for or to assert or imply endorsement of any Modied
Version.
A.8 Translation
Translation is considered a kind of modication, so you may distribute translations of the
Document under the terms of section 4. Replacing Invariant Sections with translations
requires special permission from their copyright holders, but you may include translations
of some or all Invariant Sections in addition to the original versions of these Invariant
Sections. You may include a translation of this License, and all the license notices in
the Document, and any Warranty Disclaimers, provided that you also include the original
English version of this License and the original versions of those notices and disclaimers.
In case of a disagreement between the translation and the original version of this License
or a notice or disclaimer, the original version will prevail.
If a section in the Document is Entitled Acknowledgements, Dedications, or History,
the requirement (section 4) to Preserve its Title (section 1) will typically require changing
the actual title.
A.9 Termination
You may not copy, modify, sublicense, or distribute the Document except as expressly pro-
vided for under this License. Any other attempt to copy, modify, sublicense or distribute
the Document is void, and will automatically terminate your rights under this License.
A. GNU Free Documentation License 155
However, parties who have received copies, or rights, from you under this License will not
have their licenses terminated so long as such parties remain in full compliance.
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the
with...Texts. line with this:
with the Invariant Sections being LIST THEIR TITLES, with the Front-
Cover Texts being LIST, and with the Back-Cover Texts being LIST.
If you have Invariant Sections without Cover Texts, or some other combination of the
three, merge those two alternatives to suit the situation.
If your document contains nontrivial examples of program code, we recommend relea-
sing these examples in parallel under your choice of free software license, such as the GNU
General Public License, to permit their use in free software.
Bibliograa
[1] Bjarne Stroustrup. The C++ Programming Language. Addison-Wesley, special
edition, 2000.
[2] Bruce Eckel. Thinking in C++, Volume 1: Introduction to Standard C++. Prentice
Hall, 2nd edition, 2000. Liberamente scaricabile da http://www.bruceeckel.com.
Disponibile anche in versione italiana edita da Apogeo.
[3] Carlo Savy. Da C++ ad UML: guida alla progettazione. Mc Graw Hill, 2000.
[4] SGI. C++ Standard Template Library (STL). http://www.sgi.com/tech/stl.
[5] Scott Meyers. Eective C++: 55 Specic Ways to Improve Your Programs and
Designs. Addison-Wesley, 3rd edition, 2005.
[6] GCC. GNU/GCC, the GNU compiler collection. http://gcc.gnu.org.
[7] ISO/IEC. International Standard for C++. International Organization for
Standardization (ISO), 2st edition, 2003. http://www.ansi.org.
[8] Bloodshed Software. Dev-C++. http://www.bloodshed.net/devcpp.html.
[9] E. Gamma, R. Helm, R. Johnson, and J. Vlissides. Design Patterns: Elements of
Reusable Object-Oriented Software. Addison-Wesley, 1995.
[10] Scott Meyers. More Eective C++: 35 New Ways to Improve Your Programs and
Designs. Addison-Wesley, 1995.
[11] Andrei Alexandrescu. Modern C++ Design: Generic Programming and Design
Patterns Applied. Addison-Wesley, 2001.
156