Sei sulla pagina 1di 157

50 Esercizi di C++

V0.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 Documentation 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

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

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

. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .

14

EL.11

Elimina Pari e Dispari . . . . . . . . . . . . . . . . . . . . .

16

EL.12

Lista Doppiamente Collegata . . . . . . . . . . . . . . . . .

16

EL.13

Ribalta

18

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

EA Esercizi su alberi binari


EA.1

19

Albero Binario . . . . . . . . . . . . . . . . . . . . . . . . .

EA.2

Numero Elementi

EA.3

Occorrenze

19

. . . . . . . . . . . . . . . . . . . . . . .

20

. . . . . . . . . . . . . . . . . . . . . . . . . . .

20

EA.4

Occorrenza Massima . . . . . . . . . . . . . . . . . . . . . .

21

EA.5

Profondit Limitata

. . . . . . . . . . . . . . . . . . . . . .

21

EA.6

Somma

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22

EA.7

Sostituisci . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22

EA.8

Conta Min e Max

22

EA.9

Profondit Maggiore di Due . . . . . . . . . . . . . . . . . .

23

EA.10

Profondita Maggiore Di

23

. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .

INDICE

EA.11

Profondit Massima

. . . . . . . . . . . . . . . . . . . . . .

23

EA.12

Somma Livello . . . . . . . . . . . . . . . . . . . . . . . . .

24

EA.13

Eliminazione Foglia

. . . . . . . . . . . . . . . . . . . . . .

24

EA.14

Eliminazione Foglie

. . . . . . . . . . . . . . . . . . . . . .

24

EA.15

Cerca Foglia

. . . . . . . . . . . . . . . . . . . . . . . . . .

25

EA.16

Operatore di Confronto

. . . . . . . . . . . . . . . . . . . .

25

EA.17

Conta Nodi non Foglia . . . . . . . . . . . . . . . . . . . . .

26

EA.18

Conta Nodi . . . . . . . . . . . . . . . . . . . . . . . . . . .

26

EA.19

Conta Nodi Sottoalbero . . . . . . . . . . . . . . . . . . . .

26

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

SL.4

Min e Max

SL.5

Lista Statica

. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .

58
59

SL.6

Ordinata . . . . . . . . . . . . . . . . . . . . . . . . . . .

61

SL.7

Elimina Tutti . . . . . . . . . . . . . . . . . . . . . . . . . .

61

SL.8

Elimina Ultimi . . . . . . . . . . . . . . . . . . . . . . . . .

62

SL.9

Somma Coda . . . . . . . . . . . . . . . . . . . . . . . . . .

63

SL.10

Sposta Testa in Coda

. . . . . . . . . . . . . . . . . . . . .

64

SL.11

Elimina Pari e Dispari . . . . . . . . . . . . . . . . . . . . .

65

SL.12

Lista Doppiamente Collegata . . . . . . . . . . . . . . . . .

66

SL.13

Ribalta

69

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

SA Soluzioni degli esercizi su alberi binari

73

SA.1

Albero Binario . . . . . . . . . . . . . . . . . . . . . . . . .

73

SA.2

Numero Elementi

. . . . . . . . . . . . . . . . . . . . . . .

79

SA.3

Occorrenze

. . . . . . . . . . . . . . . . . . . . . . . . . . .

79

SA.4

Occorrenza Massima . . . . . . . . . . . . . . . . . . . . . .

80

SA.5

Profondit Limitata

. . . . . . . . . . . . . . . . . . . . . .

81

SA.6

Somma

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

82

SA.7

Sostituisci . . . . . . . . . . . . . . . . . . . . . . . . . . . .

83

SA.8

Conta Min e Max

. . . . . . . . . . . . . . . . . . . . . . .

83

SA.9

Profondit Maggiore di Due . . . . . . . . . . . . . . . . . .

84

SA.10

Profondita Maggiore Di

. . . . . . . . . . . . . . . . . . . .

84

SA.11

Profondit Massima

. . . . . . . . . . . . . . . . . . . . . .

85

SA.12

Somma Livello . . . . . . . . . . . . . . . . . . . . . . . . .

85

SA.13

Eliminazione Foglia

. . . . . . . . . . . . . . . . . . . . . .

86

SA.14

Eliminazione Foglie

. . . . . . . . . . . . . . . . . . . . . .

86

SA.15

Cerca Foglia

. . . . . . . . . . . . . . . . . . . . . . . . . .

87

SA.16

Operatore di Confronto

. . . . . . . . . . . . . . . . . . . .

88

SA.17

Conta Nodi non Foglia . . . . . . . . . . . . . . . . . . . . .

89

SA.18

Conta Nodi . . . . . . . . . . . . . . . . . . . . . . . . . . .

89

SA.19

Conta Nodi Sottoalbero . . . . . . . . . . . . . . . . . . . .

90

SP Soluzioni degli esercizi su pile

93

SP.1

Push Greater . . . . . . . . . . . . . . . . . . . . . . . . . .

93

SP.2

Push If

96

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

SC Soluzioni degli esercizi su code


SC.1

Coda

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

99
99

SC.2

Coda con Perdite . . . . . . . . . . . . . . . . . . . . . . . . 103

SC.3

Coda a Priorit . . . . . . . . . . . . . . . . . . . . . . . . . 107

SC.4

PopMinMax

. . . . . . . . . . . . . . . . . . . . . . . . . . 112

INDICE

SX Soluzioni degli altri esercizi

113

SX.1

Accumulatore . . . . . . . . . . . . . . . . . . . . . . . . . . 113

SX.2

Cifratore

. . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

SX.3

Lista Della Spesa . . . . . . . . . . . . . . . . . . . . . . . . 115

SX.4

Predittore di Temperatura

. . . . . . . . . . . . . . . . . . 119

SX.5

Contenitore . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

SX.6

Lista Prenotazioni . . . . . . . . . . . . . . . . . . . . . . . 124

SX.7

Classica

. . . . . . . . . . . . . . . . . . . . . . . . . . . . 128

SX.8

Agenzia Matrimoniale . . . . . . . . . . . . . . . . . . . . . 132

SX.9

Parco Pattini . . . . . . . . . . . . . . . . . . . . . . . . . . 136

SX.10

Timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

SX.11

Timer Avanzato

SX.12

Votazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

. . . . . . . . . . . . . . . . . . . . . . . . 143

GNU Free Documentation License


A.1

Applicability and Denitions

149

. . . . . . . . . . . . . . . . . 149

A.2

Verbatim Copying

A.3

Copying in Quantity . . . . . . . . . . . . . . . . . . . . . . 151

. . . . . . . . . . . . . . . . . . . . . . . 151

A.4

Modications . . . . . . . . . . . . . . . . . . . . . . . . . . 152

A.5

Combining Documents . . . . . . . . . . . . . . . . . . . . . 153

A.6

Collection of Documents . . . . . . . . . . . . . . . . . . . . 154

A.7

Aggregation with Independent Works

A.8

Translation . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

A.9

Termination

A.10

Future revisions of this license

. . . . . . . . . . . . 154

. . . . . . . . . . . . . . . . . . . . . . . . . . 154
. . . . . . . . . . . . . . . . 155

Prefazione
Gli esercizi presentati in questo eserciziario sono stati proposti a studenti di
Ingegneria delle Telecomunicazioni nell'ambito di un corso di Programmazio-

ne I.
Il corso aveva lo scopo di introdurre alla programmazione orientata agli
oggetti utilizzando il linguaggio C++. Una rilevante parte del programma
arontava lo studio dei tipi di dati astratti, con particolare enfasi alle strutture dati di tipo contenitore, stressandone i concetti di incapsulamento ed
interfaccia. Gli esercizi dedicati all'approfondimento di questi concetti sono
stati raccolti in questo eserciziario, insieme con le relative soluzioni.

A chi rivolto questo testo


Gli studenti che approcciano allo studio del linguaggio C++, in occasione
di corsi di studi superiori, troveranno utile studiare e risolvere gli esercizi
contenuti in questo testo. Se da un lato questi favoriscono l'acquisizione delle
ricorrenti tecniche legate alla realizzazione ed all'uso di contenitori, dall'altro
rappresentano un pretesto per mettere in pratica approcci algoritmici alla
risoluzione di problemi pi generici.
Non essendo questo un libro di teoria, lo studio di uno dei numerosi testi
dedicati alle nozioni della programmazione, alle regole ed alla sintassi del
linguaggio C++, risulta propedeutico. Il testo certamente pi rappresentativo scritto dall'inventore del linguaggio, Bjarne Stroustrup [1]. Esistono
comunque numerosi altri testi orientati all'apprendimento del linguaggio, tra
cui [2, 3].

La struttura degli esercizi


Questo eserciziario contiene dierenti tipologie di esercizi: alcuni richiedono
la realizzazione di una struttura dati di tipo contenitore, mediante uso del
costrutto

class

del linguaggio, fornendo allo studente la specica in forma

Prefazione

di interfaccia dei classici metodi di cui tali strutture sono dotate (aggiunta di
un elemento, conteggio degli elementi, svuotamento, visita, etc.). Altri esercizi, basandosi sulle suddette implementazioni, richiedono la realizzazione di
funzionalit nalizzate ad eettuare particolari elaborazioni sugli elementi
contenuti (per esempio inserimenti o eliminazioni condizionate, somme, spostamenti, 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 informazioni:

il nome del metodo;

l'insieme dei parametri di ingresso;

l'insieme dei parametri di uscita;

la descrizione della funzionalit che il metodo deve realizzare.

Per esempio, la specica di un ipotetico metodo di eliminazione di elementi da una lista, potrebbe apparire come segue.

Nome

Param. Ingr.

Elimina()

TElem

Param. Usc.

unsigned int

Elimina dalla struttura tutte le occorrenze dell'elemento specicato dal


parametro di ingresso. Restituisce il numero delle eliminazioni eettuate.
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 contenitore, spesso gli algoritmi da realizzare sono sucientemente indipendenti
dal tipo degli elementi contenuti, e fanno riferimento solo ad alcune loro propriet (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
nizione del tipo

TElem

TElem, essendo la de-

centralizzata e localizzata in testa all'header le del-

la classe contenitore. Questa procedura anticipa l'uso della programmazione

Prefazione

generica, che in C++ pu essere praticata mediante il meccanismo dei templates. 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 estensione

.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 consistente 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 anche 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 realizzate, 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 responsabilit 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

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 scorretto  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 costrutto che nisca per invocare uno di questi due metodi produrr un errore di

Prefazione

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 della suite di compilazione GNU/GCC [6], utilizzando le seguenti opzioni di
compilazione:

-Wall ansi pedantic


L'opzione

-Wall

richiede al compilatore di non inibire la maggior parte

dei messaggi di warning che, pur non compromettendo la corretta compilazione del programma, sono sintomi di imprecisioni all'interno del codice. Le
altre due opzioni inducono il compilatore ad accettare esclusivamente codice
strettamente aderente allo standard ISO-C++ [7], riutando la compilazione
di eventuali estensioni non standard del linguaggio.
Il codice sorgente delle soluzioni stato scritto utilizzando l'ambiente
di sviluppo Dev-C++ [8], nella sua versione 4.9.9.0, utilizzabile su sistemi
TM
Windows. Tale software consiste di un

operativi della famiglia Microsoft

editor graco che funge da interfaccia per le operazioni di stesura, compilazione e debugging del codice sorgente, oltre a fornire ed installare anche la suite
di compilazione GNU/GCC. In ogni caso, purch si disponga di un compilatore conforme allo standard ISO-C++, qualsiasi altro ambiente di sviluppo,
o anche un semplice editor di testi, possono essere considerati validi ai ni
della stesura del codice sorgente.

Uno sguardo al futuro


Quelli che alla ne di questo eserciziario penseranno: S, e allora? , probabilmente sono pronti per arontare uno studio pi approfondito della programmazione, che non si esaurisce con il possesso delle nozioni su un linguaggio. Tra un individuo che conosca un linguaggio di programmazione ed
un programmatore esperto c' un dierenza analoga a quella che esiste tra
un individuo che sappia scrivere ed uno scrittore. Un buon programmatore
non quello che sa arontare la complessit, ma quello che sa dominar-

la. Certamente la conoscenza della sintassi del linguaggio un primo passo


indispensabile, ma chi vuole approfondire questa materia non pu fare a meno di acquisire le nozioni della progettazione, le buone prassi per la stesura
del codice e gli strumenti forniti dalle librerie standard oggi disponibili.

Prefazione

solo attraverso questa strada che diviene possibile scrivere applicazioni non
banali, preservandone le caratteristiche di comprensibilit, estensibilit, manutenibilit, correttezza e, in una sola parola, di qualit. Programmare utilizzando 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 consolidati; 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.

Si pensi ad esempio al seguente semplice problema: si vuole realizzare un programma


C++ che, data una stringa di testo comunque lunga, calcoli l'occorrenza delle parole
contenute in essa. Utilizzando esclusivamente i costrutti messi a disposizione dal linguaggio
sarebbe necessario procedere secondo i seguenti passi:
1. progettazione di una struttura dati capace di contenere sequenze di caratteri comunque lunghe;
2. progettazione di una struttura ad accesso tabellare capace di contenere coppie del
tipo (stringa, intero);
3. progettazione di un algoritmo che analizzi la stringa, la scomponga nelle singole
parole componenti e popoli coerentemente la struttura tabellare.
Utilizzando invece quanto messo a disposizione dalla libreria STL [4], il programma
suddetto apparirebbe come segue:

int

main ( ) {
s t r i n g buf ;
map<s t r i n g , int > m;
while ( c i n >> buf )
m[ buf ]++;

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.
Nell'apprendere le nozioni della progettazione e le buone prassi per la
stesura del codice, ascoltare cosa hanno da dirci `i giganti' al proposito, pu
servire molto.

A questo scopo non si pu fare a meno di citare dei testi

disponibili in letteratura, universalmente considerati dei classici.

Design Patterns [9] probabilmente il pi bel testo mai scritto nell'ambito


della progettazione software, considerando anche le profonde ripercussioni
che esso ha poi avuto sul concetto di buona progettazione software orientata
agli oggetti, tanto da essere ancora oggi il libro di gran lunga pi citato
nel suo genere. In questo testo gli autori introducono il concetto di pattern

Prefazione

10

progettuale software (design pattern ); ad un livello di astrazione superiore a


quello di qualsiasi linguaggio di programmazione, presentano poi 55 soluzioni
a problemi comuni nell'ambito della progettazione, con esempi in linguaggio
C++. Imperdibile.
In programmazione un problema pu essere spesso risolto seguendo un notevole numero di dierenti strade, ognuna delle quali assoggetta il programmatore ad accettare determinati compromessi. I due libri Eective C++ [5]
e More Eective C++ [10] contengono una collezione di linee guida utili a
comprendere cosa fare  e cosa non fare  con il linguaggio C++. Una nutrita schiera di programmatori ha assimilato da questi due testi un corretto
stile di programmazione, ed ha imparato ad evitare i ricorrenti trabocchetti
in agguato durante le fasi di stesura di codice in linguaggio C++. Il successo
di questi testi tale che oggi il compilatore GNU/GCC dotato di un'opzione di compilazione che produce dei warnings in caso di violazione delle linee

guida contenute in Eective C++ .


Chi voglia realmente approfondire la propria conoscenza del C++, non
pu fare a meno di assimilare le tecniche di programmazione basate sul meccanismo dei template e della programmazione generica (generic programming).

Modern C++ Design [11] particolarmente illuminante sotto questo punto di


vista. Il libro apre le porte ad un utilizzo estremamente elegante dei template,
inimmaginato perno da chi li aveva originariamente progettati. Seguendo la
sua impostazione nella stesura del software e le sue linee guida si perviene al
progetto di architetture software limpide e snelle, ma contemporaneamente
estremamente potenti e versatili.

Dove trovare questo eserciziario


Questo eserciziario distribuito sotto licenza GNU Free Documentation License (vedi Appendice A) all'indirizzo

net.

http://esercizicpp.sourceforge.

Dal sito possibile prelevare l'ultima versione disponibile, accedere ai

forum dedicati ai lettori ed iscriversi alla mailing-list informativa.

Contattare l'autore
Commenti, suggerimenti e segnalazioni sono graditi.
contattato al seguente indirizzo e-mail:

1 L'opzione

: -Weffc++.

L'autore pu essere

mesposit@unina.it

Parte I
Esercizi

11

Capitolo EL
Esercizi su liste
EL.1 Lista Semplicemente Collegata
Soluzione a pag. 51

Si realizzi la struttura dati


uguale al tipo

int

Lista.

Il tipo

TElem

degli elementi contenuti sia

del linguaggio. La lista sia dotata dei metodi riportati di

seguito.
Nome

Param. Ingr.

Param. Usc.

Lista()

Lista

TElem

int

Costruttore senza parametri.

Lista()
Costruttore di copia.

Lista()
Distruttore.

Inserisci()
Inserimento in testa alla lista.

NumeroElementi()

Restituisce il numero degli elementi contenuti nella lista.

Svuota()

TElem

Svuota la lista.

Elimina()

Elimina un elemento dalla lista, se presente.

12

EL. Esercizi su liste

13

Stampa()

Stampa sullo standard output tutti gli elementi contenuti nella lista.

Ricerca()

TElem

bool

Predicato indicante la presenta di un elemento.


L'unico metodo della classe
(cout) il metodo

Stampa().

Lista

che pu utilizzare lo standard-output

Gli altri metodi (pubblici, privati o protetti)

non possono fare uso delle funzionalit di stampa.


Si realizzi una funzione

main() che permetta di eettuare il collaudo della

struttura dati realizzata.

EL.2 Somma Elementi


Soluzione a pag. 57

Dotare la classe

Lista (vedi EL.1) del metodo Somma() secondo la seguente

specica.
Nome

Param. Ingr.

Param. Usc.

Somma()

TElem

Restituisce la somma degli elementi presenti nella lista.

EL.3 Coda Pari


Soluzione a pag. 57

Dotare la classe

Lista

(vedi EL.1) del metodo

CodaPari(),

secondo la

seguente interfaccia.
Nome

Param. Ingr.

Param. Usc.

CodaPari()
Restituisce true

bool

se l'elemento in coda pari,

false

altrimenti.

EL.4 Min e Max


Soluzione a pag. 58

Dotare la classe
specica.

Lista (vedi EL.1) del metodo MinMax() secondo la seguente

EL. Esercizi su liste

14

Nome

Param. Ingr.

Param. Usc.

MinMax()

TElem,TElem

Restituisce gli elementi minimo e massimo all'interno della lista. In


caso di lista vuota l'uscita di questo metodo non specicata.

EL.5 Lista Statica


Soluzione a pag. 59

Si realizzi la struttura dati

Lista secondo un approccio all'allocazione della


TElem degli elementi contenuti sia uguale al

memoria di tipo statico. Il tipo


tipo

int

del linguaggio. La lista sia dotata dei metodi riportati di seguito.

Nome

Param. Ingr.

Param. Usc.

Lista()

TElem

Costruttore.

Lista()
Distruttore.

InserisciInCoda()

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.
L'unico metodo della classe Lista che pu utilizzare lo standard-output
(cout) il metodo

Stampa().

Gli altri metodi (pubblici, privati o protetti)

non possono fare uso delle funzionalit di stampa.

EL.6 Ordinata
Soluzione a pag. 61

Dotare la classe

Lista

seguente interfaccia.

(vedi EL.5) del metodo

EOrdinata(),

secondo la

EL. Esercizi su liste

15

Nome

EOrdinata()
true

Restituisce

Param. Ingr.

Param. Usc.

bool

se la lista ordinata secondo la relazione di

ordinamento crescente per gli interi,

false

altrimenti.

EL.7 Elimina Tutti


Soluzione a pag. 61

Dotare la classe

Lista (vedi EL.5) del metodo EliminaTutti(),

secondo la

seguente interfaccia.
Nome

Param. Ingr.

Param. Usc.

EliminaTutti()

TElem

int

Elimina tutte le occorrenze dell'elemento specicato presenti nella


lista. Restituisce il numero di occorrenze eliminate.

EL.8 Elimina Ultimi


Soluzione a pag. 62

Dotare la classe

Lista (vedi EL.1) dei metodi le cui interfacce sono riportate

di seguito.
Nome

Param. Ingr.

Param. Usc.

EliminaUltimi()

unsigned int

unsigned int

Elimina dalla lista gli ultimi

elementi, con

pari al valore del

parametro di ingresso. Il valore restituito pari al numero di elementi


eettivamente eliminati dalla lista.

LasciaPrimi()

unsigned int

Elimina dalla lista tutti gli elementi tranne i primi

unsigned int
n, con n pari al

valore del parametro di ingresso. Il valore restituito pari al numero


di elementi eettivamente eliminati dalla lista.

EL.9 Somma Coda


Soluzione a pag. 63

Dotare la classe

Lista

seguente interfaccia.

(vedi EL.1) del metodo

SommaCoda(),

secondo la

EL. Esercizi su liste

16

Nome

Param. Ingr.

Param. Usc.

SommaCoda()

Somma a tutti gli elementi della lista il valore dell'elemento di coda.

EL.10 Sposta Testa in Coda


Soluzione a pag. 64

Dotare la classe

Lista

(vedi EL.1) del metodo

SpostaTestaInCoda(),

se-

condo la seguente interfaccia.


Nome

Param. Ingr.

Param. Usc.

SpostaTestaInCoda()

bool

Sposta in coda alla lista l'elemento di testa.

true

se lo spostamento eettuato,

false

Il metodo restituisce

altrimenti.

EL.11 Elimina Pari e Dispari


Soluzione a pag. 65

Lista (vedi EL.1) dei metodi EliminaElPostoPari()


EliminaElPostoDispari(), secondo la seguente interfaccia.

Dotare la classe

Nome

Param. Ingr.

Param. Usc.

EliminaElPostoPari()

unsigned int

ed

Elimina dalla lista tutti gli elementi di posto pari (0, 2, 4, ...).
Restituisce il numero di elementi eliminati.

EliminaElPostoDispari()

unsigned int

Elimina dalla lista tutti gli elementi di posto dispari (1, 3, 5, ...).
Restituisce il numero di elementi eliminati.

EL.12 Lista Doppiamente Collegata


Soluzione a pag. 66

Si realizzi in linguaggio C++ il tipo di dato astratto


costrutto

class del linguaggio.

Lista mediante uso del

L'implementazione deve essere realizzata me-

diante puntatori ed allocazione dinamica della memoria secondo l'approccio

EL. Esercizi su liste

17

el

el

el
last

first

Figura EL.1: Struttura della lista doppiamente collegata

di lista doppiamente collegata. Ogni elemento, cio, punta contemporaneamente al precedente ed al successivo (vedi Figura EL.1). Gli elementi della
lista siano di tipo

TElem

uguale al tipo

int.

Di seguito riportata la specica dei metodi pubblici da implementare


per la classe

Lista.

Nome

Param. Ingr.

Param. Usc.

Lista()

TElem

Costruttore.

Lista()
Distruttore.

Inserisci()

Inserisce un elemento in coda alla lista.

Svuota()

unsigned int

Svuota la lista.

Count()

Conta gli elementi contenuti nella 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 elemento, 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 standardoutput (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.
Nome

Param. Ingr.

Param. Usc.

Ribalta()

Ribalta la posizione di tutti gli elementi della lista. Alla chiamata di


tale metodo il primo elemento diventa l'ultimo, il secondo diventa il
penultimo. . . l'ultimo diventa il primo.

Capitolo EA
Esercizi su alberi binari
EA.1 Albero Binario
Soluzione a pag. 73

Realizzare la classe
tipo

int e

AlberoBinario.

Il tipo

TElem

dei suoi elementi sia il

gli elementi risultino ordinati secondo la relazione di ordinamento

crescente per gli interi.

L'implementazione di tutti i metodi sia basata su

appositi metodi ricorsivi. L'interfaccia della classe sia la seguente.


Nome

Param. Ingr.

Param. Usc.

AlberoBinario()

AlberoBinario

TElem

Costruttore della struttura.

AlberoBinario()
Costruttore di copia.

AlberoBinario()
Distruttore della struttura.

AggiungiElem()

Metodo di aggiunta di un elemento all'albero.

InAlb()

TElem

Ricerca un elemento nell'albero.

Restituisce

l'elemento specicato sia presente nell'albero,

Elimina()

TElem

true
false

bool
nel caso in cui
altrimenti.

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.
Gli unici metodi della classe

AlberoBinario

che possono utilizzare lo

standard-output (cout) sono i metodi di visita dell'albero (InOrdine(),

PreOrdine(), PostOrdine()).

Gli altri metodi (pubblici, privati o protetti)

non possono fare uso delle funzionalit di stampa.


Si realizzi una funzione

main() che permetta di eettuare il collaudo della

struttura dati realizzata.

EA.2 Numero Elementi


Soluzione a pag. 79

Dotare la classe

AlberoBinario (vedi EA.1) del metodo NumElem() secondo

la seguente specica.
Nome

Param. Ingr.

Param. Usc.

NumElem()

unsigned int

Restituisce il numero degli elementi presenti nell'albero.

EA.3 Occorrenze
Soluzione a pag. 79

Dotare la classe

AlberoBinario

(vedi EA.1) del metodo

Occorrenze(),

secondo la seguente interfaccia.


Nome

Param. Ingr.

Param. Usc.

Occorrenze()

TElem

unsigned int

Restituisce le occorrenze dell'elemento specicato nell'albero.

EA. Esercizi su alberi binari

21

EA.4 Occorrenza Massima


Soluzione a pag. 80

Modicare la classe

AlberoBinario

(vedi EA.1) per prevedere un'occorren-

za massima degli elementi in esso inseriti. Pi precisamente, il costruttore


deve accettare come parametro di ingresso un numero intero positivo (per es.

maxocc);

l'inserimento di un nuovo elemento nell'albero deve andare a buon

ne solo se tale elemento presente con occorrenza minore di

maxocc.

Di seguito riportata la specica dei due metodi pubblici da implementare


per la classe

AlberoBinario.

Nome

Param. Ingr.

Param. Usc.

AlberoBinario()

unsigned int

Costruttore con parametro di ingresso di tipo intero non negativo. Il


parametro di ingresso rappresenta l'occorrenza massima con cui gli
elementi potranno essere presenti nell'albero.

Inserisci()

TElem

bool

Inserisce l'elemento specicato nell'albero solo se esso presente con occorrenza minore dell'occorrenza massima specicata nel
costruttore.
Il metodo restituisce

true

false

a seconda che l'inserimento sia

avvenuto o meno.

EA.5 Profondit Limitata


Soluzione a pag. 81

Modicare la classe

AlberoBinario

(vedi EA.1) per prevedere il non su-

peramento di una profondit massima specicata all'atto della costruzione


della struttura.
Di seguito riportata la specica dei due nuovi metodi pubblici da implementare per la classe

AlberoBinario:

Nome

Param. Ingr.

Param. Usc.

AlberoBinario()

unsigned int

Costruttore con parametro intero non negativo. Il parametro di ingresso indica la massima profondit che l'albero pu assumere durante
il suo ciclo di vita.

EA. Esercizi su alberi binari

22

Inserisci()

TElem

bool

Inserisce in maniera ordinata l'elemento specicato nell'albero solo se


esso non supera la massima profondit prevista per l'albero. Il metodo restituisce

true

se l'elemento stato inserito nell'albero,

false

altrimenti.

EA.6 Somma
Soluzione a pag. 82

Dotare la classe

AlberoBinario

(vedi EA.1) del metodo

Somma()

secondo

la seguente specica.
Nome

Param. Ingr.

Param. Usc.

Somma()

TElem

Somma ad ogni elemento dell'albero il valore intero specicato come


parametro di ingresso.

EA.7 Sostituisci
Soluzione a pag. 83

Dotare la classe

AlberoBinario

(vedi EA.1) del metodo

Sostituisci()

secondo la seguente specica.


Nome

Param. Ingr.

Param. Usc.

Sostituisci()
Detti i e j i parametri

TElem,TElem

unsigned int

occorrenze dell'elemento

di ingresso al metodo, sostituisce tutte le

con l'elemento

j.

Restituisce il numero di

sostituzioni eettuate.
N.B.: questo metodo in generale non preserva la propriet di ordinamento
dell'albero.

Si assuma comunque che questo metodo agisca sempre su un

albero ordinato.

EA.8 Conta Min e Max


Soluzione a pag. 83

Dotare la classe

AlberoBinario

secondo la seguente specica.

(vedi EA.1) del metodo

ContaMinMax(),

EA. Esercizi su alberi binari

23

Nome

Param. Ingr.

Param. Usc.

ContaMinMax()

TElem,TElem

unsigned int

Restituisce il numero degli elementi presenti nell'albero il cui valore


compreso tra gli interi

Min

Max

passati in ingresso al metodo,

estremi inclusi.

EA.9 Profondit Maggiore di Due


Soluzione a pag. 84

Dotare la classe

Due()

AlberoBinario

(vedi EA.1) del metodo

ProfMaggioreDi-

secondo la seguente specica.

Nome

Param. Ingr.

Param. Usc.

ProfMaggioreDiDue()

bool

Predicato che indica se la profondit dell'albero strettamente maggiore di 2. Restituisce

false

true nel caso in cui la condizione sia vericata,

altrimenti.

EA.10 Profondita Maggiore Di


Soluzione a pag. 84

Dotare la classe

AlberoBinario (vedi EA.1) del metodo ProfMaggioreDi()

secondo la seguente specica.


Nome

Param. Ingr.

Param. Usc.

ProfMaggioreDi()

unsigned int

bool

Predicato che indica se la profondit dell'albero strettamente maggiore del valore intero rappresentato dal parametro di ingresso. Restituisce

true

nel caso in cui la condizione sia vericata,

false

altrimenti.

EA.11 Profondit Massima


Soluzione a pag. 85

Dotare la classe

AlberoBinario

secondo la seguente interfaccia.

(vedi EA.1) del metodo

Profondita(),

EA. Esercizi su alberi binari

24

Nome

Param. Ingr.

Param. Usc.

Profondita()

TElem

int,bool

Restituisce la profondit dell'elemento specicato dal parametro di


ingresso.

In caso di occorrenze multiple, restituisce la profondit

massima. Restituisce inoltre un valore booleano che informa se tale


elemento o meno una foglia dell'albero. Nel caso in cui l'elemento
non fosse presente nell'albero, il metodo restituisce il valore -1.

EA.12 Somma Livello


Soluzione a pag. 85

Dotare la classe

AlberoBinario

(vedi EA.1) del metodo

SommaLivello()

secondo la seguente specica.


Nome

Param. Ingr.

Param. Usc.

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.
N.B.: questo metodo in generale non preserva la propriet di ordinamento
dell'albero.

EA.13 Eliminazione Foglia


Soluzione a pag. 86

Dotare la classe

AlberoBinario

(vedi EA.1) del metodo

EliminaFoglia()

secondo la seguente specica.


Nome

Param. Ingr.

Param. Usc.

EliminaFoglia()

TElem

bool

Elimina dall'albero l'elemento specicato se e solo se esso presente


ed una foglia. Il metodo restituisce
eettuata,

false

true

in caso di eliminazione

altrimenti.

EA.14 Eliminazione Foglie


Soluzione a pag. 86

Dotare la classe

AlberoBinario

secondo la seguente specica.

(vedi EA.1) del metodo

EliminaFoglie()

EA. Esercizi su alberi binari

25

Nome

Param. Ingr.

Param. Usc.

EliminaFoglie()

unsigned int

Elimina dall'albero tutte le foglie. Restituisce il numero di elementi


eliminati.

EA.15 Cerca Foglia


Soluzione a pag. 87

Dotare la classe

AlberoBinario (vedi EA.1) dei due metodi le cui interfacce

sono riportate di seguito.


Nome

Param. Ingr.

Param. Usc.

CercaFoglia()

TElem

bool, bool

Predicato che indica se l'elemento specicato dal parametro di ingresso presente nell'albero. Nel caso in cui sia presente, il metodo restituisce anche un ulteriore valore booleano che indica se esiste almeno
una foglia contenente il valore specicato.

CercaNodo()

TElem

bool, bool

Predicato che indica se l'elemento specicato dal parametro di ingresso presente nell'albero. Nel caso in cui sia presente, il metodo restituisce anche un ulteriore valore booleano che indica se esiste almeno
un nodo contenente il valore specicato.

EA.16 Operatore di Confronto


Soluzione a pag. 88

Dotare la classe

AlberoBinario (vedi EA.1) dell'operatore di confronto.

Ta-

le operatore viene invocato in seguito alla valutazione della seguente espressione:

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

Nome

Param. Ingr.

Param. Usc.

operator==()

AlberoBinario

bool

l'operatore di confronto tra alberi. Permette di valutare l'esatta


uguaglianza di due alberi. Fornisce

true

se esso stesso risulta essere

perfettamente uguale all'albero in ingresso (anche strutturalmente),

false

altrimenti.

EA.17 Conta Nodi non Foglia


Soluzione a pag. 89

Dotare la classe

Foglia()

AlberoBinario

(vedi EA.1) del metodo

ContaNodiNon-

secondo la seguente specica.

Nome

Param. Ingr.

Param. Usc.

ContaNodiNonFoglia()

unsigned int

Restituisce il numero di nodi non foglia presenti nell'albero.

EA.18 Conta Nodi


Soluzione a pag. 89

Dotare la classe

AlberoBinario

(vedi EA.1) del metodo

ContaNodi()

se-

condo la seguente specica.


Nome

Param. Ingr.

Param. Usc.

ContaNodi()

unsigned int,
unsigned int,
unsigned int

Restituisce il numero di nodi dell'albero aventi 0, 1 e 2 gli, rispettivamente.

EA.19 Conta Nodi Sottoalbero


Soluzione a pag. 90

Dotare la classe

AlberoBinario

specicata di seguito.

(vedi EA.1) dei metodi aventi l'interfaccia

EA. Esercizi su alberi binari

27

Nome

Param. Ingr.

Param. Usc.

ContaNodiSottoalb_Min()

TElem

unsigned int

Conta i nodi del sottoalbero avente come radice l'elemento il cui valore pari al valore del parametro di ingresso. Nel caso di occorrenze
multiple, la radice viene individuata nell'elemento posizionato al livello dell'albero minore rispetto a tutti gli altri. In caso di assenza
dell'elemento, il metodo restituisce zero. Si consideri anche la radice
del sottoalbero nel conteggio degli elementi.

ContaNodiSottoalb_Max()

TElem

unsigned int

Conta i nodi del sottoalbero avente come radice l'elemento il cui valore pari al valore del parametro di ingresso. Nel caso di occorrenze
multiple, la radice viene individuata nell'elemento posizionato al livello dell'albero maggiore rispetto a tutti gli altri. In caso di assenza
dell'elemento, il metodo restituisce zero. Si consideri anche la radice
del sottoalbero nel conteggio degli elementi.

Capitolo EP
Esercizi su pile
EP.1 Push Greater
Soluzione a pag. 93

Pila mediante uso del


class del linguaggio e ricorrendo ad un'implementazione dinamica.
TElem degli elementi della pila sia il tipo int.

Si realizzi in linguaggio C++ il tipo di dato astratto


costrutto
Il tipo

Di seguito riportata la specica dei metodi pubblici da implementare


per la classe

Pila.

Nome

Param. Ingr.

Param. Usc.

Pila()

TElem

Costruttore senza parametri.

Pila()
Distruttore.

Push()

Aggiunge sulla pila l'elemento specicato.

PushGreater()

TElem

bool

Aggiunge sulla pila l'elemento specicato esclusivamente se esso


maggiore dell'elemento di testa corrente. Nel caso in cui la pila sia
vuota l'aggiunta sempre eseguita. Restituisce

true oppure false a

seconda che l'aggiunta sia stata eseguita oppure no.

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()

unsigned int

Svuota la pila.

Count()

Restituisce il numero di elementi presenti nella pila.

Empty()

bool

Predicato vero se la pila vuota, falso altrimenti.


Si realizzi una funzione

main() che permetta di eettuare il collaudo della

struttura dati realizzata.


Nessuno dei metodi della classe pu utilizzare operazioni che coinvolgono
gli stream di input ed output (cin e

cout).

La scrittura e la lettura su stream

sono concesse esclusivamente all'interno del programma

main().

EP.2 Push If
Soluzione a pag. 96

Si modichi la classe

Pila

dell'esercizio EP.1 per renderla conforme ai

metodi specicati di seguito:


Nome

Param. Ingr.

Param. Usc.

Pila()

unsigned int

Costruttore con parametro. Il parametro di ingresso indica il numero


di inserimenti massimi consecutivi possibili (vedi anche speciche del
metodo

Push()).

Push()

TElem

bool

Aggiunge sulla pila l'elemento specicato se non stato superato il


numero massimo di inserimenti consecutivi (cio non intervallati da

Pop()
della lista con il metodo Svuota()).
alcun prelievo con il metodo

o da uno svuotamento completo


Nel caso in cui tale numero, spe-

cicato dal parametro di ingresso del costruttore, sia stato superato,


l'inserimento non avviene ed il metodo restituisce
restituisce

true.

false.

Altrimenti

EP. Esercizi su pile


Pop()

30

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

Coda mediante uso del


class del linguaggio e ricorrendo ad un'implementazione dinamica.
TElem degli elementi della coda sia il tipo int.

Si realizzi in linguaggio C++ il tipo di dato astratto


costrutto
Il tipo

Di seguito riportata la specica dei metodi pubblici da implementare


per la classe

Coda.

Nome

Param. Ingr.

Param. Usc.

Coda()

TElem

TElem

Costruttore senza parametri.

Coda()
Distruttore.

Push()
Accoda l'elemento specicato.

Top()

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()

unsigned int

Svuota la coda.

Count()

Restituisce il numero di elementi presenti nella coda.

Empty()

bool

Predicato vero se la coda vuota, falso altrimenti.


Si realizzi una funzione

main() che permetta di eettuare il collaudo della

struttura dati realizzata.


Nessuno dei metodi della classe pu utilizzare operazioni che coinvolgono
gli stream di input ed output (cin e

cout).

La scrittura e la lettura su stream

sono concesse esclusivamente all'interno del programma

main().

EC.2 Coda con Perdite


Soluzione a pag. 103

Si realizzi in linguaggio C++ il tipo di dato astratto


costrutto
tipo

int.

class

del linguaggio. Il tipo

TElem

Coda

mediante uso del

degli elementi della coda sia il

Di seguito riportata la specica dei metodi pubblici da implementare


per la classe

Coda.

Nome

Param. Ingr.

Param. Usc.

Coda()

unsigned int

Costruttore con parametro intero. Il parametro indica il numero massimo di posti in coda, oltre il quale non deve essere possibile inserire
ulteriori elementi.

Coda()

TElem

bool

Distruttore.

Push()

Accoda l'elemento specicato. Restituisce


accodato,

false

altrimenti.

true

in caso di elemento

EC. Esercizi su code

33

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.

Pop()

unsigned int

TElem

Estrae tanti elementi quanti specicati dal parametro di ingresso e


restituisce solo il primo di questi, cio l'elemento presente in testa
precedentemente alla chiamata al metodo. Rappresenta una versione

overloaded del metodo precedente.

Nel caso in cui la coda risulti

vuota all'atto della chiamata al metodo, il comportamento risultante


non specicato.

Svuota()

unsigned int

Svuota la coda.

Count()

Restituisce il numero di elementi presenti nella coda.

Empty()

bool

Predicato vero se la coda vuota, falso altrimenti.


Si realizzi una funzione

main() che permetta di eettuare il collaudo della

struttura dati realizzata.


Nessuno dei metodi della classe pu utilizzare operazioni che coinvolgono

gli stream di input ed output (cin e

cout).

La scrittura e la lettura su stream

sono concesse esclusivamente all'interno del programma

main().

EC.3 Coda a Priorit


Soluzione a pag. 107

PriorityQueue meclass del linguaggio. Il tipo TElem degli elementi


int. La struttura permette di accodare elementi che

Si realizzi in linguaggio C++ il tipo di dato astratto


diante uso del costrutto
della coda sia il tipo

possono avere due dierenti livelli di priorit:

high (alta) e low

(bassa). Un

elemento a bassa priorit viene sempre accodato alla struttura. Un elemento

EC. Esercizi su code

34

a priorit alta ha invece la precedenza sugli elementi a priorit bassa, ma


non sugli elementi a priorit alta eventualmente gi presenti nella struttura.
Di seguito riportata la specica dei metodi pubblici da implementare
per la classe

Coda.

Nome

Param. Ingr.

Param. Usc.

PriorityQueue()

TElem

Costruttore.

PriorityQueue()
Distruttore.

PushLow()

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 assenza, il primo elemento a bassa priorit. In caso di coda vuota il
comportamento di questo metodo non specicato.

Svuota()

bool

Svuota la coda.

Empty()

Predicato vero se la coda vuota, falso altrimenti.


Si realizzi una funzione

main() che permetta di eettuare il collaudo della

struttura dati realizzata.


Nessuno dei metodi della classe pu utilizzare operazioni che coinvolgono

gli stream di input ed output (cin e

cout).

La scrittura e la lettura su stream

sono concesse esclusivamente all'interno del programma

main().

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


Nome

PopMax()
Detto n il

35

Param. Ingr.

Param. Usc.

unsigned int

TElem

valore del parametro di ingresso di tipo intero, il metodo

estrae i primi

n valori di testa della struttura e restituisce il massimo

tra questi. In caso di coda vuota il comportamento di questo metodo


non specicato.

PopMin()
Detto n il

unsigned int

TElem

valore del parametro di ingresso di tipo intero, il metodo

estrae i primi

valori di testa della struttura e restituisce il minimo

tra questi. In caso di coda vuota il comportamento di questo metodo


non specicato.

Capitolo EX
Altri esercizi
EX.1 Accumulatore
Soluzione a pag. 113

Si realizzi la classe

Accumulatore

conforme all'interfaccia seguente.

Nome

Param. Ingr.

Param. Usc.

Accumulatore()

float

Costruttore della classe.

Add()

Aggiunge all'accumulaotre il valore specicato dal parametro di


ingresso.

Reset()

float

Azzera l'accumulatore.

GetValue()

Restituisce il valore corrente dell'accumulatore.

EX.2 Cifratore
Soluzione a pag. 114

Implementare la classe

Cifratore

con la capacit di cifrare stringhe di ca-

ratteri attraverso uno slittamento del codice ASCII dei caratteri componenti
la stringa (c.d. codice di Cesare). L'interfaccia della classe sia la seguente:

36

EX. Altri esercizi

37

Nome

Cifratore()
Costruttore della classe.

Param. Ingr.

Param. Usc.

int

Imposta la costante intera di slittamento

che il cifratore utilizza per crittografare le stringhe.

Cifra()

char

char

Metodo di cifratura. Accetta la stringa da cifrare e ne restituisce la


versione cifrata. La cifratura consiste in uno slittamento (shift) dei
codici ASCII di ogni singolo carattere della stringa.

Decifra()

char

char

Metodo di decifratura. Accetta la stringa cifrata attraverso il metodo

Cifra()

e ne restituisce nuovamente la versione decifrata.

EX.3 Lista Della Spesa


Soluzione a pag. 115

Si realizzi in linguaggio C++ il tipo di dato astratto


diante uso del costrutto

class

ListaDellaSpesa

me-

del linguaggio e ricorrendo ad un'implemen-

tazione dinamica. I metodi della struttura dati possono essere implementati


utilizzando indierentemente algoritmi iterativi o ricorsivi. Gli elementi della
lista siano del tipo

Articolo

specicato di seguito:

typedef char Nome [ 2 0 ] ;


typedef float Quantita ;
struct
};

Articolo {
Nome n ;
Quantita q ;

Di seguito si riporta la specica dei metodi da implementare.


Nome

Param. Ingr.

Param. Usc.

ListaDellaSpesa()

Costruttore.

ListaDellaSpesa()
Distruttore.

EX. Altri esercizi

38

Aggiungi()

Nome,Quantita

Quantita

Se nella lista non gi presente alcun altro elemento con lo stesso


nome, inserisce l'elemento specicato (nella quantit specicata) in
coda alla lista. Nel caso in cui invece l'elemento fosse gi presente
nella lista, vi aggiunge la quantit specicata.
Il metodo restituisce la quantit con cui l'articolo specicato
presente nella lista in seguito all'aggiunta.

Elimina()

Nome

bool

Elimina dalla lista l'elemento avente il nome specicato (se presente).


Il metodo restituisce

true

false

se stato cancellato un elemento,

altrimenti.

GetQuantita()

Nome

Quantita

Restituisce la quantit dell'elemento presente nella lista ed avente il


nome specicato. Se l'elemento non presente restituisce zero.

Svuota()

Svuota la lista.

Stampa()

Stampa il contenuto dell'intera lista nel formato

Nome:

Quantit, ...

L'unico metodo della classe

Nome:

Quantit,

ListaDellaSpesa che pu stampare sullo


Stampa(). Gli altri metodi (pubblici,

standard-output (cout) il metodo

privati o protetti) non possono fare uso delle funzionalit di stampa.


Si realizzi una funzione

main() che permetta di eettuare il collaudo della

struttura dati realizzata.

EX.4 Predittore di Temperatura


Soluzione a pag. 119

Realizzare la classe
temperatura.

TempPredictor

che svolga la funzione di predittore di

Tale oggetto deve essere capace di fornire una stima della

temperatura in un certo istante futuro di tempo.

La stima operata a

partire da dati presenti e passati forniti dall'utente sui valori di temperatura


misurati attraverso ipotetici sensori.
Si supponga che la stima sia ottenuta mediante estrapolazione lineare
delle ultime due temperature fornite dall'utente della classe.

Per esempio,

se l'utente comunica all'oggetto che la temperatura all'istante 0 pari a 14

EX. Altri esercizi

39

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.
Nome

Param. Ingr.

Param. Usc.

TempPredictor()

Time,Temp

Costruttore della classe. Accetta in ingresso una prima lettura reale


della temperatura, insieme all'istante in cui questa stata campionata
da un ipotetico sensore.

SetTemp()

Time,Temp

Fornisce al predittore un ulteriore valore di temperatura campionato


ed il relativo istante di campionamento.

EstimateTemp()

Time

Temp

Richiede al predittore di eettuare una stima della temperatura in


un particolare istante di tempo specicato.
Il costruttore accetta in ingresso un primo valore della temperatura ad
un certo istante di tempo.

In assenza di altri dati la stima sar pari pro-

prio a questo valore. Qualsiasi chiamata ad

EstimateTemp(),

cio, fornir

come risultato il valore di temperatura specicato all'atto della chiamata

del costruttore . Successivamente l'utente comunicher all'oggetto nuovi valori della temperatura attraverso ripetute chiamate al metodo

SetTemp(),

specicandone anche i relativi istanti di tempo.

EX.5 Contenitore
Soluzione a pag. 121

Si realizzi in linguaggio C++ il tipo di dato astratto


uso del costrutto

class del linguaggio.

Contenitore

mediante

Un Contenitore pu contenere istanze

del tipo Oggetto, denito come segue:

const int NMAX = 5 0 ;


typedef char Nome [NMAX] ;
typedef int Peso ;
struct
};

Oggetto {
Nome n ;
Peso p ;

1 Ci

permette al predittore di operare non appena divenga disponibile un primo


campionamento della temperatura.

EX. Altri esercizi

40

Inoltre, ogni contenitore pu ospitare oggetti no al raggiungimento di


un peso complessivo massimo, oltre il quale nessun altro oggetto pu essere
ospitato.
Di seguito riportata la specica dei metodi pubblici da implementare
per la classe

Contenitore.

Nome

Param. Ingr.

Contenitore()

Peso

Costruttore con parametro di tipo

Param. Usc.

Peso.

Il parametro indica il

peso massimo raggiungibile dalla totalit degli oggetti presenti nel


contenitore.

Contenitore()

Nome,Peso

bool

Distruttore.

Inserisci()

Inserisce nel contenitore un oggetto avente il nome e il peso specicato. Il metodo restituisce

true

se l'inserimento va a buon ne, cio

se il peso dell'elemento da inserire non eccede la capacit residua del


contenitore,

false

altrimenti.

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.

NumElem()

unsigned int

Restituisce il numero di oggetti presenti nel contenitore.

Stampa()

Stampa le coppie (Nome, Peso) di tutti gli oggetti presenti nel


contenitore.

Contenitore
Stampa(). Gli

L'unico metodo (pubblico, privato o protetto) della classe

che pu utilizzare lo standard-output (cout) il metodo

altri metodi dovranno restituire l'esito delle operazioni eseguite mediante gli
opportuni parametri di passaggio riportati nelle speciche.

EX. Altri esercizi

41

EX.6 Lista Prenotazioni


Soluzione a pag. 124

Si realizzi in linguaggio C++ il tipo di dato astratto


mediante uso del costrutto

class

ListaPrenotazioni

del linguaggio. La lista deve memorizzare

le prenotazioni di studenti ad un generico evento (uno ed uno solo).


elementi della lista siano del tipo

Prenotazione

Gli

specicato di seguito:

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.


Nome

Param. Ingr.

Param. Usc.

ListaPrenotazioni()

int

Costruttore con parametro intero. Il parametro indica il numero massimo di posti disponibili per l'evento, oltre i quali non deve essere
possibile inserire ulteriori prenotazioni.

ListaPrenotazioni()

Matricola,Nome

bool

Distruttore.

Prenota()

Se nella lista non gi presente alcuna altra prenotazione con lo


stesso numero di matricola e se ci sono posti disponibili, inserisce
una nuova prenotazione in coda alla lista. Il metodo restituisce l'esito
dell'operazione.

EliminaPrenotazione()

Matricola

boolt

Elimina dalla lista la prenotazione relativa al campo matricola specicato (se presente). Il metodo restituisce
un elemento,

false

true

se stato eliminato

altrimenti.

GetPostiDisponibili()

int

Restituisce il numero di posti ancora disponibili.

EsistePrenotazione()
Matricola
Restituisce true se esiste la prenotazione
matricola specicato, false altrimenti.

bool
relativa al numero di

EX. Altri esercizi

42

Svuota()

Svuota la lista.

Stampa()

MatricoNome3, ...

Stampa il contenuto dell'intera lista nel formato seguente:

la1:

Nome1, Matricola2:

Nome2, Matricola3:

ListaPrenotazioni che pu utilizzare lo


metodo Stampa(). Gli altri metodi (pubblici,

L'unico metodo della classe


standard-output (cout) il

privati o protetti) non possono fare uso degli stream di I/O.


Si realizzi una funzione

main() che permetta di eettuare il collaudo della

struttura dati realizzata.

EX.7 Classica
Soluzione a pag. 128

Si realizzi in linguaggio C++ il tipo di dato astratto


uso del costrutto

class del linguaggio.

Classifica

mediante

L'implementazione deve essere realiz-

zata mediante puntatori ed allocazione dinamica della memoria. Gli elementi


della lista siano di tipo

TElem,

denito nel modo seguente:

const int NMAX = 5 0 ;


typedef char Nome [NMAX] ; //Nome d e l l e squadre
typedef struct
Nome n ;

unsigned int

} Squadra ;

typedef

{
punteggio ;

Squadra TElem ;

Di seguito riportata la specica dei metodi pubblici da implementare


per la classe

Classifica.

Nome

Param. Ingr.

Param. Usc.

Classifica()

Costruttore.

Classifica()
Distruttore.

EX. Altri esercizi

43

Aggiungi()

Nome,unsigned
int

unsigned int

Se la squadra non gi presente, la aggiunge alla struttura e le assegna il punteggio specicato. Nel caso di squadra gi presente, aggiunge il punteggio specicato a quello gi totalizzato. Restituisce il
numero di punti correntemente totalizzati dalla squadra.

Svuota()

Svuota la struttura.

Stampa()

Stampa la classica delle squadre presenti nella struttura, in ordine


decrescente di punteggio.

Count()

unsigned int

Conta gli elementi contenuti nella struttura.

Classifica che pu utilizzare lo standardStampa(). Gli altri metodi (pubblici, privati o

L'unico metodo della classe


output (cout) il metodo

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.


Suggerimento: l'aggiornamento di un punteggio nella struttura pu essere
convenientemente realizzato attraverso la composizione di un'eliminazione ed
un inserimento ordinato.

EX.8 Agenzia Matrimoniale


Soluzione a pag. 132

Si realizzi in linguaggio C++ il tipo di dato astratto


mediante uso del costrutto

class

del linguaggio.

AgenziaMatrimoniale

L'implementazione deve

essere realizzata mediante puntatori ed allocazione dinamica della memoria.


Gli elementi della lista siano di tipo

TElem,

denito nel modo seguente:

const int NMAX = 5 0 ;


typedef char Nome [NMAX] ; //Nome Persona
struct p e r s o n a ;
typedef struct Persona{

};

Nome n ;
bool maschio ;
Persona c o n i u g e ;

EX. Altri esercizi

typedef

44

Persona TElem ;

Di seguito riportata la specica dei metodi pubblici da implementare


per la classe

AgenziaMatrimoniale.

Nome

Param. Ingr.

Param. Usc.

AgenziaMatrimoniale()

Nome,bool

bool

Costruttore.

AgenziaMatrimoniale ()
Distruttore.

AggiungiPersona()

Aggiunge alla struttura la persona avente nome specicato attraverso


i parametri di ingresso, e indica se maschio (parametro di ingresso
pari a

true) o femmina (parametro di ingresso pari


true in caso di inserimento avvenuto, false

stituisce

false)

Re-

altrimenti (se

esiste gi una persona con lo stesso nome).

Sposa()

Nome,Nome

bool

Marca come sposate le due persone presenti nella struttura ed aventi nomi specicati dai parametri di ingresso.

Restituisce l'esito

dell'operazione. L'operazione fallisce nei casi seguenti:

uno o entrambi i nomi non sono presenti nella lista;

le persone specicate sono dello stesso sesso;

una o entrambe le persone risultano gi sposate.

Coniugato()

Nome

bool, bool

Restituisce due valori booleani. Il primo indica se il nome specicato


presente o meno nella lista. Se tale valore vero, il secondo valore
restituito pari a vero se la persona dal nome specicato coniugata,
falso altrimenti.

NumeroSposi()

unsigned int

Restituisce il numero delle persone coniugate nella struttura.

NumeroCoppie()

unsigned int

Restituisce il numero di coppie di sposi presenti nella struttura.

EX. Altri esercizi

45

Svuota()

Svuota la struttura.

Stampa()

Stampa il contenuto della struttura (vedi esempio ???).


L'unico metodo della classe

AgenziaMatrimoniale che pu utilizzare lo


Stampa(). Gli altri metodi (pubblici,

standard-output (cout) il metodo

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.

EX.9 Parco Pattini


Soluzione a pag. 136

La ditta Sax gestisce una pista di pattinaggio e dispone di un parco pattini.


I pattini, tutti dello stesso modello, vengono ttati ai clienti a tempo, in
base alla taglia della calzatura richiesta. Si implementi in linguaggio C++
la classe

ParcoPattini

utile ad una prima automatizzazione nella gestione

della pista. Data la denizione del tipo Taglia:

typedef unsigned int

Taglia ;

si implementi la struttura conformemente all'interfaccia specicata di


seguito.
Nome

Param. Ingr.

Param. Usc.

ParcoPattini()

Costruttore senza parametri. Inizializza una struttura che contiene


un parco pattini vuoto.

ParcoPattini()

Taglia

Distruttore.

AggiungiPattini()

Aggiunge al parco un paio di pattini della misura specicata.

Svuota()

unsigned int

Svuota il parco pattini.

NumeroTotPattini()

Restituisce il numero di paia di pattini che costituiscono l'intero


parco.

EX. Altri esercizi

46

Fitta()

Taglia

bool

Marca come ttati un paio di pattini della taglia specicata dal

true se esiste almeno un


false altrimenti.

parametro di ingresso. Il metodo restituisce


paio di pattini della taglia specicata,

Disponibilita()

Taglia

unsigned int

Restituisce il numero di paia di pattini disponibili per la taglia


specicata.

NumeroPattini()

Taglia

unsigned int

Restituisce il numero di paia di pattini appartenenti al parco, di data


taglia (indipendentemente dal loro stato).

Restituzione()

Taglia

bool

Marca nuovamente come disponibile un paio di pattini della taglia


specicata. Il metodo restituisce

true

se eettivamente esisteva un

paio di pattini della taglia specicata marcati come ttati,

false

altrimenti.

Stampa()

Stampa a video lo stato dell'intero parco pattini.

EX.10 Timer
Soluzione a pag. 142

Si realizzi la classe

Timer

che svolga le funzioni di cronometro.

Tale og-

getto deve poter gestire i messaggi START, STOP, RESET e GETTIME


comportandosi come specicato dall'interfaccia seguente.
Nome

Param. Ingr.

Param. Usc.

Start()

Time

Avvia il conteggio del tempo.

Stop()
Arresta il conteggio del tempo.

Reset()
Arresta ed azzera il timer.

GetTime()

Restituisce il conteggio corrente del tempo.

IL TIMER VIENE CREATO

EX. Altri esercizi

47

INATTIVO

10

GETTIME

START

ATTIVO

10

15

20

INATTIVO

15

GETTIME GETTIME

25

30

35

40

STOP

GETTIME

RESET

GETTIME

Valori conteggio

Figura EX.1: Un esempio d'uso del timer nel tempo

Nella gura riportato un esempio graco del funzionamento dell'oggetto.

Suggerimenti

La seguente riga di codice:

time t = time ( 0 ) ;
istanzia una variabile

sistema, restituito dalla

time e la pone uguale


funzione time(), sotto la forma
di tipo

al tempo di
di un intero

che rappresenta il numero di secondi trascorsi dalla mezzanotte del 1


gennaio 1970. La funzione

time()

presente nella libreria C

time.h.

Il funzionamento del timer nei casi non espressamente previsti dalle


speciche sia arbitrario.

EX.11 Timer Avanzato


Soluzione a pag. 143

Con riferimento alla classe

Timer

dell'esercizio EX.10, si considerino le se-

guenti ulteriori speciche:

quando il timer riceve il messaggio START, il conteggio non deve


ripartire sempre da 0, ma dal valore correntemente memorizzato;

la ricezione di un messaggio START a timer attivo deve essere ininuente;

la ricezione di un messaggio STOP a timer fermo deve essere ininuente.

EX. Altri esercizi

48

Modicare, se necessario, l'implementazione del timer per rendere la classe conforme a queste ulteriori speciche.

EX.12 Votazioni
Soluzione a pag. 145

Si supponga di voler gestire un exit-poll elettorale.

Ad ogni intervistato

all'uscita dal seggio si chiede il partito per cui ha votato. In ogni momento
bisogna poi essere in grado di dire quanti voti ha ottenuto ciascun partito
e qual la distribuzione dei voti tra i partiti. Mediante l'uso del costrutto

class

del linguaggio C++, si realizzi una struttura dati adatta all'uopo.

Si supponga, per semplicit, che ogni partito identicato con un codice


intero, e si ignorino i voti bianchi e nulli. Di seguito riportata la specica
dei metodi pubblici da implementare per la classe

Votazioni.

Nome

Param. Ingr.

Param. Usc.

Votazioni()

unsigned int

unsigned int

Costruttore.

Votazioni()
Distruttore.

AggiungiVoto()

Aggiunge un voto al partito avente il codice specicato dal parametro di ingresso. Restituisce il numero di voti accumulati no a quel
momento dal partito.

Svuota()

unsigned int

unsigned int

Svuota la struttura.

GetVotiPartito()

Restituisce il numero di voti ottenuto dal partito avente il codice


specicato dal parametro di ingresso.

GetNumeroVoti()

unsigned int

Restituisce il numero totale di voti.

GetSituazione()

Stampa a video un riepilogo dei voti complessivamente registrati nella


struttura.

EX. Altri esercizi

49

Votazioni che
GetSituazione().

L'unico metodo della classe


output (cout) il metodo

pu utilizzare lo standardGli altri metodi (pubblici,

privati o protetti) non possono fare uso delle funzionalit di stampa.


Si realizzi una funzione
struttura dati realizzata.

main() che permetta di eettuare il collaudo della

Parte II
Soluzioni

50

Capitolo SL
Soluzioni degli esercizi su liste
SL.1 Lista Semplicemente Collegata
Traccia a pag. 12

Di seguito si riporta il le


se

Lista,

Lista.h

contenente la dichiarazione della clas-

Record e TElem funzionali all'uso


Record, che rappresenta la generica

oltre che le denizioni dei tipi

della classe. La dichiarazione del tipo

cella della lista, rispetta il principio dell'information hiding ; tale tipo infatti esclusivamente dichiarato, e sar denito solo successivamente nel le

Lista.cpp.

La sua struttura interna risulta pertanto inaccessibile agli utenti

della classe.

File Lista.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

#ifndef _LISTA_H_
#define _LISTA_H_
struct Record ; // forward
typedef Record PRec ;
typedef int TElem ;
class L i s t a {
private :
PRec f i r s t ;
int c ount ;
L i s t a& operator =( const
public :
L i s t a ( ) ; // c o s t r u t t o r e
L i s t a ( const L i s t a& l ) ;

~ L i s t a ( ) ; // d i s t r u t t o r e

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

L i s t a &); //non implementato : i n i b i s c e l ' a s s e g n a z .

senza parametri
// c o s t r u t t o r e d i c o p i a

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


int NumeroElementi ( ) const ; // R e s t i t u i s c e i l num.
void Svuota ( ) ; // Svuota l a l i s t a
51

testa
d e gl i elementi nella l i s t a

SL. Soluzioni degli esercizi su liste


22
23
24
25 } ;
26
27

void
void
bool

#endif

E limina (
Stampa ( )
Ricerca (

52

const TElem& e l ) ; // Elimina un elemento s e p r e s e n t e


const ; // Stampa su s t . out . t u t t i g l i e l e m e n t i
const TElem& e l ) const ; // I n d i c a l a p r e s e n z a d i un elemento

/ _LISTA_H_ /

Le prime due righe del le appena mostrato, insieme con l'ultima, impediscono 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 nell'eventualit che, nel grafo delle inclusioni che va a formarsi all'atto della

Lista.h risulti incluso da pi di un le.


Dal momento che l'header le Lista.h contiene esclusivamente dichiarazioni
compilazione di un le

.cpp,

il le

(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 ) {
}

const

Lista : : Lista (
L i s t a& l ) : f i r s t ( 0 ) , c ount ( l . c ount ) {
// Se provo a c o p i a r e su me s t e s s o , o s e l a l i s t a
// l vuota non e s e g u e alcuna o p e r a z i o n e .
((
!= &l ) && l . f i r s t ) {
first =
Record ;
f i r s t >e l = l . f i r s t >e l ;

if

this

new

PRec l p = l . f i r s t ;
PRec p = f i r s t ;
( lp >s u c c ) {
p>s u c c =
Record ;

while

new

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

Lista ::~ Lista () {


// I l d i s t r u t t o r e ha i l compito d i s v u o t a r e l a l i s t a d e a l l o c a n d o l e s t r u t t u r e
// precedentemente a l l o c a t e con new n e l metodo I n s e r i s c i ( ) . In caso c o n t r a r i o
// s i i n c o r r e r e b b e i n una p e r d i t a d e l l a r e l a t i v a memoria (memory l e a k ) .
Svuota ( ) ; //E ' s u f f i c i e n t e i n v o c a r e i l metodo Svuota ( ) .
}

void

Lista : : I n s e r i s c i (
PRec p =
Record ;
p>e l = e l ;
p>s u c c = f i r s t ;
first = p;

new

const

TElem& e l ) { // I n s e r i m e n t o i n t e s t a .

c ount++;

int L i s t a : : NumeroElementi ( ) const


return c ount ;

void L i s t a : : Svuota ( ) {
PRec tbd ; // t b d = t o
while ( f i r s t ) {
}
}

be d e l e t e d

tbd = f i r s t ;
f i r s t = f i r s t >s u c c ;
tbd ;

delete

c ount = 0 ;

void

const

L i s t a : : E limina (
TElem& e l ) {
// Questo metodo e l i m i n a s o l o l a e v e n t u a l e prima o c c o r r e n z a
// d e l l ' elemento s p e c i f i c a t o .
( f i r s t ) { // l a l i s t a non vuota
( f i r s t >e l == e l ) { // l ' elemento da e l i m i n a r e i n t e s t a
PRec tbd = f i r s t ;
f i r s t = f i r s t >s u c c ;
tbd ;
c ount ;
}
{ // l ' elemento da e l i m i n a r e non i n t e s t a
PRec p = f i r s t ;
trovato =
;
( ( p>s u c c ) && ( ! t r o v a t o ) ) {
// l ' elemento s u c c e s s i v o a q u e l l o p u n t a t o da p deve e s s e r e e l i m i n a t o
( p>s uc c >e l == e l ) {
PRec tbd = p>s u c c ;
p>s u c c = tbd >s u c c ; // s c o l l e g a l ' elemento t b d . . .
tbd ; // . . . e l o e l i m i n a

if

if

delete

else
bool
while
if

delete

trovato =
c ount ;

else

false

true ;

SL. Soluzioni degli esercizi su liste

54

p = p>s u c c ;

void

L i s t a : : Stampa ( )
PRec p = f i r s t ;

const

while
}

(p) {
c out << p>e l << " " ;
p = p>s u c c ;

bool L i s t a : : R i c e r c a ( const TElem&


PRec p = f i r s t ;
bool t r o v a t o = false ;
while ( ( p ) && ( ! t r o v a t o ) ) {
if ( p>e l == e l )
t r o v a t o = true ;
else
}
}

el )

const

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 .
stampaMenu ( ) ;
I n s e r i s c i ( L i s t a& l ) ;
R i c e r c a ( L i s t a& l ) ;
E limina ( L i s t a& l ) ;
Svuota ( L i s t a& l ) ;
NumeroElementi ( L i s t a& l ) ;
Stampa ( L i s t a& l ) ;
C o p i a L i s t a ( L i s t a& l ) ;

void
void
void
void
void
void
void
void
int main ( )
{
char c ;

Lista l i s t a ;

do

{
stampaMenu ( ) ;
c i n >> c ;

switch
case

(c) {
'1 ' :

SL. Soluzioni degli esercizi su liste


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&
int i ;
}

l) {

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&
int i ;

l) {

c out << " I n s e r i s c i i n t e r o : " ;


c i n >> i ;
( l . Ricerca ( i ))
c out << " Trovato . \ n" ;

if
else

c out << "Non t r o v a t o . \ n" ;

55

SL. Soluzioni degli esercizi su liste


pp

56

pp

first
el

count

succ

el

succ

el

succ

Lista
Figura SL.1: Un puntatore scorre la lista puntando ai puntatori contenuti
in essa.

void E limina ( L i s t a&


int i ;
}

l) {

c out << " I n s e r i s c i i n t e r o : " ;


c i n >> i ;
l . E limina ( i ) ;

void
}

Svuota ( L i s t a& l ) {
c out << " Svuotamento l i s t a . " << e n d l ;
l . Svuota ( ) ;

void
}

Stampa ( L i s t a& l ) {
c out << "Stampa : \ n" ;
l . Stampa ( ) ;
c out << e n d l ;

void
}

NumeroElementi ( L i s t a& l ) {
c out << "Numero E le me nt i : " << l . NumeroElementi ( ) << e n d l ;

void

C o p i a L i s t a ( L i s t a& l ) {
Lista lcopia ( l ) ;

c out << "La l i s t a c o p i a t a c o n t i e n e : " ;


l c o p i a . Stampa ( ) ;
c out << e n d l ;

Implementazione alternativa del metodo Lista::Elimina()


possibile realizzare un'implementazione alternativa del metodo

Elimina(),

ancora pi sintetica di quella appena mostrata. Tale variante, a dierenza


dell'implementazione precedente, non discrimina il caso in cui l'elemento da
eliminare sia posizionato in testa alla struttura, ma tratta i due casi in maniera omogenea. Per ottenere questo, suciente utilizzare un puntatore a

PRec

(puntatore a puntatore  vedi Figura SL.1).

Inizialmente il puntatore pp denito del tipo PRec* punta alla locazione


first, membro privato della lista (linea continua). Nella (eventuale) seconda
iterazione, esso passa a puntare alla locazione succ dell'elemento di testa

SL. Soluzioni degli esercizi su liste

57

(linea tratteggiata). In tale passaggio la compatibilit di tipo rispettata,


essendo sia

void
if

first che

del tipo

Record

dichiarati di tipo

PRec.

const

bool
while
if

succ

L i s t a : : E limina (
TElem& e l ) {
( f i r s t ) { // l a l i s t a non vuota
PRec pp = & f i r s t ; // i n d i r i z z o d e l l a v a r i a b i l e f i r s t
trovato =
;
( ( pp ) && ( ! t r o v a t o ) ) {
( ( pp)> e l == e l ) {
PRec tbd = pp ;
pp = ( pp)>s u c c ;
tbd ;

false

delete

il campo

trovato =
count ;

else

true ;

pp = &(( pp)>s u c c ) ;

SL.2 Somma Elementi


Traccia a pag. 13

const

TElem L i s t a : : Somma( )
{
PRec p = f i r s t ;
TElem somma = 0 ;
(p) {
somma = somma + p>e l ;
p=p>s u c c ;
}

while

return

somma ;

SL.3 Coda Pari


Traccia a pag. 13

Per valutare se l'elemento di coda pari possibile adottare un approccio


iterativo che, a partire dall'elemento di testa, ricerchi l'ultimo elemento e ne
restituisca il valore.

const

PRec L i s t a : : getPuntCoda ( )
{
// R e s t i t u i s c e i l p u n t a t o r e a l l a coda d e l l a l i s t a
( f i r s t ) { // l a l i s t a nonvuota ?
PRec p = f i r s t ;
( p>s u c c )
p = p>s u c c ;

if

while

return

p;

SL. Soluzioni degli esercizi su liste

else
return

58

0 ; // s e l a l i s t a vuota non e s i s t e una coda

bool L i s t a : : CodaPari ( ) const {


PRec p = getPuntCoda ( ) ; // r e s t i t u i s c e i l punt .
if ( p )
return ( ( p>e l % 2) == 0 ) ;
else
return false ; // r i t o r n a f a l s e per d e f a u l t ;

a l l a coda , s e c ' .

L'esercizio pu essere anche risolto secondo un approccio ricorsivo, cos


come riportato di seguito.

bool
if
}
}

const

L i s t a : : _CodaPari (
PRec p )
(p) {
( p>s u c c )
_CodaPari ( p>s u c c ) ;

if
return
else
return ( ( p>e l
else
return 0 ;

const

% 2) == 0 ) ;

bool L i s t a : : CodaPari ( ) const


return _CodaPari ( f i r s t ) ;

SL.4 Min e Max


Traccia a pag. 13

La ricerca del minimo e del massimo possono essere condotte secondo un approccio 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).

void
if

1
2
3
4
5
6
7
8
9
10
11
12
13
14
}
15 }

L i s t a : : MinMax ( TElem& min , TElem& max)


( first ) {
min = f i r s t >e l ;
max = f i r s t >e l ;
PRec p = f i r s t >s u c c ;

while ( p ) {
if ( p>e l < min )
min = p>e l ;
if ( p>e l > max)
}

max = p>e l ;
p = p>s u c c ;

const

SL. Soluzioni degli esercizi su liste

59

SL.5 Lista Statica


Traccia a pag. 14

#include <i o s t r e a m>


using namespace s t d ;
const int NMAX = 1 0 0 ;
typedef int TElem ;
class L i s t a {
private :
TElem v [NMAX] ;
int nelem ;
public :

//numero max d i e l e m e n t i d e l l a l i s t a

Lista ( ) ;
~Lista ( ) ;

};

void I n s e r i s c i I n C o d a ( TElem
void Svuota ( ) ;
void Stampa ( ) const ;
int Count ( ) const ;

el );

L i s t a : : L i s t a ( ) : nelem ( 0 ) {
}
Lista ::~ Lista () {
// Qui non n e c e s s a r i a alcuna o p e r a z i o n e
// I l d i s t r u t t o r e p o t e v a anche e s s e r e omesso d e l t u t t o .
}

void
if
}

L i s t a : : I n s e r i s c i I n C o d a ( TElem e l ) {
( nelem < NMAX) {
v [ nelem ] = e l ;
nelem++;

void
}

L i s t a : : Svuota ( ) {
nelem = 0 ;

void L i s t a : : Stampa ( ) const {


for ( int i = 0 ; i < nelem ;
}

c out << v [ i ] << " " ;


c out << e n d l ;

int L i s t a : : Count ( ) const


return nelem ;

i ++)

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

void I n s e r i s c i I n C o d a ( L i s t a&
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 ( )

l );

Lista l ;

int s c e l t a ;
do {

stampa_menu ( ) ;
c i n >> s c e l t a ;
( scelta ) {
1:
InserisciInCoda ( l ) ;
;
2:
Svuota ( l ) ;
;
3:
Stampa ( l ) ;
;
4:
Count ( l ) ;
;
5:
;
:
c out << " S c e l t a non v a l i d a . \ n" ;
;
}
}
( s c e l t a != 5 ) ;

switch
case
break
case
break
case
break
case
break
case
break
default
break
while
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 ) ;

void
}

Svuota ( L i s t a& l ) {
l . Svuota ( ) ;
c out << " L i s t a s v u o t a t a . \ n" ;

void
}

Stampa ( L i s t a& l ) {
c out << " I l c o n t e n u t o d e l l a l i s t a e ' : " ;
l . Stampa ( ) ;
c out << e n d l ;

void
}

Count ( L i s t a& l ) {
c out << "N. Elem : " << l . Count ( ) << e n d l ;

60

SL. Soluzioni degli esercizi su liste

61

nelem = 8

nelem = 5

Figura SL.2: Eliminazione degli elementi con valore 0 dal vettore

SL.6 Ordinata
Traccia a pag. 14

bool L i s t a : : EOrdinata ( ) const {


int i = 0 ;
while ( i < nelem 1) {
if ( v [ i ] > v [ i +1])
return false ; // e s c e s u b i t o
}
}

i ++;

return true ;

s e t r o v a un ' i n v e r s i o n e

// e s c e senza aver t r o v a t o alcuna i n v e r s i o n e : l i s t a o r d i n a t a

SL.7 Elimina Tutti


Traccia a pag. 15

Ipotizzando che l'elemento da eliminare sia 0, il metodo

EliminaTutti()

modica il vettore degli elementi come mostrato in Figura SL.2.


Per ottenere l'eetto desiderato suciente scandire in sequenza gli elementi del vettore originario (in alto nella gura).

Ad ogni passo, se l'ele-

mento puntato diverso dall'elemento da eliminare, lo si ricopia nel vettore


in basso; in caso contrario non si eettua alcuna operazione e si passa ad
analizzare l'elemento successivo. Alla ne della scansione il vettore in basso
risulter composto dai soli elementi del vettore originario diversi da quello
da eliminare.
facile convincersi del fatto che, per realizzare l'operazione appena descritta, non sia necessario utilizzare due distinti vettori, ma tutto il procedimento pu essere svolto su un unico vettore. La copia di un elemento diviene
in questo caso uno spostamento nell'ambito dello stesso vettore, senza che la
sovrascrittura della locazione di destinazione rappresenti un problema. Allo
scopo suciente utilizzare due indici

j:

SL. Soluzioni degli esercizi su liste


i

va da 0 a

nelem 1,

62

scandendo in sequenza tutti gli elementi del

vettore originario;

avanza ogni qual volta un elemento viene ricopiato, e pertanto

rappresenta il riempimento corrente del vettore ripulito.


Di seguito si riporta il codice del metodo

EliminaTutti().

int L i s t a : : E l i m i n a T u t t i ( const TElem& e l ) {


int j = 0 ;
int c ount = 0 ;
for ( int i = 0 ; i < nelem ; i ++) {
if ( v [ i ] == e l ) // sono su un elemento da e l i m i n a r e
c ount++; // incremento i l cont . d e l l e e l i m i n a z . e non r i c o p i o l ' elem .
else {
if ( i != j ) // i e j sono d i v e r s i ? ( i n u t i l e r i c o p i a r e s e i == j )
}

v [ j ] = v [ i ] ; // l o r i c o p i o n e l v e t t o r e r i p u l i t o
j ++; // i l v e t t o r e r i p u l i t o ha ora un elemento i n p i

nelem = nelem c ount ;


c ount ;

return

SL.8 Elimina Ultimi


Traccia a pag. 15

Il metodo

LasciaPrimi()

richiede di eliminare gli elementi di coda della

lista, preservandone i primi

n.

Bisogna dapprima considerare i seguenti casi

degeneri:

il numero di elementi da conservare maggiore del numero di elementi


presenti nella lista: nessun elemento va eliminato (righe 23);

il numero degli elementi da conservare pari a zero: tutti gli elementi


vanno eliminati (righe 59).

Negli altri casi, bisogna dapprima scorrere attraverso le prime

posi-

zioni della lista (righe 1116); i restanti elementi dovranno essere eliminati,
operando similmente a come accade per il metodo
L'implementazione risultante la seguente.

Svuota()

(righe 2630).

SL. Soluzioni degli esercizi su liste

63

unsigned int L i s t a : : L a s c i a P r i m i ( unsigned int n ) {


if ( n >= nelem ) // s e n >= nelem , nessun elemento va e l i m i n a t o
return 0 ;
if ( n == 0) { // s e n = 0 t u t t i g l i e l e m e n t i vanno e l i m i n a t i
unsigned int n e l = nelem ;
Svuota ( ) ;
return n e l ;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 }

PRec p = f i r s t ;

// portiamo p a puntare a l l ' u l t i m o elemento da t e n e r e n e l l a l i s t a


// b i s o g n a f a r e n1 s a l t i
(
i = 1 ; i < n ; i ++)
p = p>s u c c ;

for unsigned int

PRec l a s t = p ; // facciamo puntare da l a s t l ' elemento che d i v e r r l ' u l t i m o


p = p>s u c c ; // p punta a l primo da e l i m i n a r e
l a s t >s u c c = 0 ; // l ' elemento p u n t a t o da l a s t punta ora a z e r o :
// l a p o r z i o n e d e l l a l i s t a che va e l i m i n . ora s c o l l e g a t a

unsigned int

e l i m i n a t i = nelem n ;

// p pu ora e s s e r e immaginato come l a t e s t a d i una l i s t a da s v u o t a r e


(p) {
PRec tbd = p ;
p = p>s u c c ;
tbd ;
}

while

delete

nelem = n ;
eliminati ;

return

Il metodo

EliminaUltimi()

deve eliminare gli ultimi

elementi. Esso

non dierisce nella sostanza dal precedente metodo, e pu essere pertanto


implementato nei termini di quest'ultimo.

unsigned int L i s t a : : E l i m i n a U l t i m i ( unsigned int n ) {


if ( n >= nelem ) { // s e n >= nelem l a l i s t a va s v u o t a t a
unsigned int n = nelem ;
Svuota ( ) ;
return n ;
} else // a l t r i m e n t i implement . q u e s t o metodo n e i t e r m i n i
return L a s c i a P r i m i ( nelem n ) ;

d i LasciaPrimi ( )

SL.9 Somma Coda


Traccia a pag. 15

L'approccio in generale pi eciente per risolvere questo problema consiste


nel tenere memoria in un membro privato della lista del valore della coda.

SL. Soluzioni degli esercizi su liste

64

Tale valore deve essere costantemente aggiornato, a cura di tutti i metodi che possono potenzialmente alterarlo: inserimento, eliminazione, svuotamento, ecc.

Si noti che lo stesso metodo

il valore della coda.


di

Inserisci()

SommaCoda()

nisce per alterare

Di seguito si mostrano le implementazioni dei meto-

SommaCoda(),

nelle ipotesi che la lista sia dotata di una

variabile-membro privata denita come segue:

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 =
Record ;
p>e l = e l ;
p>s u c c = f i r s t ;
first = p;
nelem++;

new

// 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 .
( ! f i r s t >s u c c )
v alor e C oda = e l ;

if

void
if

L i s t a : : SommaCoda ( ) {
( 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 ;
(p) {
p>e l = p>e l + v alor e C oda ;
p = p>s u c c ;
}

while

// In q u e s t o punto , i l v a l o r e d e l l ' elemento d i coda r a d d o p p i a t o .


// Aggiorno l a v a r i a b i l e membro .
v alor e C oda = v alor e C oda 2 ;

SL.10 Sposta Testa in Coda


Traccia a pag. 16

Per svolgere l'operazione si fa uso di un metodo di supporto

getPuntCoda()

deputato a restituire il puntatore all'elemento di coda della lista, se esistemte.

Si noti che nessun elemento viene creato (new) o distrutto (delete), ma


l'operazione eettuata esclusivamente mediante ricollocazione di puntatori.

SL. Soluzioni degli esercizi su liste

65

// Metodo p r i v a t o

const

PRec L i s t a : : getPuntCoda ( )
{
// R e s t i t u i s c e i l p u n t a t o r e a l l a coda d e l l a l i s t a
( first ) {
PRec p = f i r s t ;
( p>s u c c )
p = p>s u c c ;

if

while

return
else
return

}
}

p;
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

bool L i s t a : : Spos t aT e st aInC oda ( ) {


PRec p = getPuntCoda ( ) ; // r e s t i t u i s c e
if ( p ) {
}
}

i l punt . a l l a coda , s e c ' .

p>s u c c = f i r s t ;
f i r s t = f i r s t >s u c c ;
p>s uc c >s u c c = 0 ;

return

( p != 0 ) ; // s e p non 0 , l o spostamento s t a t o e f f e t t u a t o

SL.11 Elimina Pari e Dispari


Traccia a pag. 16

unsigned int
int n = 0 ;
if ( f i r s t )

Lista : : EliminaElementiPostoDispari () {

{
PRec p = f i r s t ; // p punta a l primo elemento ( d i i n d i c e 0 , q u i n d i p a r i )

// Se p punta ad un elemento , e q u e s t o elemento ha un s u c c e s s i v o . . .


( p && p>s u c c ) {
PRec tbd = p>s u c c ; // . . . i l s u c c e s s i v o deve e s s e r e e l i m i n a t o .
p>s u c c = p>s uc c >s u c c ; // S c o l l e g o l ' elemento da canc . d a l l a catena ,
tbd ; // l o d i s t r u g g o ,

while

delete

}
}

// p passa a l l ' elemento s u c c e s s i v o ,


// sempre d i i n d i c e p a r i ( n e l l a l i s t a o r i g i n a l e ) .
p = p>s u c c ;
n++;

return

n;

unsigned int
int n = 0 ;
if ( f i r s t )

Lista : : EliminaElementiPostoPari () {

{ // e s c i s u b i t o s e l a l i s t a vuota . . .
// . . . a l t r i m e n t i c a n c e l l a s u b i t o i l primo elemento ( i n d i c e 0)
PRec tbd = f i r s t ;

SL. Soluzioni degli esercizi su liste

66

f i r s t = f i r s t >s u c c ;
tbd ;
n++;

delete

}
}

// essendo s t a t a e l i m i n a t a l a t e s t a non r e s t a che


// e l i m i n a r e t u t t i g l i e l e m e n t i d i p o s t o d i s p a r i d e l l ' a t t u a l e l i s t a .
n = n + EliminaElementiPostoDispari ( ) ;

return

n;

SL.12 Lista Doppiamente Collegata


Traccia a pag. 16

#include <i o s t r e a m>


using namespace s t d ;
struct Record ;
typedef Record PRec ;
typedef int TElem ;
struct Record {
};

TElem e l ;
PRec p r e c ;
PRec s u c c ;

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 ) {
}
Lista ::~ Lista () {
Svuota ( ) ;
}

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 =
Record ;
p>e l = e l ;
p>s u c c = 0 ;
p>p r e c = l a s t ;
( last )
l a s t >s u c c = p ;
last = p;

new

if

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 ;
tbd ;

delete

}
nelem = 0 ;
last = 0;

void L i s t a : : St ampaDir e t t a ( ) const


PRec p = f i r s t ;
while ( p != 0) {
}

c out << p>e l << " " ;


p = p>s u c c ;

void L i s t a : : St ampaInv e r sa ( ) const


PRec p = l a s t ;
while ( p != 0) {
}

c out << p>e l << " " ;


p = p>p r e c ;

void

L i s t a : : StampaAlternat a ( )
PRec p = f i r s t ;
PRec q = l a s t ;
done =
;

bool
false
while ( ( p ) && ! done )
c out << p>e l << "
if ( q != p )

const

{
";

c out << q>e l << " " ;

// s e p e q sono s o v r a p p o s t i oppure sono c o n s e c u t i v i


// abbiamo t e r m i n a t o
( ( p == q ) | | ( p>s u c c == q ) )
done =
;

if

true

p = p>s u c c ;
q = q>p r e c ;

SL. Soluzioni degli esercizi su liste

unsigned int L i s t a : : Count ( ) const


return nelem ;

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 ;
( scelta ) {
1:
Inserisci ( l );
;
2:
Svuota ( l ) ;
;
3:
St ampaDir e t t a ( l ) ;
;
4:
St ampaInv e r s a ( l ) ;
;
5:
StampaAlternat a ( l ) ;
;
6:
Count ( l ) ;
;
7:
;
:
c out << " S c e l t a non v a l i d a . \ n" ;
;
}
}
( s c e l t a != 7 ) ;

switch
case
break
case
break
case
break
case
break
case
break
case
break
case
break
default
break
while
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 );

void
}

Svuota ( L i s t a& l ) {
l . Svuota ( ) ;
c out << " L i s t a s v u o t a t a . \ n" ;

void
}

St ampaDir e t t a ( L i s t a& l ) {
c out << "Stampa D i r e t t a : " ;
l . St ampaDir e t t a ( ) ;
c out << e n d l ;

void
}

St ampaInv e r s a ( L i s t a& l ) {
c out << "Stampa I n v e r s a : " ;
l . St ampaInv e r s a ( ) ;
c out << e n d l ;

void
}

StampaAlternat a ( L i s t a& l ) {
c out << "Stampa A l t e r n a t a : " ;
l . StampaAlter nat a ( ) ;
c out << e n d l ;

void
}

Count ( L i s t a& l ) {
c out << " I l numero d i e l e m e n t i c o n t e n u t i n e l l a l i s t a e ' : "
<< l . Count ( ) << e n d l ;

SL.13 Ribalta
Traccia a pag. 18

L'approccio in generale pi eciente per ribaltare la lista consiste nel modicare 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

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
ottenerne il ribaltamento suciente che il campo

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

first

el1

70

el2

eln

(a) Lista originale

eli-1

eli

p1

p2

eli+1

(b) Prima dell'i-esima iterazione

eli-1

eli

eli+1

p1

p2

temp

(c) Dopo l'i-esima iterazione

first

el1

el2

eln

(d) Lista ribaltata

Figura SL.3: Il processo logico di ribaltamento di una lista

SL. Soluzioni degli esercizi su liste

71

due elementi consecutivi e spostandosi in avanti di un elemento alla volta.


Ad ogni passo dell'iterazione lo scambio pu essere eettuato servendosi di
un terzo puntatore temporaneo (vedi Figure SL.3(b) e SL.3(c)).

Lo stato

nale della lista al termine dell'iterazione riportato in Figura SL.3(d).

// 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
Lista : : Ribalta () {
( 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

void
if

while

( p2>s u c c ) { // s e p2 non l ' u l t i m o elemento


PRec temp = p2>s u c c ; // memorizzo i n temp i l s u c c e s s i v o d i p2
p2>s u c c = p1 ; // i l s u c c e s s i v o d i p2 ora p1

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 ) {
( ( ! 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
p;
{

if

return
else

SL. Soluzioni degli esercizi su liste


// 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 ) ;
// l a v e c c h i a t e s t a d i v i e n e l ' u l t i m o elemento ( e q u i n d i punta a 0)
v e c c h i a _ t e s t a >s u c c = 0 ;
// i l v e c c h i o secondo elemento punta a l l a v e c c h i a t e s t a
v e c c hio_s e c ondo >s u c c = v e c c h i a _ t e s t a ;

return

nuova_testa ; // r e s t i t u i s c o l a nuova t e s t a

// Metodo p u b b l i c o
Lista : : Ribalta () {
f i r s t = _ribalta ( f i r s t ) ;
}

void

72

Capitolo SA
Soluzioni degli esercizi su alberi
binari
SA.1 Albero Binario
Traccia a pag. 19

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
class A l b e r o B i n a r i o {
private :

interi

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
_CopiaAlbero ( PNodo& de st ,
PNodo& s o u r c e ) ;
_Svuota (
PNodo& n ) ;
_AggiungiElem ( PNodo& n ,
TElem& e l ) ;
_ S o s t i t u i s c e ( PNodo& n , PNodo& p ) ;
_InAlb (
PNodo& n ,
TElem& e l )
;
_Elimina ( PNodo& n ,
TElem& e l ) ;
_PreOrdine (
PNodo& n )
;
_PostOrdine (
PNodo& n )
;
_InOrdine (
PNodo& n )
;

void
void
void
void
bool
void
void
void
void

const
const
const
const
const
const
const
const
const
const
const
const

const

// 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&
=(
A l b e r o B i n a r i o &);
:
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

public

operator const

73

SA. Soluzioni degli esercizi su alberi binari

74

const

AlberoBinario (
A l b e r o B i n a r i o & a ) ; // c o s t r u t t o r e d i c o p i a
~ A l b e r o B i n a r i o ( ) ; // D i s t r u t t o r e

};

void
bool
void
void
void
void
void

#endif

const
const
const
const
const
const

AggiungiElem (
TElem& e l ) ;
InAlb (
TElem& e l )
;
E limina (
TElem& e l ) ;
Svuota ( ) ;
PreOrdine ( )
;
P os t Or dine ( )
;
InOr dine ( )
;

const

/ _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 ( ) : root (0) {


}

const

AlberoBinario : : AlberoBinario (
AlberoBinario& a ) {
(
!= &a ) // c o p i a s o l o da un o g g e t t o d i f f e r e n t e
_CopiaAlbero ( r oot , a . r o o t ) ;
}

if this

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

void

const

A l b e r o B i n a r i o : : _CopiaAlbero ( PNodo& de st ,
PNodo& s o u r c e ) {
// Questo metodo r i c o r s i v o a c c e t t a i n i n g r e s s o un p u n t a t o r e ad un a l b e r o
// s o r g e n t e ( s o u r c e ) e r e s t i t u i s c e i n u s c i t a un p u n t a t o r e ad un a l b e r o che
// v i e n e c o s t r u i t o r i c o p i a n d o i l primo .
( s o u r c e ) { // s e l a s o r g e n t e non l ' a l b e r o vuoto
dest =
Nodo ; // crea un nuovo nodo
de s t >e l = s o u r c e >e l ; // assegna i l c o n t e n u t o d a l l a s o r g e n t e a l l a d e s t i n a z .

if

new

//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 .

_CopiaAlbero ( de s t >s i n , s o u r c e >s i n ) ; // assegna i l s o t t o a l b e r o s i n i s t r o


_CopiaAlbero ( de s t >des , s o u r c e >de s ) ; // assegna i l s o t t o a l b e r o d e s t r o

else

dest = 0;

SA. Soluzioni degli esercizi su alberi binari

75

void
if
}

new

else
if ( e l > n>e l )
_AggiungiElem ( n>des ,
else

el );

_AggiungiElem ( n>s i n , e l ) ;

bool
if
if

const

A l b e r o B i n a r i o : : _AggiungiElem ( PNodo& n ,
TElem& e l ) {
( ! n) {
n =
Nodo ; // s i crea un nuovo elemento d e l l ' a l b e r o . . .
n>e l = e l ; // . . . e l o s i i n i z i a l i z z a .
n>s i n = 0 ;
n>de s = 0 ;

A l b e r o B i n a r i o : : _InAlb (
( ! n)
;

return false

const

PNodo& n ,

const

TElem& e l )

const

( n>e l == e l ) // l ' elemento c e r c a t o n e l l a r a d i c e ?

return true ;

if ( e l > n>e l ) // maggiore


return _InAlb ( n>des , e l ) ;
else
return _InAlb ( n>s i n , e l ) ;

del contenuto d e l l a radice ?


// c e r c a n e l s o t t o a l b e r o d e s t r o
// c e r c a n e l s o t t o a l b e r o s i n i s t r o

void

//
//
//
//
//
//
//
//

A l b e r o B i n a r i o : : _ S o s t i t u i s c e ( PNodo& n , PNodo& p ) {
Questo metodo ha come parametri d i i n g r e s s o u s c i t a :
n : un p u n t a t o r e a l l a r a d i c e d i un a l b e r o ;
p : un p u n t a t o r e ad un nodo .
I l suo e f f e t t o q u e l l o d i s o s t i t u i r e i l nodo p u n t a t o da p con i l massimo
elemento d e l l ' a l b e r o n . La prima v o l t a q u e s t o metodo v i e n e i n v o c a t o
( n e l metodo e l i m i n a ) con l a s i n t a s s i _ S o s t i s u i s c i ( n>sin , n ) , p e r c u i
s i p r o v v e d e a l l a s o s t i t u z i o n e d e l nodo n con i l massimo d e l suo
sottoalbero sinistro .
PNodo q ;
( ! n>de s ) {
q = n;
n = n>s i n ;
q>s i n=p>s i n ;
q>de s=p>de s ;
p=q ;
}
_ S o s t i t u i s c e ( n>des , p ) ;

if

else

void
if

const

A l b e r o B i n a r i o : : _Elimina ( PNodo& n ,
TElem& e l ) {
( n ) { // Eliminare da un a l b e r o vuoto non produce alcuna o p e r a z i o n e
( n>e l == e l ) {
// c a n c e l l a nodo c o r r e n t e
PNodo p = n ;
( ! n>s i n ) // i l ramo s i n i s t r o d e l nodo da e l i m i n a r e vuoto ?
n = n>de s ; // s o s t i t u z i o n e d e l nodo c o l suo s o t t o a l b e r o d e s t r o

if

if
else
if ( ! n>de s ) // i l ramo d e s t r o d e l nodo da e l i m i n a r e vuoto ?
n = n>s i n ; // s o s t i t u z i o n e d e l nodo c o l suo s o t t o a l b e r o s i n i s t r o
else // i l nodo da e l i m i n a r e ha s i a i l s o t t o a l b e r o s x che q u e l l o dx ?
_ S o s t i t u i s c e ( n>s i n , n ) ; // chiamo i l " s e r v i z i o " S o s t i t u i s c e ( )
delete p ;

SA. Soluzioni degli esercizi su alberi binari


}

void
if
}

void
if
}

void
if
}

void
if
}

else
if ( e l > n>e l )
_Elimina ( n>des ,
else

76

el );

_Elimina ( n>s i n , e l ) ;

const

A l b e r o B i n a r i o : : _Svuota (
PNodo& n ) {
( n ) { // Agisce s o l o s e l ' a l b e r o e s i s t e
_Svuota ( n>s i n ) ;
_Svuota ( n>de s ) ;
n;

delete

A l b e r o B i n a r i o : : _PreOrdine (
(n) {
c out << n>e l << " " ;
_PreOrdine ( n>s i n ) ;
_PreOrdine ( n>de s ) ;

const

A l b e r o B i n a r i o : : _PostOrdine (
(n) {
_PostOrdine ( n>s i n ) ;
_PostOrdine ( n>de s ) ;
c out << n>e l << " " ;

A l b e r o B i n a r i o : : _InOrdine (
(n) {
_InOrdine ( n>s i n ) ;
c out << n>e l << " " ;
_InOrdine ( n>de s ) ;

const

const

const

PNodo& n )

PNodo& n )

PNodo& n )

const

const

// Metodi p u b b l i c i

void
}

A l b e r o B i n a r i o : : AggiungiElem (
_AggiungiElem ( r oot , e l ) ;

bool A l b e r o B i n a r i o : : InAlb ( const


return _InAlb ( r oot , e l ) ;

const

TElem& e l ) {

TElem& e l )

const

void
}

A l b e r o B i n a r i o : : Elimina (
_Elimina ( r oot , e l ) ;

const

TElem& e l ) {

void
}

A l b e r o B i n a r i o : : Svuota ( ) {
_Svuota ( r o o t ) ;
root = 0;

void
}

A l b e r o B i n a r i o : : PreOrdine ( )
_PreOrdine ( r o o t ) ;

const

SA. Soluzioni degli esercizi su alberi binari

void
}

A l b e r o B i n a r i o : : Post Or dine ( )
_PostOrdine ( r o o t ) ;

void
}

A l b e r o B i n a r i o : : InOr dine ( )
_InOrdine ( r o o t ) ;

const

const

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 .
stampaMenu ( ) ;
I n s e r i s c i ( AlberoBinario& a ) ;
Ricerca ( AlberoBinario& a ) ;
E limina ( A l b e r o B i n a r i o & a ) ;
Svuota ( A l b e r o B i n a r i o & a ) ;
PreOrdine ( A l b e r o B i n a r i o & a ) ;
InOr dine ( A l b e r o B i n a r i o & a ) ;
P os t Or dine ( A l b e r o B i n a r i o & a ) ;
Copia ( A l b e r o B i n a r i o & a ) ;

void
void
void
void
void
void
void
void
void
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 ) ;

77

SA. Soluzioni degli esercizi su alberi binari

break ;
case ' 9 ' :
break ;
default :
c out << " S c e l t a
break ;
}
} while ( c != ' 9 ' ) ;
return 0 ;

non v a l i d a . \ n" ;

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 ;
( a . InAlb ( i ) )
c out << " Trovato . \ n" ;

if
else

c out << "Non t r o v a t o . \ n" ;

void E limina ( 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 . E limina ( i ) ;

void
}

Svuota ( A l b e r o B i n a r i o & a ) {
c out << " Svuotamento a l b e r o . " << e n d l ;
a . Svuota ( ) ;

void
}

PreOrdine ( A l b e r o B i n a r i o & a ) {
c out << "Stampa i n pre o r d i n e : \ n" ;
a . PreOrdine ( ) ;
c out << e n d l ;

78

SA. Soluzioni degli esercizi su alberi binari

79

void
}

InOr dine ( A l b e r o B i n a r i o & a ) {


c out << "Stampa i n o r d i n e : \ n" ;
a . InOr dine ( ) ;
c out << e n d l ;

void
}

P os t Or dine ( A l b e r o B i n a r i o & a ) {
c out << "Stampa i n post o r d i n e : \ n" ;
a . P os t Or dine ( ) ;
c out << e n d l ;

void

Copia ( A l b e r o B i n a r i o & a ) {
AlberoBinario b( a ) ;
c out << "La v i s i t a i n o r d i n e d e l l ' a l b e r o c o p i a t o e ' : " ;
b . InOr dine ( ) ;
c out << e n d l ;

// 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 .

SA.2 Numero Elementi


Traccia a pag. 20

La tecnica pi semplice per eettuare il conteggio del numero di elementi


contenuti in un albero, consiste nel denire un membro privato di tipo intero
non negativo atto a memorizzare tale valore.

Il valore del membro viene

alterato da tutti i metodi della struttura che modicano il numero di nodi


presenti in essa (inserimento, eliminazione, svuotamento, ecc.).
Qui si mostrer un approccio dierente, di solito meno eciente, consistente in un metodo ricorsivo che calcola il numero di elementi mediante una
visita completa dell'albero.

// 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

unsigned int A l b e r o B i n a r i o : : _Occorrenze ( const PNodo& n ,


const TElem& e l ) const
if ( ! n ) // Se l ' a l b e r o con r a d i c e i n n vuoto . . .
return 0 ; // . . . i l numero d i o c c o r r e n z e p a r i a z e r o .
int oc c = 0 ;
if ( n>e l == e l )

oc c ++;

if

( e l > n>e l ) // i l segno > deve e s s e r e c o e r e n t e con l a c o n v e n z i o n e


// s t a b i l i t a per l ' i n s e r i m e n t o d e g l i e l e m e n t i n e l l ' a l b e r o
oc c = oc c + _Occorrenze ( n>des , e l ) ;

else

oc c = oc c + _Occorrenze ( n>s i n , e l ) ;

return

oc c ;

// Metodo p u b b l i c o

unsigned int A l b e r o B i n a r i o : : Oc c or r e nz e ( const


return _Occorrenze ( r oot , e l ) ;

TElem& e l )

const

SA.4 Occorrenza Massima


Traccia a pag. 21

L'interfaccia della classe

AlberoBinario

da realizzare mostrata di seguito,

con enfasi sulle modiche da applicare alla versione della classe presentata
in EA.1.

class A l b e r o B i n a r i o
private :

...

const int

maxocc ;

...

bool _ I n s e r i s c i ( PNodo& n , const TElem&


public :
A l b e r o B i n a r i o ( unsigned int max_occ ) ;

el ,

int

c ur r _oc c ) ;

...
};

bool

Inserisci (

const

TElem& e l ) ;

Particolare attenzione merita la funzione

Inserisci().

Tale funzione

ricorsiva si occupa dell'inserimento nell'albero dell'elemento specicato dal


parametro di ingresso, nel rispetto del vincolo delle occorrenze massime. Essa

SA. Soluzioni degli esercizi su alberi binari

81

si basa sulla propriet secondo la quale, durante l'inserimento di un elemento


in un albero binario ordinato, bisogna necessariamente attraversare tutti gli
eventuali altri nodi contenenti lo stesso valore da inserire. possibile dunque discendere attraverso l'albero in cerca della posizione in cui aggiungere
l'elemento e, contemporaneamente, tenere il conteggio dell'occorrenza delle
eventuali repliche, interrompendo prematuramente l'inserimento in caso di
raggiungimento del numero massimo di occorrenze.
L'implementazione dei metodi dichiarati riportata di seguito.

AlberoBinario : : AlberoBinario (

unsigned int

max_occ ) : r o o t ( 0 ) ,
maxocc ( max_occ ) {

// 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
A l b e r o B i n a r i o : : _ I n s e r i s c i ( PNodo& n ,
TElem& e l ,
c ur r _oc c ) {
( ! n ) { // s e l ' a l b e r o vuoto i n s e r i s c o certamente
n =
Nodo ;
n>e l = e l ;
n>s i n = 0 ;
n>de s = 0 ;
;
}
{
( 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 . . .
( 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 . . .
; // . . . e s c o con i l v a l o r e f a l s e .
}

bool
if

const

new

int

return true
else
if
if
return false

// 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 .
( e l > n>e l )
_ I n s e r i s c i ( n>des , e l , c ur r _oc c ) ;

if
return
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
if ( maxocc > 0)
return _ I n s e r i s c i ( r oot , e l , 0 ) ;
else
return false ;

TElem& e l ) {

SA.5 Profondit Limitata


Traccia a pag. 21

L'interfaccia della classe

AlberoBinario

da realizzare mostrata di seguito,

con enfasi sulle modiche da applicare alla versione della classe presentata
in EA.1.

class

AlberoBinario {

SA. Soluzioni degli esercizi su alberi binari

82

private :
...

const unsigned int


...

maxDepth ;

public :

};

bool
if

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 ) ;
...
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

TElem& e l ,

unsigned int

( _maxDepth > 0) {
( ! n) {
n =
Nodo ; // s i crea un nuovo elemento d e l l ' a l b e r o . . .
n>e l = e l ; // . . . e l o s i i n i z i a l i z z a .
n>s i n = 0 ;
n>de s = 0 ;

if

_maxDepth ) {

new

return true ;
else
if ( e l > n>e l )
return _ I n s e r i s c i ( n>des ,
else
return _ I n s e r i s c i ( n>s i n ,

}
}

e l , _maxDepth 1 ) ;
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 ) {

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&


return _ I n s e r i s c i ( r oot , e l , maxDepth ) ;

el ) {

SA.6 Somma
Traccia a pag. 22

// Metodo p r i v a t o

void
if
}

A l b e r o B i n a r i o : : _Somma(
( n && ( i != 0 ) ) {
n>e l += i ;
_Somma( n>s i n , i ) ;
_Somma( n>des , i ) ;

const

PNodo& n ,

int

i) {

SA. Soluzioni degli esercizi su alberi binari

83

// Metodo P u b b l i c o

void
}

A l b e r o B i n a r i o : : Somma(
_Somma( r oot , i ) ;

int

i) {

SA.7 Sostituisci
Traccia a pag. 22

// Metodo p r i v a t o

unsigned int A l b e r o B i n a r i o : : _ S o s t i t u i s c i ( PNodo& n , TElem


unsigned int s o s t i t u z i o n i = 0 ;
if ( n ) {
// S o s t i t u i s c o prima n e i s o t t o a l b e r i . . .
if ( i > n>e l )
s o s t i t u z i o n i = s o s t i t u z i o n i + _ S o s t i t u i s c i ( n>des ,
else

i , TElem j ) {

i , j );

s o s t i t u z i o n i = s o s t i t u z i o n i + _ S o s t i t u i s c i ( n>s i n , i , j ) ;

// . . . p o i n e l l a r a d i c e
( n>e l == i ) {
n>e l = j ;
s o s t i t u z i o n i ++;
}

if

}
}

return

sostituzioni ;

// Metodo p u b b l i c o

unsigned int A l b e r o B i n a r i o : : S o s t i t u i s c i ( TElem


return _ S o s t i t u i s c i ( r oot , i , j ) ;

i , TElem j ) {

SA.8 Conta Min e Max


Traccia a pag. 22

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 nell'intervallo

5,

(10, 20).

In occasione della visita di un ipotetico elemento pari a

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
A l b e r o B i n a r i o : : _ContaMinMax (

unsigned int

const

PNodo& n , TElem Min ,

SA. Soluzioni degli esercizi su alberi binari

if

84

TElem Max)
(n) {
c ount = 0 ;
// Se l ' elemento p u n t a t o da e l compreso t r a Min e Max . . .
( ( n>e l >= Min ) && ( n>e l <= Max ) )
c ount ++; // . . . incremento count .

int
if

const

// Se l ' elemento p u n t a t o da n minore d i Max . . .


( n>e l < Max) {
// . . . a l l o r a n e l s o t t o a l b e r o d e s t r o p o t r e b b e r o e s s e r c i a l t r i e l e m e n t i .
c ount = c ount + _ContaMinMax ( n>des , Min , Max ) ;
}

if

if
}
}

( n>e l >= Min) //E v i c e v e r s a per i l s o t t o a l b e r o s i n i s t r o .


c ount = c ount + _ContaMinMax ( n>s i n , Min , Max ) ;

return
else
return

c ount ;
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


return _ContaMinMax ( r oot , Min , Max ) ;

Min , TElem Max)

const

SA.9 Profondit Maggiore di Due


Traccia a pag. 23

Si noti che il metodo riportato di seguito non ricorsivo, n richiama alcun


altro metodo.

bool A l b e r o B i n a r i o : : ProfMaggioreDiDue ( ) const


return

// c ' l a r a d i c e e . . .
// . . . o e s i s t e i l nodo d i s i n i s t r a e q u e s t o ha almeno un f i g l i o
// oppure e s i s t e i l nodo d i d e s t r a e q u e s t o ha almeno un f i g l i o .
// Tradotto i n c o d i c e s i ha :
r o o t && (
( r oot >s i n && ( r oot >s i n >s i n | | r oot >s i n >de s ) ) | |
( r oot >de s && ( r oot >des >s i n | | r oot >des >de s ) )
);

SA.10 Profondita Maggiore Di


Traccia a pag. 23

// Metodo p r i v a t o
A l b e r o B i n a r i o : : _ProfMaggioreDi (
PNodo& n ,
( n ) { // s e l ' a l b e r o non vuoto . . .
( 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 . . .

bool
if

if

const

unsigned int

p)

const

SA. Soluzioni degli esercizi su alberi binari

85

return true ; // . . . abbiamo s u p e r a t o l a p r o f . r i c h i e s t a . . .


else // . . . a l t r i m e n t i b i s o g n a c o n t i n u a r e l a d i s c e s a n e i s o t t o a l b e r i decrement .
return ( _ProfMaggioreDi ( n>s i n , p 1) | | _ProfMaggioreDi ( n>des , p 1 ) ) ;
}
else // . . . a l t r i m e n t i f a l s o .
return false ;

// Metodo p u b b l i c o
A l b e r o B i n a r i o : : Pr of Maggior e Di (
_ProfMaggioreDi ( r oot , p ) ;
}

bool
return

unsigned int

p)

const

SA.11 Profondit Massima


Traccia a pag. 23

int A l b e r o B i n a r i o : : _Pr of ondit a ( const PNodo& n , const TElem& e l ,


bool& f o g l i a ) const
if ( n ) { // s e l ' a l b e r o vuoto e s c o s u b i t o
int p ;
// d e c i d o s e c e r c a r l o a d e s t r a o a s i n i s t r a e . . .
if ( e l > n>e l )

// . . . uso i l s e r v i z i o che i o s t e s s o o f f r o : r i c o r s i o n e .
p = _P r of ondit a ( n>des , e l , f o g l i a ) ;

else

p = _P r of ondit a ( n>s i n , e l , f o g l i a ) ;

if

( p != 1) // s e l ' ho t r o v a t o i n p r o f o n d i t p a l " piano d i s o t t o " . . .


p + 1 ; // . . . l a p r o f o n d i t d a l mio punto d i v i s t a p + 1 .

return

// s e sono q u i v u o l d i r e che ancora devo t r o v a r l o


( n>e l == e l ) { // s e sono p r o p r i o i o . . .
// . . . s e non ho f i g l i l ' elemento t r o v a t o anche una f o g l i a . . .
f o g l i a = ( ! n>s i n && ! n>de s ) ;
1 ; // . . . e l a p r o f o n d i t d a l mio punto d i v i s t a 1 .
}

if

return

// s e sono q u i non l ' ho t r o v a t o


1;

return

int A l b e r o B i n a r i o : : P r o f o n d i t a ( const TElem&


return _P r of ondit a ( r oot , e l , f o g l i a ) ;

el ,

bool&

foglia )

const

SA.12 Somma Livello


Traccia a pag. 24

// Metodo p r i v a t o

void

A l b e r o B i n a r i o : : _SommaLivello (

const

PNodo& n ,

unsigned int

i) {

p.

SA. Soluzioni degli esercizi su alberi binari

if
}

86

(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 ) ;

SA.13 Eliminazione Foglia


Traccia a pag. 24

// Metodi p r i v a t i
A l b e r o B i n a r i o : : EUnaFoglia (
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 .
( ! n>s i n && ! n>de s ) ;
}

inline bool

const

return

bool
if

}
}

const

A l b e r o B i n a r i o : : _EliminaF oglia ( PNodo& n ,


TElem& e l ) {
( n ) { // s e n punta ad un nodo ( e non a z e r o )
// s e l ' elemento p u n t a t o e l e i l nodo una f o g l i a
( ( n>e l == e l ) && EUnaFoglia ( n ) ) {
n ; // e l i m i n a l ' elemento
n = 0 ; // a z z e r a i l p u n t a t o r e
;
}
( e l > n>e l )
// r i p e t i l ' o p e r a z i o n e n e l s o t t o a l b . d e s t r o
_E liminaF oglia ( n>des , e l ) ;

if

delete
return true
else
if
return
else
// r i p e t i l ' o p e r a z i o n e n e l s o t t o a l b .
return _E liminaF oglia ( n>s i n , e l ) ;

sinistro

return false ;

// Metodo p u b b l i c o
AlberoBinario : : EliminaFoglia(
( _E liminaF oglia ( r oot , e l ) ) {
numelem;
;
}
;
}

bool
if

const

TElem& e l ) {

return true
else
return false

SA.14 Eliminazione Foglie


Traccia a pag. 24

SA. Soluzioni degli esercizi su alberi binari

87

// Metodi p r i v a t i
A l b e r o B i n a r i o : : EUnaFoglia (
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 .
( ! n>s i n && ! n>de s ) ;
}

inline bool

const

return

unsigned int A l b e r o B i n a r i o : : _EliminaF oglie ( PNodo& n ) {


if ( n ) {
if ( EUnaFoglia ( n ) ) {
delete n ;
n = 0;
return 1 ;
}
else
return _E liminaF oglie ( n>s i n ) + _EliminaF oglie ( 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 ) ) ;

SA.15 Cerca Foglia


Traccia a pag. 25

// Metodi p r i v a t i
A l b e r o B i n a r i o : : EUnaFoglia (
( ! n>de s && ! n>s i n ) ;
}

inline bool
return

// Metodi r i c o r s i v i d i s u p p o r t o
A l b e r o B i n a r i o : : _C e r c aF oglia (

bool
if

( ! n)

return false ;
bool t r o v a t o ;

const

const

PNodo& n )

const

PNodo& n , TElem e l ,
& foglia )

bool

// Cerco s u b i t o p i i n b a s s o .
( 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 ) ;

if
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 . . .

const

SA. Soluzioni degli esercizi su alberi binari

if
}
}

( n>e l == e l ) { // . . . e sono p r o p r i o i o . . .
trovato =
; // . . . 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

bool
if
if
}

88

true

trovato ;

A l b e r o B i n a r i o : : _CercaNodo (
( ! n)
;

return false

const

bool& nodo ) const

PNodo& n , TElem e l ,

( n>e l == e l ) { // Se l ' elemento c o r r e n t e p a r i ad e l . . .


nodo = ( ! EUnaFoglia ( n ) ) ; // . . . v e r i f i c o s e un nodo . . .
; // . . . ed e s c o con r i s u l t a t o p o s i t i v o .
//E ' i n f a t t i i n u t i l e p r o c e d e r e v e r s o i l b a s s o .

return true

else // Se non l ' ho t r o v a t o , c e r c o


if ( e l > n>e l )
return _CercaNodo ( n>des , e l ,
else
return _CercaNodo ( n>s i n , e l ,

pi in basso .
nodo ) ;
nodo ) ;

// Metodi p u b b l i c i
A 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 ,
_C e r c aF oglia ( r oot , e l , f o g l i a ) ;
}

bool
return

bool&

foglia )

const

bool A l b e r o B i n a r i o : : CercaNodo ( TElem e l , bool& nodo ) const


return _CercaNodo ( r oot , e l , nodo ) ;

SA.16 Operatore di Confronto


Traccia a pag. 25

// Metodo p r i v a t o
A l b e r o B i n a r i o : : _uguale (
PNodo& n1 ,
PNodo& n2 )
{
( 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
; // 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 .

bool
if
if

return true

const

const

const

( ( ! n1 | | ! n2 ) && ( n1 | | n2 ) ) // Se s o l o una d e l l e due rad . 0 (XOR) . . .


// . . . i due a l b e r i non sono u g u a l i
// ( p e r c h l ' a l t r a certamente non z e r o )

return false ;

// Appurato che nessuna d e l l e due r a d i c i punta a z e r o . . .


( n1>e l != n2>e l ) // . . . s e i due elem . p u n t a t i da n1 e n2 sono d i v e r s i . . .
;
// . . . a l l o r a i due a l b e r i non sono u g u a l i .

if

return false

//Dunque , abbiamo due a l b e r i non v u o t i e c o n t e n e n t i e l e m e n t i


// d i u g u a l e v a l o r e n e l l a r a d i c e .
// Bisogna ora c o n t r o l l a r e s e i l o r o s o t t o a l b e r i s i n i s t r o e
// d e s t r o sono u g u a l i : r i c o r s i o n e .
_uguale ( n1>s i n , n2>s i n ) && _uguale ( n1>des , n2>de s ) ;

return

SA. Soluzioni degli esercizi su alberi binari

89

// Metodo p u b b l i c o
AlberoBinario : :
==(
AlberoBinario& rhs )
{
// 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 .
_uguale ( r oot , r h s . r o o t ) ;
}

bool

operator const

const

return

SA.17 Conta Nodi non Foglia


Traccia a pag. 26

// 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


if ( ! n )
return 0 ;
unsigned int c ount = 0 ;

PNodo& n )

const

// 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
( n>s i n )
c ount = c ount + _ContaNodiNonFoglia ( n>s i n ) ;

if

// 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
( n>de s )
c ount = c ount + _ContaNodiNonFoglia ( n>de s ) ;

if

// 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
( n>s i n | | n>de s )
c ount++;

if

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 ) ;

SA.18 Conta Nodi


Traccia a pag. 26

// Metodo p r i v a t o
A l b e r o B i n a r i o : : _ContaNodi (

void
if

const PNodo& n , unsigned int& z e r o ,


unsigned int& uno , unsigned int& due ) const

(n) {
_ContaNodi ( n>s i n , z e r o , uno , due ) ;
_ContaNodi ( n>des , z e r o , uno , due ) ;

if ( n>s i n
due++;
else

&& n>de s )

SA. Soluzioni degli esercizi su alberi binari

if ( ! n>s i n
z e r o ++;
else
}

&& ! n>de s )

uno++;

// Metodo p u b b l i c o
A l b e r o B i n a r i o : : ContaNodi (

void

90

unsigned int&

zero ,

zero = 0;
uno = 0 ;
due = 0 ;
_ContaNodi ( r oot , z e r o , uno , due ) ;

unsigned int& uno ,


unsigned int& due ) const

SA.19 Conta Nodi Sottoalbero


Traccia a pag. 26

Il problema posto pu essere scomposto in due sottoproblemi:

individuare la radice del sottoalbero di cui contare i nodi;

contare i nodi del sottoalbero individuato.

Solo la prima delle due operazioni suddette dipende da quale dei due
metodi viene invocato, a dierenza della seconda che resta inalterata. Questa
considerazione suggerisce di aggiungere alla classe

AlberoBinario

i seguenti

metodi:

class A l b e r o B i n a r i o
private :

...

unsigned int _ContaNodi( const PNodo& n ) const ;


PNodo _CercaOccorrenzaMin ( const PNodo& n ,
const TElem& e l ) const ;
PNodo _CercaOccorrenzaMax ( const PNodo& n ,
const TElem& e l ) const ;
public :
...

};

unsigned int
unsigned int

Il metodo

ContaNodiSottoalb_Min ( const TElem& e l )


ContaNodiSottoalb_Max( const TElem& e l )

_ContaNodi()

di cui sia fornita la radice.

const ;
const ;

restituisce il numero di nodi di un sottoalbero


Il metodo

_CercaOccorrenzaMin()

restituisce

il puntatore al nodo avente valore specicato e posizionato pi in alto (livello minimo) all'interno di un albero di cui si fornisce la radice. Analogo

SA. Soluzioni degli esercizi su alberi binari


comportamento ha il metodo

91

_CercaOccorrenzaMax().

I due metodi pub-

blici svolgono le operazioni richieste basandosi sui metodi privati mostrati.

_CercaOccorrenzaMin(), ad esempio, invoca il


OccorrenzaMin() perch individui la radice del
invoca poi il metodo _ContaNodi().

metodo ricorsivo

_Cerca-

sottoalbero; su tale radice

Di seguito si riportano le implementazioni dei cinque metodi dichiarati.

// 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
A l b e r o B i n a r i o : : _ContaNodi (
PNodo& n )
(n)
1 + _ContaNodi ( n>s i n ) + _ContaNodi ( n>de s ) ;

unsigned int
if
return
else
return 0 ;

const

const

const

PNodo A l b e r o B i n a r i o : : _CercaOccorrenzaMin (
PNodo& n ,
TElem& e l )
{
// Cerca n e l l ' a l b e r o a v e n t e r a d i c e i n n l ' elemento i l c u i v a l o r e p a r i
// ad e l ed i l c u i l i v e l l o minimo . Ne r e s t i t u i s c e i l p u n t a t o r e .
(n) {
( n>e l == e l ) // Se sono i l nodo con l ' elemento c e r c a t o . . .
n ; // . . . r e s t i t u i s c o i l p u n t a t o r e a me s t e s s o . . .

const

if

}
}

const

if
return
else
if ( n>e l < e l ) // . . . a l t r i m e n t i c e r c o " p i
return _CercaOccorrenzaMin ( n>des , e l ) ;
else
return _CercaOccorrenzaMin ( n>s i n , e l ) ;
else
return 0 ;

gi"

const

PNodo A l b e r o B i n a r i o : : _CercaOccorrenzaMax (
PNodo& n ,
TElem& e l )
{
// Cerca n e l l ' a l b e r o a v e n t e r a d i c e i n n l ' elemento i l c u i v a l o r e p a r i
// ad e l ed i l c u i l i v e l l o massimo . Ne r e s t i t u i s c e i l p u n t a t o r e .
(n) {
PNodo r e s u l t ;
( n>e l < e l ) // Cerco prima " p i g i "
r e s u l t = _CercaOccorrenzaMax ( n>des , e l ) ;

const
if

const

if
else

r e s u l t = _CercaOccorrenzaMax ( n>s i n , e l ) ;

}
}

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
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
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


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 ;

l ' elem . c e r c a t o .
stesso . . .

TElem& e l )

const

SA. Soluzioni degli esercizi su alberi binari

92

unsigned int A l b e r o B i n a r i o : : ContaNodiSottoalb_Max ( const


PNodo n = _CercaOccorrenzaMax ( r oot , e l ) ;
if ( n ) //C ' almeno un elemento p a r i ad e l ?
return _ContaNodi ( n ) ;
else
return 0 ;
}

TElem& e l )

const

Capitolo SP
Soluzioni degli esercizi su pile
SP.1 Push Greater
Traccia a pag. 28

#include <i o s t r e a m>


#include <s t d l i b . h>
using namespace s t d ;
typedef int TElem ;
struct Record ;
typedef Record PRec ;
typedef struct Record
};

TElem e l ;
PRec s u c c ;

class P i l a {
private :
PRec top ;
int nelem ;
public :
P i l a ( unsigned int
~Pila ( ) ;

void
bool

};

p = 0);

const
const
const

Push (
TElem& e ) ;
PushGreater (
TElem& e ) ;
TElem Top ( )
;
TElem Pop ( ) ;
Svuota ( ) ;
Count ( )
;
Empty ( )
;

void
unsigned int
const
bool
const

P i l a : : P i l a ( ) : top ( 0 ) , nelem ( 0 ) {
}
Pila ::~ Pila () {
Svuota ( ) ;
}
93

SP. Soluzioni degli esercizi su pile

void

const

P i l a : : Push (
TElem& e ) {
PRec p =
Record ;
p>e l = e ;
p>s u c c = top ;
top = p ;
nelem++;

bool
if
}
}

new

const

P i l a : : PushGreater (
TElem& e ) {
( Empty ( ) | | ( e > Top ( ) ) ) {
Push ( e ) ;
;

return true
else
return false ;

const

TElem P i l a : : Top ( )
( top )
top >e l ;

if

94

return

// q u e s t o metodo r e s t i t . un v a l o r e non s p e c i f . n e l caso l a p i l a s i a vuota

TElem P i l a : : Pop ( ) {
( 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

if

// 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
p ; // e l i m i n a l a v e c c h i a t e s t a

delete

}
}

nelem ;
e;

return

// q u e s t o metodo r e s t i t . un v a l o r e non s p e c i f . 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 ;
top = top >s u c c ;
p;

delete

}
nelem = 0 ;

unsigned int P i l a : : Count ( ) const


return nelem ;
}

bool P i l a : : Empty ( ) const


return ( nelem == 0 ) ;

void
void
void
void
void

stampaMenu ( ) ;
Push ( P i l a& p ) ;
PushGreater ( P i l a& p ) ;
Top ( P i l a& p ) ;
Pop ( P i l a& p ) ;

SP. Soluzioni degli esercizi su pile

void Svuota ( P i l a& p ) ;


void Count ( P i l a& p ) ;
void Empty ( P i l a& p ) ;
int main ( )
{
char c ;
Pila pila ;

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
break ;
}
} while ( c != ' 8 ' ) ;
return 0 ;

void

v a l i d a . \ n" ;

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 : " ;

void

Push ( P i l a& p ) {

95

SP. Soluzioni degli esercizi su pile

96

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 ) ;

void

PushGreater ( P i l a& p ) {
TElem e l ;
c out << " I n s e r i r e e le me nt o : " ;
c i n >> e l ;
( p . PushGreater ( e l ) )
c out << " Elemento i n s e r i t o . \ n" ;

if
else

c out << " Elemento non i n s e r i t o . \ n" ;

void Top ( P i l a& p ) {


if ( ! p . Empty ( ) )
c out << " Elemento
else

d i t e s t a : " << p . Top ( ) << e n d l ;

c out << " P i l a vuota . " << e n d l ;

void Pop ( P i l a& p ) {


if ( ! p . Empty ( ) )
c out << " Elemento
else

d i t e s t a : " << p . Pop ( ) << e n d l ;

c out << " P i l a vuota . " << e n d l ;

void
}

Svuota ( P i l a& p ) {
p . Svuota ( ) ;
c out << " P i l a s v u o t a t a . \ n" ;

void
}

Count ( P i l a& p ) {
c out << "Numero e l e m e n t i : " << p . Count ( ) << e n d l ;

void Empty ( P i l a& p ) {


if ( p . Empty ( ) )
c out << " True . " <<
else
}

endl ;

c out << " F a l s e . " << e n d l ;

SP.2 Push If
Traccia a pag. 29

Nella parte privata della classe sono dichiarati i seguenti membri:

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 costruttore 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


come una classica

Push().

_Push()

implementato

Di seguito si riporta l'implementazione dei metodi richiesti dalla traccia.

unsigned int

Pila : : Pila (
maxpush ) :
top ( 0 ) , nelem ( 0 ) , _maxpush( maxpush ) , _currpush ( 0 ) {
}

void

bool
if
}
}

const

P i l a : : _Push (
TElem& e ) {
// C l a s s i c a Push ( ) i n una p i l a : metodo p r i v a t o
PRec p =
Record ;
p>e l = e ;
p>s u c c = top ;
top = p ;
nelem++;

new

const

P i l a : : Push (
TElem& e ) {
( _currpush < _maxpush) {
_Push ( e ) ; // I n s e r i s c e i n c o n d i z i o n a t a m e n t e n e l l a p i l a
_currpush++;
;

return true

return false ;

TElem P i l a : : Pop ( ) {
( 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 ;

if

// 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
p ; // e l i m i n a l a v e c c h i a t e s t a

delete

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
e;

return

// 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


top = top >s u c c ;
p;

delete

}
nelem = 0 ;
_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

98

Capitolo SC
Soluzioni degli esercizi su code
SC.1 Coda
Traccia a pag. 31

#include <i o s t r e a m>


#include <s t d l i b . h>
using namespace s t d ;
typedef int TElem ;
struct Record ;
typedef Record PRec ;
typedef struct Record
};

TElem e l ;
PRec s u c c ;

class Coda
private :

PRec head ;
PRec t a i l ;
nelem ;
:
Coda ( ) ;
~Coda ( ) ;

int
public

void

};

const
const
const
void
unsigned int
const
bool
const

Push (
TElem& e ) ;
TElem Top ( )
;
TElem Pop ( ) ;
TElem Somma ( )
;
Svuota ( ) ;
Count ( )
;
Empty ( )
;

Coda : : Coda ( ) : head ( 0 ) , t a i l ( 0 ) , nelem ( 0 ) {


}
Coda : : ~ Coda ( ) {
Svuota ( ) ;
99

SC. Soluzioni degli esercizi su code

100

void

const
new

Coda : : Push (
TElem& e ) {
// Creo un nuovo elemento n e l l ' heap
PRec temp =
Record ;
temp>e l = e ;
temp>s u c c = 0 ;

// s e c ' un elemento d i coda q u e s t o deve puntare a l nuovo elemento


( tail )
t a i l >s u c c = temp ;

if

// i n o g n i caso l a coda punter a l nuovo elemento


t a i l = temp ;
// s e l a t e s t a non punta ad un elemento , deve puntare a l nuovo elemento :
// l a coda , c i o , era vuota a l momento d e l l ' i n s e r i m e n t o
( ! head )
head = temp ;

if

nelem++;

const

TElem Coda : : Top ( )


( head )
head >e l ;
}

if

return

TElem Coda : : Pop ( ) {


( head ) {
PRec temp = head ;
TElem el_temp = temp>e l ;

if

// head passa a puntare a l l ' elemento s u c c e s s i v o


head = head >s u c c ;
// s e non punta a n i e n t e v u o l e d i r e che l a coda conteneva un s o l o elem .
// anche t a i l q u i n d i deve puntare a 0
( ! head )
t a i l = 0;

if

nelem ;
temp ;
el_temp ;

delete
return

const

TElem Coda : : Somma( )


{
TElem sum = 0 ;
( PRec temp = head ; temp != 0 ; temp = temp>s u c c )
sum = sum + temp>e l ;

for

return

sum ;

void Coda : : Svuota ( )


while ( head != 0)
}

{
{

PRec tbd = head ;


head = head >s u c c ;
tbd ;

delete

SC. Soluzioni degli esercizi su code

head = t a i l = 0 ;
nelem = 0 ;

unsigned int Coda : : Count ( ) const


return nelem ;

bool Coda : : Empty ( ) const


return ( 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
break ;
}
} while ( c != ' 8 ' ) ;
return 0 ;

non v a l i d a . \ n" ;

101

SC. Soluzioni degli esercizi su code


}

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 : " ;

void
}

Push ( Coda& c ) {
TElem e l ;
c out << " I n s e r i r e e le me nt o : " ;
c i n >> e l ;
c . Push ( e l ) ;

void Top ( Coda& c ) {


if ( ! c . Empty ( ) )
c out << " Elemento
else

d i t e s t a : " << c . Top ( ) << e n d l ;

c out << "Coda vuota . " << e n d l ;

void Pop ( Coda& c ) {


if ( ! c . Empty ( ) )
c out << " Elemento
else

d i t e s t a : " << c . Pop ( ) << e n d l ;

c out << "Coda vuota . " << e n d l ;

void
}

Somma( Coda& c ) {
c out << "Somma e l e m e n t i : " << c . Somma( ) << e n d l ;

void
}

Svuota ( Coda& c ) {
c . Svuota ( ) ;
c out << "Coda s v u o t a t a . \ n" ;

void
}

Count ( Coda& c ) {
c out << "Numero e l e m e n t i : " << c . Count ( ) << e n d l ;

void Empty ( Coda& c ) {


if ( c . Empty ( ) )
c out << " True . " <<
else
}

endl ;

c out << " F a l s e . " << e n d l ;

102

SC. Soluzioni degli esercizi su code

103

SC.2 Coda con Perdite


Traccia a pag. 32

#include <i o s t r e a m>


#include <s t d l i b . h>
using namespace s t d ;
typedef int TElem ;
struct Record ;
typedef Record PRec ;
typedef struct Record
};

TElem e l ;
PRec s u c c ;

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
const
unsigned int
void
unsigned int
const
bool
const

Push (
TElem& e ) ;
TElem Top ( )
;
TElem Pop ( ) ;
TElem Pop (
n);
Svuota ( ) ;
Count ( )
;
Empty ( )
;

Coda : : Coda (
}

unsigned int

_post i ) : head ( 0 ) , t a i l ( 0 ) , p o s t i ( _post i ) , nelem ( 0 ) {

Coda : : ~ Coda ( ) {
Svuota ( ) ;
}

bool
if

const

Coda : : Push (
TElem& e ) {
( nelem == p o s t i )
;

return false

// Creo un nuovo elemento n e l l ' heap


PRec temp =
Record ;
temp>e l = e ;
temp>s u c c = 0 ;

new

// s e c ' un elemento d i coda q u e s t o deve puntare a l nuovo elemento


( tail )
t a i l >s u c c = temp ;

if

// i n o g n i caso l a coda punter a l nuovo elemento


t a i l = temp ;
// s e l a t e s t a non punta ad un elemento , deve puntare a l nuovo elemento :

SC. Soluzioni degli esercizi su code

104

// l a coda , c i o , era vuota a l momento d e l l ' i n s e r i m e n t o


( ! head )
head = temp ;

if

nelem++;
}

return true ;
const

TElem Coda : : Top ( )


( head )
head >e l ;
}

if

return

TElem Coda : : Pop ( ) {


( head ) {
PRec temp = head ;
TElem el_temp = temp>e l ;

if

// head passa a puntare a l l ' elemento s u c c e s s i v o


head = head >s u c c ;
// s e non punta a n i e n t e v u o l e d i r e che l a coda conteneva un s o l o elem .
// anche t a i l q u i n d i deve puntare a 0
( ! head )
t a i l = 0;

if

nelem ;
temp ;
el_temp ;

delete
return

unsigned int

TElem Coda : : Pop (


( head ) {
TElem e l = Pop ( ) ;

if

n) {

// e s t r a z i o n e d e i r e s t a n t i e l e m e n t i : s i usa i l metodo Pop ( ) ;


(
i = 2 ; ( i <= n ) && head ; i ++)
Pop ( ) ;

for int

return

el ;

void Coda : : Svuota ( )


while ( head != 0)
}

{
{

PRec tbd = head ;


head = head >s u c c ;
tbd ;

delete

head = t a i l = 0 ;
nelem = 0 ;

unsigned int Coda : : Count ( ) const


return nelem ;
}

bool Coda : : Empty ( ) const


return ( nelem == 0 ) ;

SC. Soluzioni degli esercizi su code


}

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
break ;
}
} while ( c != ' 8 ' ) ;
return 0 ;

void

non v a l i d a . \ n" ;

stampaMenu ( ) {
c out << e n d l ;
c out << " 1 . Push" << e n d l ;

105

SC. Soluzioni degli esercizi su code

c out
c out
c out
c out
c out
c out
c out
c out
c out

<<
<<
<<
<<
<<
<<
<<
<<
<<

" 2 . Top" << e n d l ;


" 3 . Pop" << e n d l ;
" 4 . PopMany" << e n d l ;
" 5 . Svuota " << e n d l ;
" 6 . Count " << e n d l ;
" 7 . Empty" << e n d l ;
" 8 . E s c i " << e n d l ;
endl ;
" Scelta : " ;

void

Push ( Coda& c ) {
TElem e l ;
c out << " I n s e r i r e e le me nt o : " ;
c i n >> e l ;
( c . Push ( e l ) )
c out << " Elemento i n s e r i t o . \ n" ;

if
else

c out << " Elemento NON i n s e r i t o . \ n" ;

void Top ( Coda& c ) {


if ( ! c . Empty ( ) )
c out << " Elemento
else

d i t e s t a : " << c . Top ( ) << e n d l ;

c out << "Coda vuota . " << e n d l ;

void Pop ( Coda& c ) {


if ( ! c . Empty ( ) )
c out << " Elemento
else

d i t e s t a : " << c . Pop ( ) << e n d l ;

c out << "Coda vuota . " << e n d l ;

void PopMany( Coda&


int i ;

c) {

c out << " Quanti e l e m e n t i e s t r a r r e ? " ;


c i n >> i ;

if ( ! c . Empty ( ) )
c out << " Elemento
else

d i t e s t a : " << c . Pop ( i ) << e n d l ;

c out << "Coda vuota . " << e n d l ;

void
}

Svuota ( Coda& c ) {
c . Svuota ( ) ;
c out << "Coda s v u o t a t a . \ n" ;

void
}

Count ( Coda& c ) {
c out << "Numero e l e m e n t i : " << c . Count ( ) << e n d l ;

void Empty ( Coda& c ) {


if ( c . Empty ( ) )
c out << " True . " <<
else
}

endl ;

c out << " F a l s e . " << e n d l ;

106

SC. Soluzioni degli esercizi su code

107

SC.3 Coda a Priorit


Traccia a pag. 33

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 elementi 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 comprende gli elementi a priorit bassa.

Una o entrambe queste sotto-sequenze possono in generale essere vuote.


Dal momento che le operazioni di prelievo (Pop()) e di inserimento a bassa

priorit (PushLow()) corrispondono in questo caso alle normali operazioni


usate nel caso di una classica coda, l'unica operazione nuova da implementare
consiste nell'inserimento in coda di un elemento a priorit alta (PushHigh()).
Tale operazione prevede l'aggiunta di un elemento in coda agli elementi a
priorit alta. In quest'ottica risulta utile denire un puntatore

aggiuntivo

posizionato sull'ultimo degli elementi a priorit alta. Tale nuovo puntatore


punter alla coda degli elementi ad alta priorit, oppure varr zero in caso
di assenza di tali elementi.

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

t
Figura SC.1:

108

Una sequenza di elementi formata da due sotto-sequenze

consecutive

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
Push (
TElem& e ) ; // c l a s s i c o Push i n coda
:
PriorityQueue ( ) ;
~PriorityQueue ( ) ;

void
public

};

const

void PushLow ( const TElem& e ) ;


void PushHigh ( const TElem& e ) ;
TElem Pop ( ) ;
void C l e a r ( ) ;
bool Empty ( ) const ;
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 =
Record ;
temp>e l = e ;
temp>s u c c = 0 ;

new

// s e c ' un elemento d i coda q u e s t o deve puntare a l nuovo elemento


( tail )
t a i l >s u c c = temp ;

if

// i n o g n i caso l a coda punter a l nuovo elemento


t a i l = temp ;
// s e l a t e s t a non punta ad un elemento , deve puntare a l nuovo elemento :
// l a s t r u t t u r a , c i o , era vuota a l momento d e l l ' i n s e r i m e n t o

SC. Soluzioni degli esercizi su code

if
}

( ! head )
head = temp ;

void
}

109

const

P r i o r i t y Q u e u e : : PushLow (
TElem& e ) {
Push ( e ) ; // s i r i d u c e ad un c l a s s i c o i n s e r i m e n t o i n coda

void
if

P r i o r i t y Q u e u e : : PushHigh (
( ! tail_h ) {

const

TElem& e ) {

//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
( ! head ) // l a coda vuota ?
Push ( e ) ; // i n s e r i s c o con Push ( )
{
PRec temp =
Record ;
temp>e l = e ;
temp>s u c c = head ;
head = temp ;
}

if
else

new

t a i l _ h = head ; // l ' elemento i n s e r i t o i n t e s t a : t a i l _ h deve p u n t a r v i


}

else

{
// i n s e r i s c o
PRec temp =
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 ;

new

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
( ! t ail_h >s u c c )
t a i l = tail_h ;

if

TElem P r i o r i t y Q u e u e : : Pop ( ) {
( head ) {
PRec temp = head ;
TElem el_temp = temp>e l ;

if

if

( head == t a i l _ h ) // ho p r e l e v a t o l ' unico elemento a p r i o r i t a l t a ?


tail_h = 0;
// a l l o r a non ce ne sono p i

// head passa a puntare a l l ' elemento s u c c e s s i v o


head = head >s u c c ;
// s e non punta a n i e n t e v u o l e d i r e che l a coda conteneva un s o l o elem .
// anche t a i l q u i n d i deve puntare a 0
( ! head ) {
t a i l = 0;
tail_h = 0;
}

if

delete
return

temp ;
el_temp ;

SC. Soluzioni degli esercizi su code

110

CODA A PRIORIT

SOTTO-CODA AD
ALTA PRIORIT

SOTTO-CODA A
BASSA PRIORIT

Figura SC.2: Coda a priorit formata da due classiche code aancate

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 ;
tbd ;

delete

head = t a i l = t a i l _ h = 0 ;

bool P r i o r i t y Q u e u e : : Empty ( ) const


return ! head ;

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
Il metodo

PushHigh(),

PushLow()

accoda nella coda a bassa priorit.

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-

Coda (vedi EC.1). Denendo tali


PriorityQueue esse non risulteran-

de aancate risultano istanze della classe


istanze come membri privati della classe

no visibili dall'esterno della struttura (information hiding ), la quale continuer 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

const P r i o r i t y Q u e u e& c ) ; // i n i b i s c e
operator=( const P r i o r i t y Q u e u e& c ) ;

PriorityQueue (
P r i o r i t y Q u e u e&
:
PriorityQueue ( ) ;

public

};

void PushLow ( const TElem& e ) ;


void PushHigh ( const TElem& e ) ;
TElem Pop ( ) ;
void C l e a r ( ) ;
bool Empty ( ) const ;

#include " p r i o r i t y q u e u e . h"


void P r i o r i t y Q u e u e : : PushLow ( const
}

coda_l . Push ( e ) ;

void
}

la copia . . .
// . . e l ' a s s e g n a z i o n e

P r i o r i t y Q u e u e : : PushHigh (
coda_h . Push ( e ) ;

const

TElem& e ) {

TElem& e ) {

TElem P r i o r i t y Q u e u e : : Pop ( ) {
( ! coda_h . Empty ( ) )
coda_h . Pop ( ) ;
}

if
return
else
return

coda_l . Pop ( ) ;

void
}

PriorityQueue : : Clear () {
coda_h . Svuota ( ) ;
coda_l . Svuota ( ) ;

bool P r i o r i t y Q u e u e : : Empty ( ) const {


return ( coda_h . Empty ( ) && coda_l . Empty ( ) ) ;

Approccio 3
La coda a priorit pu essere una normale coda in cui i record, disposti

secondo l'ordine di inserimento, vengono etichettati con la loro priorit


di Figura SC.3).

PushLow(),
il metodo

In questo caso sia il metodo

PushHigh()

(ve-

che il metodo

previa opportuna etichettatura, eettuano un'aggiunta in coda.

Pop()

in questo caso a prendersi carico della restituzione del

giusto elemento. Tale operazione viene eettuata scorrendo tutta la struttura 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

Figura SC.3: Sequenza di elementi etichettati

Tale implementazione, pur prestandosi a diverse ottimizzazioni, non risulta particolarmente eciente, richiedendo un ciclo di ricerca per ogni operazione

Pop()

eettuata. La sua implementazione non qui riportata.

SC.4 PopMinMax
Traccia a pag. 34

// Metodo p r i v a t o
// I l metodo s e g u e n t e e s t r a e n e l e m e n t i e ne r e s t i t u i s c e i l min ed i l max
Coda : : _PopMinMax(
n , TElem& min , TElem& max) {
min = max = Pop ( ) ; // Assegno min e max a l l ' elemento d i t e s t a

void

unsigned int

unsigned int

i = 1;
// c o n f r o n t o con g l i a l t r i n1 e l e m e n t i s e g u e n t i : n1 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 )
( ( i < n ) && ! Empty ( ) ) {
TElem e l = Pop ( ) ;
( e l < min )
min = e l ;
( e l > max)
max = e l ;
i ++;
}

while
if
if
}

// Metodi p u b b l i c i
// I l metodo s e g u e n t e chiama _PopMinMax ( ) e r e s t i t u i s c e i l massimo
TElem Coda : : PopMax (
n) {
TElem min , max ;
_PopMinMax( n , min , max ) ;
max ;
}

unsigned int

return

// I l metodo s e g u e n t e chiama _PopMinMax ( ) e r e s t i t u i s c e i l minimo


TElem Coda : : PopMin (
n) {
TElem min , max ;
_PopMinMax( n , min , max ) ;
min ;
}

unsigned int

return

Capitolo SX
Soluzioni degli altri esercizi
SX.1 Accumulatore
Traccia a pag. 36

#include <i o s t r e a m>


using namespace s t d ;
class Accumulatore {
private :
float a ;
public :
Accumulatore ( ) { R e se t ( ) ; } ;
void Add( float v a l ) { a += v a l ;
void R e s e t ( ) { a = 0 ; } ;
float GetValue ( ) const { return
};

int

};
a ; };

main ( )

Accumulatore a ;
f;
ch ;

float
char
c out
c out
c out
c out

do

<<
<<
<<
<<

" 'a '


"'r '
"'s '
" 'e '

add \n" ;
r e s e t \n" ;
show \n" ;
e x i t \n" ;

{
c i n >> ch ;
( ch ) {
'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" ;
;
'r ':
a . Reset ( ) ;
c out << " R e se t . \ n" ;

switch
case

break
case

113

SX. Soluzioni degli altri esercizi

break ;
case ' s ' :
c out << "The
break ;
case ' e ' :
break ;
default :

v a l u e i s " << a . GetValue ( ) << e n d l ;

c out << " I n v a l i d command . \ n" ;

while ( ch
return 0 ;
}

114

!= ' e ' ) ;

Accumulatore vengono implementati direttamente nell'ambito del costrutto class. Questa tecnica parIn questo esercizio i metodi della classe

ticolarmente conveniente nel caso di metodi molto semplici (come questi costituiti da una sola riga), ed equivalente a rendere i metodi

inline attraverso

l'approccio classico alla stesura dei metodi di una classe e l'uso della keyword

inline.

SX.2 Cifratore
Traccia a pag. 36

#include <i o s t r e a m>


#include <s t d l i b . h>
using namespace s t d ;
class C i f r a t o r e {
private :
int c h i a v e ;
char C i f r a C a r a t t e r e ( char c , bool
public :
C i f r a t o r e ( int c ) ;
void C i f r a ( char s t r ) const ;
void D e c i f r a ( char s t r ) const ;

cifra )

const ;

};

Cifratore : : Cifratore (
}

int

c ) : chiave ( c ) {

char C i f r a t o r e : : C i f r a C a r a t t e r e ( char
if ( c i f r a )
return c + c h i a v e ;
else
return c c h i a v e ;

c,

void C i f r a t o r e : : C i f r a ( char
while ( s t r ) {

str )

s t r = C i f r a C a r a t t e r e ( str ,

s t r ++;

const {
true ) ;

bool

cifra )

const

SX. Soluzioni degli altri esercizi

void C i f r a t o r e : : D e c i f r a ( char
while ( s t r ) {
}

s t r ++;

const
false ) ;

str )

s t r = C i f r a C a r a t t e r e ( str ,

115

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 ) ;
c out << " S t r i n g a : " << s t r << e n d l ;
c . Cifra ( str ) ;
c out << " C i f r a t u r a : " << s t r << e n d l ;
c . Decifra ( str ) ;
c out << " D e c i f r a t u r a : " << s t r << e n d l ;

system ( "PAUSE" ) ;
0;

return

SX.3 Lista Della Spesa


Traccia a pag. 37

#include <i o s t r e a m>


using namespace s t d ;
const int MAX_CHARS = 2 0 ;
typedef char Nome [MAX_CHARS] ;
typedef float Quant it a ;
struct A r t i c o l o {
};

Nome n ;
Quant it a q ;

struct Record ;
typedef Record
struct Record {
};

PRec ;

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

bool _Elimina ( PRec& p , const Nome n ) ;


bool S t r i n g h e U g u a l i ( const char s1 , const char
return ( strcmp ( s1 , s2 ) == 0 ) ;

s2 )

const

// 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
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
= (
L i s t a D e l l a S p e s a &) { } ;
:
ListaDellaSpesa ( ) ;
~ListaDellaSpesa ( ) ;

const
void operator const
public

};

Quant it a A ggiungi ( const Nome n ,


bool E limina ( const Nome n ) ;
Quant it a GetQuantita ( const Nome
void Svuota ( ) ;
void Stampa ( ) const ;

Quant it a q ) ;
n)

const ;

ListaDellaSpesa : : ListaDellaSpesa ( ) : f i r s t (0) {


}
ListaDellaSpesa ::~ ListaDellaSpesa () {
Svuota ( ) ;
}

bool

const

const

ListaDellaSpesa : : Ricerca (
Nome n , PRec& p )
{
// Questo metodo c e r c a l ' a r t i c o l o a v e n t e i l nome s p e c i f i c a t o e r e s t i t u i s c e :
// t r u e o f a l s e , a seconda che l ' a r t i c o l o s i a s t a t o t r o v a t o o meno ;
// i l p u n t a t o r e a l l ' u l t i m o r e c o r d v i s i t a t o .
( first ) {
p = first ;
( S t r i n g h e U g u a l i ( p>a r t . n , n ) )
;
{
( p>s u c c ) {
p = p>s u c c ;
( S t r i n g h e U g u a l i ( p>a r t . n , n ) )
;
}
}
}

if

if
return true
else
while
if
return true

return false ;

bool
if

const

L i s t a D e l l a S p e s a : : _Elimina ( PRec& p ,
Nome n ) {
// metodo r i c o r s i v o d i e l i m i n a z i o n e d i un elemento d a l l a l i s t a
(p) {
( S t r i n g h e U g u a l i ( p>a r t . n , n ) ) {
PRec tbd = p ;
p = tbd >s u c c ;
tbd ;
;
}
}
}

if

delete
return true
else
return _Elimina ( p>suc c ,

return false ;

n);

SX. Soluzioni degli altri esercizi

Quant it a L i s t a D e l l a S p e s a : : Aggiungi (
(! first ) {
first =
Record ;
f i r s t >s u c c = 0 ;
s t r c p y ( f i r s t >a r t . n , n ) ;
f i r s t >a r t . q = q ;
q;
}
{
PRec p ;

if

new

117

const

Nome n , Quant it a q ) {

return
else
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 =
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

new

p>a r t . q ;

bool L i s t a D e l l a S p e s a : : Elimina ( const


return _Elimina ( f i r s t , n ) ;

Nome n ) {

Quant it a L i s t a D e l l a S p e s a : : GetQuantita (
PRec p ;
( Ricerca (n , p ))
p>a r t . q ;
}

if
return
else
return

void
if

const

Nome n )

0;

L i s t a D e l l a S p e s a : : Svuota ( ) {
( 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 L i s t a D e l l a S p e s a : : Stampa ( ) const


PRec p = f i r s t ;
while ( p ) {
}

c out << p>a r t . n << " : " << p>a r t . q << e n d l ;


p = p>s u c c ;

const

SX. Soluzioni degli altri esercizi

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" ;

void A ggiungi ( L i s t a D e l l a S p e s a & l ) ;


void E limina ( L i s t a D e l l a S p e s a& l ) ;
void GetQuantita ( L i s t a D e l l a S p e s a & l ) ;
void Svuota ( L i s t a D e l l a S p e s a& l ) ;
void Stampa ( L i s t a D e l l a S p e s a& 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 ) ;
int main ( )
{

ListaDellaSpesa l ;

int s c e l t a ;
do {

stampa_menu ( ) ;
c i n >> s c e l t a ;
( scelta ) {
1:
A ggiungi ( l ) ;
;
2:
E limina ( l ) ;
;
3:
GetQuantita ( l ) ;
;
4:
Svuota ( l ) ;
;
5:
Stampa ( l ) ;
;
6:
TestVeloce ( l ) ;
;
7:
;
:
c out << " S c e l t a non v a l i d a . \ n" ;
;
}
}
( s c e l t a != 7 ) ;

switch
case
break
case
break
case
break
case
break
case
break
case
break
case
break
default
break
while
return 0 ;

void

A ggiungi ( L i s t a D e l l a S p e s a & l ) {
Nome n ;
Quant it a q , qq ;
c out << "Nome a r t i c o l o : " ;
c i n >> n ;
c out << " Quant it a ' : " ;

118

SX. Soluzioni degli altri esercizi

119

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 ;

void

E limina ( L i s t a D e l l a S p e s a& l ) {
Nome n ;
c out << "Nome a r t i c o l o : " ;
c i n >> n ;

if ( l . E limina ( n ) )
c out << " A r t i c o l o
else

e l i m i n a t o . " << e n d l ;

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

GetQuantita ( L i s t a D e l l a S p e s a & l ) {
Nome n ;
Quant it a q ;
c out << "Nome a r t i c o l o : " ;
c i n >> n ;
q = l . GetQuantita ( n ) ;
c out << "La q u a n t i t a ' e ' " << q << e n d l ;

void
}

Svuota ( L i s t a D e l l a S p e s a& l ) {
l . Svuota ( ) ;
c out << " L i s t a s v u o t a t a . " << e n d l ;

void
}

Stampa ( L i s t a D e l l a S p e s a& l ) {
c out << " L i s t a : " << e n d l ;
l . Stampa ( ) ;

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 ( ) ;

SX.4 Predittore di Temperatura


Traccia a pag. 38

Il metodo

EstimateTemp()

deve eettuare un'estrapolazione lineare della

temperatura basandosi sui dati delle ultime due letture comunicate.


formula da utilizzare la seguente:

La

SX. Soluzioni degli altri esercizi

120

T2 T1
(t t1 ) + T1 ;
T =
t2 t1
dove

la stima della temperatura all'istante

t; T1 , T2 , t1

t2

sono

le ultime due letture della temperatura ed i relativi due istanti di lettura,


rispettivamente.

N.B.: Variando l'implementazione del metodo EstimateTemp() (ed eventualmente la


sezione private della classe) diviene possibile operare stime pi accurate della temperatura; si potrebbe per esempio pensare di operare estrapolazioni di ordine superiore al primo.
Per giunta ci, non alterando l'interfaccia della classe, non avrebbe alcuna ripercussione
sui moduli utenti del predittore.

#include <i o s t r e a m>


#include <s t d l i b . h>
using namespace s t d ;
typedef int Time ;
typedef float Temp ;
class TempPredictor {
private :
Time
Time
Temp
Temp

t ime 1 ;
t ime 2 ;
temp1 ;
temp2 ;

public :
TempPredictor ( Time time , Temp temp ) ;
void SetTemp ( Time time , Temp temp ) ;
Temp EstimateTemp ( Time time ) const ;
};

TempPredictor : : TempPredictor ( Time time , Temp temp ) :


t ime 1 ( time 1) , t ime 2 ( time ) , temp1 ( temp ) , temp2 ( temp ) {
// Impostare i n q u e s t o modo l e temp . ed i tempi s i g n i f i c a imporre che l e
// u l t i m e _due_ l e t t u r e d e l l a temperatura hanno f o r n i t o un r i s u l t . p a r i a temp
// e su q u e s t e u l t i m e due l e t t u r e b i s o g n a e s t r a p o l a r e l a stima .
}

void
}

TempPredictor : : SetTemp ( Time time , Temp temp ) {


t ime 1 = t ime 2 ; // " s p o s t a " l ' u l t i m a l e t t u r a n e l l a penultima
temp1 = temp2 ;
t ime 2 = time ; // a g g i o r n a l ' u l t i m a l e t t u r a con i d a t i proven . d a l l ' u t e n t e
temp2 = temp ;

const

Temp TempPredictor : : EstimateTemp ( Time time )


{
( ( temp2temp1 ) / ( time2 t ime 1 ) ) ( time t ime 1 ) + temp1 ;
}

return

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 ) ;
c out << " Stima : l a t e mpe r at ur a a l l ' i s t a n t e 10 s a r a ' "
<< tp . EstimateTemp ( 1 0 ) << e n d l ;
c out << " Stima : l a t e mpe r at ur a a l l ' i s t a n t e 20 s a r a ' "
<< tp . EstimateTemp ( 2 0 ) << e n d l ;
c out << " L e t t u r a : a l l ' i s t a n t e 5 : l a t e mpe r at ur a v a l e 16\ n" ;

//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 ) ;
c out << " Stima : l a t e mpe r at ur a a l l ' i s t a n t e 10 s a r a ' "
<< tp . EstimateTemp ( 1 0 ) << e n d l ;
c out << " Stima : l a t e mpe r at ur a a l l ' i s t a n t e 12 s a r a ' "
<< tp . EstimateTemp ( 1 2 ) << e n d l ;
c out << " L e t t u r a : a l l ' i s t a n t e 1 0 : l a t e mpe r at ur a v a l e 16\ n" ;

//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 ) ;
c out << " Stima : l a t e mpe r at ur a a l l ' i s t a n t e 15 s a r a ' "
<< tp . EstimateTemp ( 1 5 ) << e n d l ;
c out << " Stima : l a t e mpe r at ur a a l l ' i s t a n t e 20 s a r a ' "
<< tp . EstimateTemp ( 2 0 ) << e n d l ;

system ( "PAUSE" ) ;
0;

return

SX.5 Contenitore
Traccia a pag. 39

#include <i o s t r e a m>


using namespace s t d ;
const int NMAX = 5 0 ;
typedef char Nome [NMAX] ;
typedef int Peso ; // s i t r a t t i
struct Oggetto {
};

Nome n ;
Peso p ;

struct C e l l a ;
typedef C e l l a
struct C e l l a {
};

P C e lla ;

Oggetto elem ;
P C e lla s u c c ;

class

Contenitore {

i l peso come v a l o r e i n t e r o ( p . e s . grammi )

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 ;
nelem ;
:
C o n t e n i t o r e ( Peso max ) ;
~Contenitore ( ) ;

unsigned int
public
bool
void

char

n , Peso p ) ;
Inserisci (
Svuota ( ) ;
Peso P e s oC omple ssiv o ( )
;
Peso P e s oR e s iduo ( )
;
NumElem ( )
;
Stampa ( )
;

unsigned int
void
const

};

const
const
const

C o n t e n i t o r e : : C o n t e n i t o r e ( Peso max ) : f i r s t ( 0 ) , c a p a c i t a ( max ) ,


somma_pesi ( 0 ) , nelem ( 0 ) {
}
Contenitore : : ~ Contenitore () {
Svuota ( ) ;
}

bool
if

char

n , Peso p ) {
Contenitore : : I n s e r i s c i (
( p <= c a p a c i t a somma_pesi ) {
P C e lla c =
Cella ;
s t r c p y ( c>elem . n , n ) ;
c>elem . p = p ;
c>s u c c = f i r s t ;
first = c;

new

somma_pesi = somma_pesi + p ; // i l c o n t e n i t o r e ora p i p e s a n t e d i p . . .


nelem++; // . . . e c ' un elemento i n p i .
}
}

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 ;
tbd ;

delete

somma_pesi = 0 ;
nelem = 0 ;

Peso C o n t e n i t o r e : : P e soC omple ssiv o ( )


somma_pesi ;
}

return

Peso C o n t e n i t o r e : : P e soR e siduo ( )


c a p a c i t a somma_pesi ;
}

return

unsigned int

const

const

C o n t e n i t o r e : : NumElem ( )

const

SX. Soluzioni degli altri esercizi

return

nelem ;

void C o n t e n i t o r e : : Stampa ( ) const


P C e lla p = f i r s t ;
while ( p ) {
}

void
void
void
void
void
void
void

c out << p>elem . n << " , " << p>elem . p << e n d l ;


p = p>s u c c ;

I n s e r i s c i ( Contenitore& c ) ;
Svuota ( C o n t e n i t o r e & c ) ;
P e s oC omple s s iv o ( C o n t e n i t o r e & c ) ;
P e s oR e s iduo ( C o n t e n i t o r e & c ) ;
NumeroElementi ( C o n t e n i t o r e & c ) ;
Stampa ( C o n t e n i t o r e & c ) ;

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

123

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 ;
( scelta ) {
1:
Inserisci (c );
;
2:
Svuota ( c ) ;
;
3:
P e s oC omple s siv o ( c ) ;
;
4:
P e s oR e s iduo ( c ) ;
;
5:
NumeroElementi ( c ) ;
;
6:
Stampa ( c ) ;
;
7:
;
:
c out << " S c e l t a non v a l i d a . \ n" ;

switch
case
break
case
break
case
break
case
break
case
break
case
break
case
break
default

SX. Soluzioni degli altri esercizi

break ;
} while ( s c e l t a
return 0 ;
}

124

!= 7 ) ;

void I n s e r i s c i ( C o n t e n i t o r e &
char n [NMAX] ;

c) {

Peso p ;

c out << " I n s e r i s c i nome e le me nt o : " ;


c i n >> n ;
c out << " I n s e r i s c i pe so e le me nt o : " ;
c i n >> p ;
( c . I n s e r i s c i (n , p ))
c out << " Elemento i n s e r i t o . \ n" ;

if
else

c out << " Elemento NON i n s e r i t o . \ n" ;

void
}

Svuota ( C o n t e n i t o r e & c ) {
c . Svuota ( ) ;
c out << " C o n t e n i t o r e s v u o t a t o . \ n" ;

void
}

P e s oC omple s s iv o ( C o n t e n i t o r e & c ) {
c out << " I l pe s o c o m p l e s s i v o e ' : " << c . Pe soC omple ssiv o ( ) << e n d l ;

void
}

P e s oR e s iduo ( C o n t e n i t o r e & c ) {
c out << " I l pe s o r e s i d u o e ' : " << c . Pe soR e siduo ( ) << e n d l ;

void
}

NumeroElementi ( C o n t e n i t o r e & c ) {
c out << "N. Elem : " << c . NumElem ( ) << e n d l ;

void
}

Stampa ( C o n t e n i t o r e & c ) {
c out << " I l c o n t e n u t o d e l c o n t e n i t o r e e ' : \ n" ;
c . Stampa ( ) ;
c out << e n d l ;

SX.6 Lista Prenotazioni


Traccia a pag. 41

#include <i o s t r e a m>


using namespace s t d ;
const int MAX_CHARS = 2 0 ;
typedef int M a t r i c o l a ;
typedef char Nome [ 3 0 ] ;
struct P r e n o t a z i o n e {
M a t r i c o l a mat ;

SX. Soluzioni degli altri esercizi

};

125

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 .
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 ) ;

dinamicam . a l l o c a t o

~ListaPrenotazioni ( ) ;

};

bool P r e not a ( M a t r i c o l a m, Nome n ) ;


bool 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 G e t P o s t i D i s p o n i b i l i ( ) const ;
bool 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 ;
void Svuota ( ) ;
void Stampa ( ) ;

ListaPrenotazioni : : ListaPrenotazioni (
pv =
Prenotazione [ posti ] ;
}

new

int

n ) : p o s t i ( n ) , nelem ( 0 ) {

ListaPrenotazioni ::~ ListaPrenotazioni () {


[ ] pv ;
}

delete

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;

bool
if

L i s t a P r e n o t a z i o n i : : Pr e not a ( M a t r i c o l a m, Nome n ) {
( ( G e t P o s t i D i s p o n i b i l i ( ) > 0) && ( ! E s i s t e P r e n o t a z i o n e (m) ) ) {
pv [ nelem ] . mat = m;
s t r c p y ( pv [ nelem ] . nom , n ) ;
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" ;

void P r e not a ( L i s t a P r e n o t a z i o n i& l ) ;


void E limina ( L i s t a P r e n o t a z i o n i& l ) ;
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 ) ;
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 ) ;
void Svuota ( L i s t a P r e n o t a z i o n i& l ) ;
void Stampa ( L i s t a P r e n o t a z i o n i& l ) ;
int main ( )
{
int n ;

c out << " I n s e r i r e i l numero d i p o s t i d i s p o n i b i l i : " ;


c i n >> n ;
ListaPrenotazioni l (n ) ;

int s c e l t a ;
do {

stampa_menu ( ) ;
c i n >> s c e l t a ;
( scelta ) {
1:
P r e not a ( l ) ;
;
2:
E limina ( l ) ;
;
3:
GetPostiDisponibili ( l );
;
4:

switch
case
break
case
break
case
break
case

SX. Soluzioni degli altri esercizi


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
break ;
}
} while ( s c e l t a != 7 ) ;
return 0 ;

v a l i d a . \ n" ;

void

P r e not a ( 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;
Nome n ;
c out << " I n s e r i s c i M a t r i c o l a : " ;
c i n >> m;
c out << " I n s e r i s c i nome : " ;
c i n >> n ;

if ( l . P r e not a (m, n ) )
c out << " P r e n o t a z i o n e
else

e f f e t t u a t a . \ n" ;

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" ;

void

E limina ( 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;

c out << " I n s e r i s c i M a t r i c o l a : " ;


c i n >> m;

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;

c out << " I n s e r i s c i M a t r i c o l a : " ;


c i n >> 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" ;

127

SX. Soluzioni degli altri esercizi

128

void
}

Svuota ( L i s t a P r e n o t a z i o n i& l ) {
l . Svuota ( ) ;
c out << " L i s t a s v u o t a t a . \ n" ;

void
}

Stampa ( L i s t a P r e n o t a z i o n i& l ) {
l . Stampa ( ) ;

SX.7 Classica
Traccia a pag. 42

#include <i o s t r e a m>


#include <s t r i n g . h>
using namespace s t d ;
const int NMAX = 5 0 ;
typedef char Nome [NMAX] ;
struct Record ;
typedef Record PRec ;
typedef struct {
Nome n ;
unsigned int p u n t e g g i o ;
} Squadra ;

typedef Squadra
struct Record {
};

TElem e l ;
PRec s u c c ;

TElem ;

// 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

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 ();

};

unsigned int A ggiungi ( const


void Svuota ( ) ;
void Stampa ( ) const ;
unsigned int Count ( ) const ;

Nome& n ,

unsigned int

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 ) {

punti ) ;

SX. Soluzioni degli altri esercizi

129

}
Classifica ::~ Classifica () {
Svuota ( ) ;
}

unsigned int

const

C l a s s i f i c a : : Elimina (
Nome& n ) {
// Questo metodo e l i m i n a d a l l a s t r u t t u r a un e v e n t u a l e elem . a v e n t e nome p a r i
// ad n . In caso d i e s i s t e n z a ne r e s t i t u i s c e i l p u n t e g g i o , a l t r i m e n t i
// r e s t i t u i s c e 0 .

//E ' i l primo elemento ? ( Caso p a r t i c o l a r e )


( f i r s t && ( strcmp ( f i r s t >e l . n , n ) == 0 ) ) {
PRec tbd = f i r s t ;
f i r s t = f i r s t >s u c c ;
p u n t i = tbd >e l . p u n t e g g i o ;
tbd ;
nelem ;
punti ;
}

if

unsigned int
delete
return

//E ' un elemento s u c c e s s i v o a l primo ?


PRec p = f i r s t ;
( p && p>s u c c ) {
// c o n t r o l l o s e i l s u c c e s s i v o d i p deve e s s e r e e l i m i n a t o
( strcmp ( p>s uc c >e l . n , n ) == 0) {
PRec tbd = p>s u c c ;
p>s u c c = tbd >s u c c ;
p u n t i = tbd >e l . p u n t e g g i o ;
tbd ;
nelem ;
punti ;
}

while
if

unsigned int
delete
return

p = p>s u c c ;

// Elemento non t r o v a t o
0;

return

void

const

unsigned int

C l a s s i f i c a : : InserimentoOrdinato (
Nome& n ,
punti ) {
// Questo metodo e f f e t t u a un i n s e r i m e n t o o r d i n a t o n e l l a s t r u t t u r a , i n b a s e a l
//campo p u n t e g g i o . S i procede a t t r a v e r s o i s e g u e n t i p a s s i :
// s e l a l i s t a vuota s i i n s e r i s c e l ' elemento e s i e s c e ;
// s i c o n t r o l l a s e i n s e r i r e i n t e s t a : s e s , s i i n s e r i s c e e s i e s c e ;
// s i c e r c a i l punto d i i n s e r i m e n t o a t t r a v e r s o una v i s i t a , s i i n s e r i s c e
//
( e v e n t u a l m e n t e i n coda ) e s i e s c e .

// In o g n i caso a l l o c o un nuovo r e c o r d
PRec nuovo =
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++;

new

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 ;
}
{
// 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
( 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

else
if

SX. Soluzioni degli altri esercizi

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
if ( p u n t i >= p>suc c >e l . p u n t e g g i o ) {

p?

nuovo>s u c c = p>s u c c ;
p>s u c c = nuovo ;
;

return

130

p = p>s u c c ;

// Se sono qui , non ho ancora i n s e r i t o : i n s e r i m . i n coda , a l l a q u a l e punta p


p>s u c c = nuovo ;
nuovo>s u c c = 0 ;

unsigned int C l a s s i f i c a : : Aggiungi ( const Nome& n , unsigned int p u n t i ) {


unsigned int p = Elimina ( n ) ; // Elimina d a l l a l i s t a l ' elemento ( s e e s i s t e )
I n s e r i m e n t o O r d i n a t o ( n , p u n t i + p ) ; //Lo ( re ) i n s e r i s c e a l p o s t o g i u s t o
}

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 ;
tbd ;

delete

}
nelem = 0 ;

void C l a s s i f i c a : : Stampa ( ) const


PRec p = f i r s t ;
while ( p ) {
}

c out << p>e l . n << " : " << p>e l . p u n t e g g i o << e n d l ;


p = p>s u c c ;

unsigned int C l a s s i f i c a : : Count ( ) const


return nelem ;
}

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" ;

void
void
void
void

A ggiungi ( C l a s s i f i c a& l ) ;
Svuota ( C l a s s i f i c a& l ) ;
Stampa ( C l a s s i f i c a& l ) ;
Count ( C l a s s i f i c a& l ) ;

SX. Soluzioni degli altri esercizi

int

131

main ( )

Classifica l ;

int s c e l t a ;
do {

stampa_menu ( ) ;
c i n >> s c e l t a ;
( scelta ) {
1:
A ggiungi ( l ) ;
;
2:
Svuota ( l ) ;
;
3:
Stampa ( l ) ;
;
4:
Count ( l ) ;
;
5:
;
:
c out << " S c e l t a non v a l i d a . \ n" ;
;
}
}
( s c e l t a != 5 ) ;

switch
case
break
case
break
case
break
case
break
case
break
default
break
while
return 0 ;

void A ggiungi ( C l a s s i f i c a&


Nome n ;
unsigned int p u n t i ;

l) {

c out << " I n s e r i s c i nome : " ;


c i n >> n ;
c out << " I n s e r i s c i p u n t i : " ;
c i n >> p u n t i ;
c out << "La s q uadr a " << n << " or a ha p u n t i : " << l . Aggiungi ( n , p u n t i ) << " . \ n" ;

void
}

Svuota ( C l a s s i f i c a& l ) {
l . Svuota ( ) ;
c out << " C l a s s i f i c a s v u o t a t a . \ n" ;

void
}

Stampa ( C l a s s i f i c a& l ) {
l . Stampa ( ) ;
c out << e n d l ;

void
}

Count ( C l a s s i f i c a& l ) {
c out << " I l numero d i e l e m e n t i e ' : " << l . Count ( ) << e n d l ;

SX. Soluzioni degli altri esercizi

132

SX.8 Agenzia Matrimoniale


Traccia a pag. 43

#include <i o s t r e a m>


using namespace s t d ;
const int NMAX = 5 0 ;
typedef char Nome [NMAX] ;
struct p e r s o n a ;
typedef struct Persona {
Nome n ;
bool maschio ;
};

Persona c o n i u g e ;

typedef Persona
struct Record ;
typedef Record
struct Record {
};

//Nome Persona

TElem e l ;
PRec s u c c ;

TElem ;
PRec ;
// 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

class A ge nz iaMat r imoniale


private :

PRec f i r s t ;

A ge nz iaMat r imoniale ( const Age nz iaMat r imoniale &); // i n i b i s c e l a c o p i a da


void operator= ( const Age nz iaMat r imoniale &); // i n i b i s c e l ' a s s e g n a z i o n e
PRec Cerca (Nome n ) const ;
public :
A ge nz iaMat r imoniale ( ) ;
~ A ge nz iaMat r imoniale ( ) ;

};

bool A ggiungiP e r s ona (Nome n , bool s e s s o ) ;


bool Sposa (Nome n1 , Nome n2 ) ;
bool Coniugato (Nome n , bool& c o n i u g a t o ) const ;
unsigned int NumeroSposi ( ) const ;
unsigned int NumeroCoppie ( ) const ;
void Svuota ( ) ;
void Stampa ( ) const ;

A ge nz iaMat r imoniale : : Age nz iaMat r imoniale ( ) : f i r s t ( 0 ) {


}
A ge nz iaMat r imoniale : : ~ Age nz iaMat r imoniale ( ) {
Svuota ( ) ;
}

const

PRec A ge nz iaMat r imoniale : : Cerca (Nome n )


{
// Cerca n e l l a l i s t a l a persona a v e n t e i l nome s p e c i f i c a t o
// R e s t i t u i s c e i l p u n t a t o r e a l l a c o r r i s p o n d e n t e c e l l a s e e s i s t e , 0 a l t r i m .
PRec p = f i r s t ;
(p) {
( strcmp ( p>e l . n , n ) == 0)

while
if

costr .

SX. Soluzioni degli altri esercizi

133

return

}
}

p;
p = p>s u c c ;

return

bool
if

0;

A ge nz iaMat r imoniale : : AggiungiPe r sona (Nome n ,


( Cerca ( n ) )
;

return false

bool

maschio ) {

// I n s e r i m e n t o i n t e s t a
PRec p =
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;

new

return true ;

bool

A ge nz iaMat r imoniale : : Sposa (Nome n1 , Nome n2 ) {


PRec p1 = Cerca ( n1 ) ;
// s e i l primo 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
( ! p1 )
;

if

return false

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
( ! p2 )
;

if

return false

// s e i due nomi sono u g u a l i r e s t i t u i s c e f a l s e


( p1 == p2 )
;

if

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
( p1>e l . maschio == p2>e l . maschio )
;

if

return false

// s e una d e l l e due persone g i s p o s a t a r e s t i t u i s c e f a l s e


( p1>e l . c o n i u g e | | p2>e l . c o n i u g e )
;

if

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 ;

bool

A ge nz iaMat r imoniale : : Coniugato ( Nome n ,


PRec p = Cerca ( n ) ;

if

bool&

coniugato )

( ! 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 ;

unsigned int

A ge nz iaMat r imoniale : : NumeroSposi ( )

const

const

SX. Soluzioni degli altri esercizi

134

unsigned int

c ount = 0 ;
PRec p = f i r s t ;

while ( p ) {
if ( p>e l . c o n i u g e
}
}

c ount++;
p = p>s u c c ;

return

!= 0)

c ount ;

unsigned int A ge nz iaMat r imoniale : : NumeroCoppie ( ) const


return NumeroSposi ( ) / 2 ;
}

void A ge nz iaMat r imoniale : : 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 ;
tbd ;

delete

void A ge nz iaMat r imoniale : : Stampa ( ) const


PRec p = f i r s t ;
while ( p ) {
c out << p>e l . n << " ( " ;
if ( p>e l . maschio )
c out << 'M' ;
else

c out << 'F ' ;


c out << " ) ; " ;

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" ;

void
void
void
void
void
void
void

A ggiungiP e r s ona ( Age nz iaMat r imoniale& am ) ;


Sposa ( A ge nz iaMat r imoniale & am ) ;
Coniugato ( A ge nz iaMat r imoniale& am ) ;
NumeroSposi ( A ge nz iaMat r imoniale & am ) ;
NumeroCoppie ( A ge nz iaMat r imoniale& am ) ;
Svuota ( A ge nz iaMat r imoniale& am ) ;
Stampa ( A ge nz iaMat r imoniale& am ) ;

SX. Soluzioni degli altri esercizi

int

135

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 ;
( scelta ) {
1:
A ggiungiP e r s ona (am ) ;
;
2:
Sposa (am ) ;
;
3:
Coniugato (am ) ;
;
4:
NumeroSposi (am ) ;
;
5:
NumeroCoppie (am ) ;
;
6:
Svuota (am ) ;
;
7:
Stampa (am ) ;
;
8:
;
:
c out << " S c e l t a non v a l i d a . \ n" ;
;
}
}
( s c e l t a != 8 ) ;

switch
case
break
case
break
case
break
case
break
case
break
case
break
case
break
case
break
default
break
while
return 0 ;

void

A ggiungiP e r s ona ( Age nz iaMat r imoniale& am) {


Nome n ;
c out << " S p e c i f i c a r e i l nome : " ;
c i n >> n ;
sesso ;
{
c out << " S p e c i f i c a r e i l s e s s o (M, F ) : " ;
c i n >> s e s s o ;
}
( ( s e s s o != 'M' ) && ( s e s s o != 'm' ) && ( s e s s o != 'F ' )
&& ( s e s s o != ' f ' ) ) ;

char
do

while

bool maschio = ( s e s s o == 'M' | | s e s s o


if (am. A ggiungiP e r sona ( n , maschio ) )
c out << " Persona a g g i u n t a . \ n" ;
else
c out << " Persona non a g g i u n t a . \ n" ;

void

Sposa ( A ge nz iaMat r imoniale & am) {


Nome n1 , n2 ;

== 'm' ) ;

SX. Soluzioni degli altri esercizi

136

c out << " I n s e r i r e primo nome : " ;


c i n >> n1 ;
c out << " I n s e r i r e se c ondo nome : " ;
c i n >> n2 ;

if (am. Sposa ( n1 , n2 ) )
c out << " Matrimonio
else

r e g i s t r a t o . \ n" ;

c out << " Matrimonio non r e g i s t r a t o . \ n" ;

void Coniugato ( A ge nz iaMat r imoniale& am)


Nome n ;
bool c o n i u g a t o ;

c out << " I n s e r i s c i i l nome : " ;


c i n >> n ;
( ! am. Coniugato ( n , c o n i u g a t o ) )
c out << " Persona non e s i s t e n t e . \ n" ;

if
else
if ( c o n i u g a t o )
c out << n << "
else

ha c o n i u g e . \ n" ;

c out << n << " non ha c o n i u g e . \ n" ;

void
}

NumeroSposi ( A ge nz iaMat r imoniale & am) {


c out << " I l numero s p o s i p a r i a " << am. NumeroSposi ( ) << e n d l ;

void
}

NumeroCoppie ( A ge nz iaMat r imoniale& am) {


c out << " I l numero c o p p i e p a r i a " << am. NumeroCoppie ( ) << e n d l ;

void
}

Svuota ( A ge nz iaMat r imoniale& am) {


am. Svuota ( ) ;
c out << " A ge nz iaMat r imoniale s v u o t a t a . \ n" ;

void
}

Stampa ( A ge nz iaMat r imoniale& am) {


am. Stampa ( ) ;
c out << e n d l ;

SX.9 Parco Pattini


Traccia a pag. 45

La struttura dati pu essere realizzata come una lista dinamica semplicemente collegata in cui ogni elemento rappresenta lo stato di tutti i pattini di una
data taglia. La generica cella della struttura contiene dunque:

taglia dei pattini;

numero totale di pattini della taglia data;

numero totale di pattini disponibili della taglia data.

SX. Soluzioni degli altri esercizi


first

44

137

43

42

Numero pattini
disponibili

Taglia dei pattini


Numero pattini
complessivo

Figura SX.1: La struttura che implementa il parco pattini.

A titolo esemplicativo si immagini che il parco pattini disponga di un


paio di pattini della taglia 44, di un paio della taglia 43 e di due paia della
taglia 42. Se uno delle due paia di pattini della taglia 42 risulta ttato, lo
stato della struttura mostrato in Figura SX.1.
Si noti come la struttura ammetta una gestione di tipo tabellare, dal
momento che la taglia dei pattini risulta essere unica per ogni cella, e quindi
assimilabile ad una chiave.
Di seguito si riporta il listato.

#include <i o s t r e a m>


using namespace s t d ;
typedef unsigned int T a g l i a ;
struct P a t t i n i {
Taglia t a g l i a ;
unsigned int t o t a l i ;
unsigned int d i s p o n i b i l i ;
};

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
operator const

const ;

ParcoPattini (
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 .
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
:
ParcoPattini ( ) ;
~ParcoPattini ( ) ;
AggiungiPattini ( Taglia t ) ;
Svuota ( ) ;
NumeroTotPattini ( )
;
Fitta ( Taglia t ) ;

public

void
void
unsigned int
bool

const

SX. Soluzioni degli altri esercizi

};

unsigned int D i s p o n i b i l i t a ( T a g l i a
unsigned int NumeroPattini ( T a g l i a
bool R e s t i t u z i o n e ( T a g l i a t ) ;
void Stampa ( ) const ;

138

t)
t)

const ;
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 ( ) : f i r s t ( 0 ) , t o t ( 0 ) {}
ParcoPattini ::~ ParcoPattini () {
Svuota ( ) ;
}

const

PRec P a r c o P a t t i n i : : GetRecordByTaglia ( T a g l i a t )
{
// Questo metodo p e r m e t t e l a g e s t i o n e d e l l a l i s t a come t a b e l l a .
// R e s t i t u i s c e i l punt . a l l a c e l l a c o n t e n e n t e i p a t t i n i d e l l a t a g l i a r i c h i e s t a ,
// oppure 0 s e t a l e c e l l a non n e l l a l i s t a .
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
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

}
}

alla cella della lista

return

0 ; // non t r o v a t o .

void

ParcoPattini : : AggiungiPattini ( Taglia t ) {


PRec p = GetRecordByTaglia ( t ) ;

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 =
p>p a t t i n i
p>p a t t i n i
p>p a t t i n i
p>s u c c =
first = p;

new

Record ;
. taglia = t ;
. t o t a li = 1;
. disponibili = 1;
first ;

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 ;
tbd ;

delete

tot = 0;

unsigned int P a r c o P a t t i n i : : NumeroTotPattini ( ) const


return t o t ;
}

SX. Soluzioni degli altri esercizi

139

bool

ParcoPattini : : Fitta ( Taglia t ) {


PRec p = GetRecordByTaglia ( t ) ;

// 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 . ?
( 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
;
}

if

return true
else
return false ;

unsigned int

ParcoPattini : : D i s p o n ib il i t a ( Taglia t )
PRec p = GetRecordByTaglia ( t ) ;

if ( p )
return
else
return

const

0;

P a r c o P a t t i n i : : NumeroPattini ( T a g l i a t )
PRec p = GetRecordByTaglia ( t ) ;

p>p a t t i n i . d i s p o n i b i l i ;

unsigned int
if ( p )
return
else
return

const

p>p a t t i n i . t o t a l i ;
0;

bool

ParcoPattini : : Restituzione ( Taglia t ) {


PRec p = GetRecordByTaglia ( t ) ;

// 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 ?
( 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 ++;
;
}

if

return true
else
return false ;

void

P a r c o P a t t i n i : : Stampa ( )
PRec p = f i r s t ;

const

while

void
void
void
void
void
void
void
void

(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 ;

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 ) ;
Svuota ( P a r c o P a t t i n i& p ) ;
NumeroTotPattini ( P a r c o P a t t i n i& p ) ;
F i t t a ( P a r c o P a t t i n i& p ) ;
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 ) ;
NumeroPattini ( P a r c o P a t t i n i& p ) ;
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 ) ;
Stampa ( P a r c o P a t t i n i& p ) ;

SX. Soluzioni degli altri esercizi

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 ;
( scelta ) {
1:
A g g i u n g i P a t t i n i ( par c o ) ;
;
2:
Svuota ( par c o ) ;
;
3:
NumeroTotPattini ( par c o ) ;
;
4:
F i t t a ( par c o ) ;
;
5:
D i s p o n i b i l i t a ( par c o ) ;
;
6:
NumeroPattini ( par c o ) ;
;
7:
R e s t i t u z i o n e ( par c o ) ;
;
8:
Stampa ( par c o ) ;
;
9:
;
:
c out << " S c e l t a non v a l i d a . \ n" ;
;
}
}
( s c e l t a != 9 ) ;

switch
case
break
case
break
case
break
case
break
case
break
case
break
case
break
case
break
case
break
default
break
while
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 ;

140

SX. Soluzioni degli altri esercizi

141

c out << " I n s e r i r e l a t a g l i a : " ;


c i n >> t ;
p . AggiungiPattini ( t ) ;
c out << " P a t t i n i a g g i u n t i a l par c o . \ n" ;

void
}

Svuota ( P a r c o P a t t i n i& p ) {
p . Svuota ( ) ;
c out << " Parco s v u o t a t o . \ n" ;

void
}

NumeroTotPattini ( P a r c o P a t t i n i& p ) {
c out << " I l par c o p a t t i n i c o n t i e n e " << p . NumeroTotPattini ( )
<< " p a i a d i p a t t i n i i n t o t a l e . \ n" ;

void

F i t t a ( P a r c o P a t t i n i& p ) {
Taglia t ;

c out << " I n s e r i r e l a t a g l i a : " ;


c i n >> t ;
(p . Fitta ( t ))
c out << " P a t t i n i f i t t a t i . \ n" ;

if
else

c out << " P a t t i n i non d i s p o n i b i l i . \ n" ;

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 ;

c out << " I n s e r i r e l a t a g l i a : " ;


c i n >> t ;
c out << " D i s p o n i b i l i t a ' t a g l i a " << t << " : " << p . D i s p o n i b i l i t a ( t )
<< e n d l ;

void

NumeroPattini ( P a r c o P a t t i n i& p ) {
Taglia t ;

c out << " I n s e r i r e l a t a g l i a : " ;


c i n >> t ;
c out << " I l par c o c o n t i e n e " << p . NumeroPattini ( t ) <<
" p a i a d i p a t t i n i d i t a g l i a " << t << " . \ n" ;

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 ;

c out << " I n s e r i r e l a t a g l i a : " ;


c i n >> t ;
(p . Restituzione ( t ))
c out << " P a t t i n i r e s t i t u i t i . \ n" ;

if
else

c out << " E r r o r e . P a t t i n i non f i t t a t i . \ n" ;

void
}

Stampa ( P a r c o P a t t i n i& p ) {
p . Stampa ( ) ;

SX. Soluzioni degli altri esercizi

142

SX.10 Timer
Traccia a pag. 46

#include <i o s t r e a m>


#include <time . h>
using namespace s t d ;
typedef int Time ;
class Timer {
private :
Time s t ar t T ime ;
Time stopTime ;
:
Timer ( ) ;
start ();
stop ( ) ;
reset ();
Time getTime ( )

public
void
void
void
};

const ;

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 ;

const

Time Timer : : getTime ( )


{
( s t ar t T ime == 0) // i l timer i n s t a t o d i r e s e t ?
0;

if

if ( stopTime == 0) // i l timer i n
return time ( 0 ) st ar t T ime ; // s
else
return stopTime st ar t T ime ; // no

int

return

main ( )

Timer t ;
ch ;

char
c out
c out
c out
c out
c out

<<
<<
<<
<<
<<

"'s '
" 'x '
"'r '
" 'p '
" 'e '

s t a r t \n" ;
s t o p \n" ;
r e s e t \n" ;
show t i m e r \n" ;
e x i t \n" ;

moto?

SX. Soluzioni degli altri esercizi

do

143

{
c i n >> ch ;
( ch ) {
's ':
t . start ();
c out << " Timer s t a r t e d . \ n" ;
;
'x ' :
t . stop ( ) ;
c out << " Timer st oppe d . \ n" ;
;
'r ':
t . reset ();
c out << " Timer r e s e t . \ n" ;
;
'p ' :
c out << " Timer shows : " << t . getTime ( ) << e n d l ;
;
'e ' :
;
:
c out << " I n v a l i d command . \ n" ;
}
}
( ch != ' e ' ) ;

switch
case

break
case

break
case

break
case
break
case
break
default

while
return 0 ;

SX.11 Timer Avanzato


Traccia a pag. 47

Il primo dei requisiti aggiuntivi imposti dalla traccia suggerisce intuitivamente che il timer una sorta di accumulatore che tiene memoria della durata
complessiva degli intervalli di tempo cronometrati no ad un certo istante.
Infatti l'esecuzione di un nuovo conteggio fornisce un contributo che va a
sommarsi a tutti gli eventuali contributi precedenti.
Ai ni dello svolgimento di questo esercizio, il valore corrente del cronometro pu essere pertanto considerato come la composizione di due contributi:

la somma di tutti gli intervalli di tempo cronometrati nel passato, cio


compresi tra un segnale di START ed uno di STOP;

l'eventuale contributo del conteggio corrente, se il timer attivo.

dunque possibile pensare al timer come una classe dotata di due membri
privati:

storedTime:

contiene la somma di tutti i conteggi passati gi terminati;

questo membro va aggiornato al termine di ogni conteggio;

SX. Soluzioni degli altri esercizi


startTime:

144

contiene l'istante di inizio dell'eventuale conteggio in corso; vale

0 se il timer inattivo.
In questo modo, all'arrivo del messaggio GETTIME, suciente restituire

storedTime, aggiungendo eventualmente la dierenza


e l'istante startTime, se startTime diverso da zero

il valore del membro


tra l'istante attuale

(cio se c' un conteggio in corso).


Dal momento che spesso sorge la necessit di valutare se c' un conteggio
in corso oppure no, in questa implementazione lo svolgimento di tale servizio
stato incapsulato nell'opportuno metodo privato

bool

isRunning ( )

const ;

#include <i o s t r e a m>


#include <time . h>
using namespace s t d ;
typedef int Time ;
class Timer {
private :
Time s t or e dT ime ;
Time s t ar t T ime ;
is R unning ( )
:
Timer ( ) ;
start ();
stop ( ) ;
reset ();
Time getTime ( )

bool
public
void
void
void
};

const

return

( st ar t T ime != 0 ) ; } ;

const ;

Timer : : Timer ( ) {
reset ();
}

void
if
}

void
if
}

Timer : : s t a r t ( ) {
( ! is R unning ( ) )
s t ar t T ime = time ( 0 ) ;
Timer : : s t o p ( ) {
( 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 ;

Time Timer : : getTime ( )


Time t = s t or e dT ime ;

const

SX. Soluzioni degli altri esercizi

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

int

145

t;

main ( )

Timer t ;
ch ;

char
c out
c out
c out
c out
c out

do

<<
<<
<<
<<
<<

"'s '
" 'x '
"'r '
" 'p '
" 'e '

s t a r t \n" ;
s t o p \n" ;
r e s e t \n" ;
show t i m e r \n" ;
e x i t \n" ;

{
c i n >> ch ;
( ch ) {
's ':
t . start ();
c out << " Timer s t a r t e d . \ n" ;
;
'x ' :
t . stop ( ) ;
c out << " Timer st oppe d . \ n" ;
;
'r ':
t . reset ();
c out << " Timer r e s e t . \ n" ;
;
'p ' :
c out << " Timer shows : " << t . getTime ( ) << e n d l ;
;
'e ' :
;
:
c out << " I n v a l i d command . \ n" ;
}
}
( ch != ' e ' ) ;

switch
case

break
case

break
case

break
case
break
case
break
default

while
return 0 ;

SX.12 Votazioni
Traccia a pag. 48

#include <i o s t r e a m>


using namespace s t d ;
const int NMAX = 5 0 ;
typedef char Nome [NMAX] ;
typedef unsigned int C odic e ;

//un p a r t i t o per s e m p l i c i t i d e n t i f i c a t o
// da un c o d i c e d i t i p o i n t e r o .

SX. Soluzioni degli altri esercizi

struct Oggetto
C odic e i d ;
unsigned int
};

struct C e l l a ;
typedef C e l l a
struct C e l l a {
};

146

{
voti ;

P C e lla ;

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
public :

id )

const ;

Votazioni ( ) ;
~Votazioni ( ) ;

unsigned int AggiungiVoto ( C odic e i d ) ;


void Svuota ( ) ;
unsigned int G e t V o t i P a r t i t o ( C odic e i d ) const ;
unsigned int GetNumeroVoti ( ) const ;
void G e t S i t u a z i o n e ( ) const ;

};

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 ) {
}
Votazioni ::~ Votazioni () {
Svuota ( ) ;
}

const

P C e lla V o t a z i o n i : : C e r c a P a r t i t o ( C odic e i d )
{
//La s t r u t t u r a g e s t i b i l e con metodo t a b e l l a r e : i n f a t t i i l c o d i c e
// p a r t i t o r a p p r e s e n t a una c h i a v e per l a t a b e l l a d e i v o t i .
// Questo metodo r e s t i t u i s c e i l p u n t a t o r e a l l a c e l l a a v e n t e i d p a r i a q u e l l o
// s p e c i f i c a t o i n i n g r e s s o , 0 a l t r i m e n t i .
P C e lla p = f i r s t ;
trovato =
;

bool
false
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 ;

return

p ; // s e t r o v a t o vero , p punta a l l a c e l l a r i c e r c . , a l t r i m . p z e r o

unsigned int

V o t a z i o n i : : AggiungiVoto ( C odic e i d ) {
numVoti++; // incremento i l numero d i v o t i c o m p l e s s i v i
P C e lla p = C e r c a P a r t i t o ( i d ) ;

if

(p) {
p>elem . v o t i ++;
p>elem . v o t i ;

return

SX. Soluzioni degli altri esercizi


}

else

147

{
P C e lla p =
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;
1;

new

return

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 ;
tbd ;

delete

}
numVoti = 0 ;

unsigned int

V o t a z i o n i : : G e t V o t i P a r t i t o ( C odic e i d )
P C e lla p = C e r c a P a r t i t o ( i d ) ;

if ( p )
return
else
return

const

p>elem . v o t i ;
0;

unsigned int V o t a z i o n i : : GetNumeroVoti ( ) const


return numVoti ;

void

Votazioni : : GetSituazione ()
P C e lla p = f i r s t ;

while

const

(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 << " ( " << (
) p>elem . v o t i /numVoti 100 << "%)" << e n d l ;

void
void
void
void
void
void

p = p>s u c c ;

AggiungiVoto ( V o t a z i o n i& v ) ;
Svuota ( V o t a z i o n i& v ) ;
G e t V o t i P a r t i t o ( V o t a z i o n i& v ) ;
GetNumeroVoti ( V o t a z i o n i& v ) ;
G e t S i t u a z i o n e ( V o t a z i o n i& v ) ;

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

float

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 ;
( scelta ) {
1:
AggiungiVoto ( v ) ;
;
2:
Svuota ( v ) ;
;
3:
GetVotiPartito ( v ) ;
;
4:
GetNumeroVoti ( v ) ;
;
5:
GetSituazione (v ) ;
;
6:
;
:
c out << " S c e l t a non v a l i d a . \ n" ;
;
}
}
( s c e l t a != 6 ) ;

switch
case
break
case
break
case
break
case
break
case
break
case
break
default
break
while
return 0 ;

void

AggiungiVoto ( 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 << " Voto Aggiunto . Ora i l p a r t i t o " << i d << " ha v o t i " <<
v . AggiungiVoto ( i d ) << " . \ n" ;

void
}

Svuota ( V o t a z i o n i& v ) {
v . Svuota ( ) ;
c out << " S t r u t t u r a s v u o t a t a . " << e n d l ;

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
}

GetNumeroVoti ( V o t a z i o n i& v ) {
c out << " I v o t i c o m p l e s s i v i sono : " << v . GetNumeroVoti ( ) << e n d l ;

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
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
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 noncommercially. 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 providing 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.

A.1 Applicability and Denitions


This License applies to any manual or other work, in any medium, that contains a notice
placed by the copyright holder saying it can be distributed under the terms of this License.
Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that
work under the conditions stated herein. The Document, below, refers to any such
manual or work. Any member of the public is a licensee, and is addressed as you. You

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 revising 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 Transparent 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 markup, 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. Opaque 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 generally 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.2 Verbatim Copying


You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice
saying this License applies to the Document are reproduced in all copies, and that you
add no other conditions whatsoever to those of this License. You may not use technical
measures to obstruct or control the reading or further copying of the copies you make
or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section
3.
You may also lend copies, under the same conditions stated above, and you may
publicly display copies.

A.3 Copying in Quantity


If you publish printed copies (or copies in media that commonly have printed covers) of the
Document, numbering more than 100, and the Document's license notice requires Cover
Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover.
Both covers must also clearly and legibly identify you as the publisher of these copies.
The front cover must present the full title with all words of the title equally prominent
and visible. You may add other material on the covers in addition. Copying with changes
limited to the covers, as long as they preserve the title of the Document and satisfy these
conditions, can be treated as verbatim copying in other respects.
If the required texts for either cover are too voluminous to t legibly, you should put
the rst ones listed (as many as t reasonably) on the actual cover, and continue the rest
onto adjacent pages.
If you publish or distribute Opaque copies of the Document numbering more than 100,
you must either include a machine-readable Transparent copy along with each Opaque
copy, or state in or with each Opaque copy a computer-network location from which
the general network-using public has access to download using public-standard network
protocols a complete Transparent copy of the Document, free of added material. If you use
the latter option, you must take reasonably prudent steps, when you begin distribution of
Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible
at the stated location until at least one year after the last time you distribute an Opaque
copy (directly or through your agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of the Document well
before redistributing any large number of copies, to give them a chance to provide you
with an updated version of the Document.

A. GNU Free Documentation License

152

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 endorsements 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.5 Combining Documents


You may combine the Document with other documents released under this License, under
the terms dened in section 4 above for modied versions, provided that you include in
the combination all of the Invariant Sections of all of the original documents, unmodied,
and list them all as Invariant Sections of your combined work in its license notice, and
that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and multiple identical
Invariant Sections may be replaced with a single copy. If there are multiple Invariant
Sections with the same name but dierent contents, make the title of each such section
unique by adding at the end of it, in parentheses, the name of the original author or
publisher of that section if known, or else a unique number. Make the same adjustment
to the section titles in the list of Invariant Sections in the license notice of the combined
work.
In the combination, you must combine any sections Entitled History in the various
original documents, forming one section Entitled History; likewise combine any sections
Entitled Acknowledgements, and any sections Entitled Dedications. You must delete all
sections Entitled Endorsements.

A. GNU Free Documentation License

154

A.6 Collection of Documents


You may make a collection consisting of the Document and other documents released under
this License, and replace the individual copies of this License in the various documents
with a single copy that is included in the collection, provided that you follow the rules of
this License for verbatim copying of each of the documents in all other respects.
You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted
document, and follow this License in all other respects regarding verbatim copying of that
document.

A.7 Aggregation with Independent Works


A compilation of the Document or its derivatives with other separate and independent
documents or works, in or on a volume of a storage or distribution medium, is called an
aggregate if the copyright resulting from the compilation is not used to limit the legal
rights of the compilation's users beyond what the individual works permit. When the
Document is included in an aggregate, this License does not apply to the other works in
the aggregate which are not themselves derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these copies of the Document,
then if the Document is less than one half of the entire aggregate, the Document's Cover
Texts may be placed on covers that bracket the Document within the aggregate, or the
electronic equivalent of covers if the Document is in electronic form. Otherwise they must
appear on printed covers that bracket the whole aggregate.

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 provided 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.

A.10 Future revisions of this license


The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to
the present version, but may dier in detail to address new problems or concerns. See
http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number. If the Document
species that a particular numbered version of this License or any later version applies
to it, you have the option of following the terms and conditions either of that specied
version or of any later version that has been published (not as a draft) by the Free Software
Foundation. If the Document does not specify a version number of this License, you may
choose any version ever published (not as a draft) by the Free Software Foundation.

How to use this License for your documents


To use this License in a document you have written, include a copy of the License in the
document and put the following copyright and license notices just after the title page:
c YEAR YOUR NAME. Permission is granted to copy, distribute
Copyright
and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software
Foundation; with no Invariant Sections, no Front-Cover Texts, and no BackCover Texts. A copy of the license is included in the section entitled GNU
Free Documentation License.
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 FrontCover 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 releasing 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.
edition, 2000.

The C++ Programming Language. Addison-Wesley, special

[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
Designs. Addison-Wesley, 3rd edition, 2005.

Ways to Improve Your Programs and

[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
Reusable Object-Oriented Software. Addison-Wesley, 1995.
[10] Scott Meyers. More Eective C++:
Designs. Addison-Wesley, 1995.

Patterns: Elements of

35 New Ways to Improve Your Programs and

[11] Andrei Alexandrescu. Modern C++ Design:


Patterns Applied. Addison-Wesley, 2001.

156

Generic Programming and Design