Elementi di
programmazione
ad oggetti
a. a. 2009/2010
Corso di Laurea Magistrale in Ingegneria Elettronica
Docente: Mauro Mazzieri, Dipartimento di Ingegneria Informatica,
Gestionale e dell’Automazione
Lezione 10.2
La libreria standard: algoritmi e oggetti
funzione.
Complessità computazionale
La complessità di un’elaborazione può essere definita
in termini di tempo di esecuzione
in termini di occupazione di memoria
complessità spaziale
La complessità è espressa come funzione della dimensione
dell’input
complessità temporale
es. numero di elementi da ordinare, numero di elementi in un
contenitore
è una misura di complessità relativa, perché il tempo
effettivamente impiegato o la memoria effettivamente occupata
dipendono dallo specifico elaboratore
Notazione O
se la complessità di una certa operazione è f(n), dove n è la
dimensione dell’input, la complessità appartiene alla famiglia
O(g), dove g è funzione di n, se e solo se esistono una costante
positiva k ed un n’ tali che, per tutti gli n > n’,
f(n) <= k * g(n)
Complessità delle operazioni sui
contenitori
[]
vector
O(1)
list
deque
O(1)
insert
front /
erase push_front
back /
push_back
O(n)1
O(1) / O(n)2
O(1)
O(1)
O(1)
O(n)
O(1) /
O(n)2
O(1) / O(n)2
stack
queue
O(1) / O(n)2
O(1) /
O(n)2
O(1) / O(n)2
priority-queue
1.
2.
O(log n) /
O(log n) /
O(n)2 tutti i successivi;
O(n)2a volte
Inserire o eliminare un elemento comporta spostare
è necessario spostarli tutti
Normalmente richiede un tempo costante, ma se non c’è spazio disponibile
occorre spostare tutto il vettore
Algoritmi generici
Sui contenitori sono disponibili operazione
per accedere e manipolare membri
La libreria standard l’implementazione di
algoritmi generici
Indipendenti dal contenitore e dal tipo
dell’oggetto contenuto
Operano su sequenze
Definite da coppie di iteratori
#include <algorithm>
Esempi: sort, unique_copy, find…
Esempio: ordinare e copiare
vector<Elemento> v;
lista<Elemento> l;
// …
sort(v.begin(), v.end());
unique_copy(v.begin(),
v.end(), l.begin());
Esempio: cercare e contare
string s;
char c;
string::const_iterator i =
find(s.begin(), s.end(), c);
int n = count(s.begin(),
s.end(), c);
Esempio: cercare un elemento
vector<int> v;
// …
vector<int> const_iterator
result = find(v.begin(),
v.end(), 42);
cout << result == v.end() ?
“non presente” : “presente”;
Come sarebbe fatto usando list?
Esempio: array
Gli algoritmi possono essere usati
anche su array, usando i puntatori
come iteratori
int a[6] = {1, 2, 3, 5, 7,
11};
int* result = find(a, a + 6,
42);
cout << result == a + 6 ?
“non presente” : “presente”;
Algoritmi: presupposti
Un algoritmo ha bisogno di:
attraversare la collezione, avanzando da un
elemento al successivo, a partire dal primo;
sapere quando fermarsi, ovvero quando si
arriva alla fine della sequenza;
accedere ad un elemento deferenziando un
iteratore
L’iteratore “uno-dopo-l’ultimo” serve dunque:
come valore sentinella
nel caso di alcuni algoritmi (es. find), viene restituito
come valore che indica fallimento (es. elemento non
trovato)
Algoritmi che non modificano
una sequenza
for_each invoca una funzione per ogni argomento
find trova la prima occorrenza dell’argomento
find_if trova il primo elemento che soddisfa un predicato
find_first_of cerca un valore di una sequenza in un’altra
adjacent_find cerca una coppia di valori consecutivi
count conta le occorrenze di un valore
count_if conta gli elementi che verificano una condizione
mismatch trova il primo elemento diverso di due sequenze
equal controlla se due sequenze sono uguali
search cerca la prima ocorrenza di una sottosequenza
find_end cerca l’ultima occorrenza di una sequenza
search_n cerca l’n-esima occorrenza di un valore in una
sequenza
Algoritmi che modificano una
sequenza
transform applica un’operazione a tutti gli elementi
copy copia elementi
copy_backward copia a partire dall’ultimo elemento
swap scambia due elementi
iter_swap scambia due elementi indicato
swap_rages scambia gli elementi di due sequenze
replace sostituisce elementi con un nuovo valore
replace_if sostituisce elementi che verificano una condizione
replace_copy copia una sequenza sostituendo gli elementi che hanno un certo valore
replace_copy_if copia una sequenza sostituendo tutti gli elementi che soddisfano un predicato
fill sostituisce tutti gli elementi con un valore
fill_n sostituisce i primi n elementi con un certo valore
unique_copy copia omettendo i duplicati
generate sostituisce ogni elementi con il risultato di un’operazione
generate_n sostituisce i primi n elementi con il risultato di un’operazione
remove rimuove gli elementi che hanno un certo valore
remove_if rimuove gli elementi che soddisfano un predicato
remove_copy copia una sequenza rimuovendo gli elementi con un certo valore
remov_copy_if copia una sequenza rimuovendo gli elementi che soddisfano un predicato
unique rimuove gli elementi adiacenti uguali
unique_copy copia una sequenza rimuovendo gli elementi adiacenti uguali
reverse inverte l’ordine degli elementi
rotate ruota gli elementi
rotate_copy copia gli elementi in una sequenza ruotata
randm_shuffe mischia gli elementi a caso, con distribuzione uniforme
Ordinamenti e algoritmi su
sequenza ordinate
sort ordina
stable_sort ordina mantenendo l’ordine precedente degli
elementi uguali
partial_sort ordina la prima parte di una sequenza
partial_sort_copy copia ordinando la prima parte di una
sequenza
nth_element sistema l’n-esimo elemento al proprio posto
lower_bound cerca la prima occorrenza
upper_bound cerca il primo elemento maggiore
equal_range cerca una sequenza con un dato valore
binary_search cerca in una sequenza ordinata
merge fonde sequenze ordinate
inplace_merge fonde sequenze ordinate consecutive
partition muove in testa elementi che soddisfano una
condizione
stable_partition muove in testa elementi che soddisfano una
condizione mantenendo il loro ordine relativo
Algoritmi su insiemi
includes verifica l’inclusione di una
sequenza in un’altra
set_union unione
set_intersection intersezione
set_difference differenza (elementi
nella prima sequenza ma non nella
seconda)
set_symmetric_difference elementi in
una delle sequenze ma non in
entrambe
Algoritmi su heap
Gli heap sono dei gruppo, non necessariamente
ordinati, che mantengono una sequenza in
maniera che sia facile ordinare.
make_heap costruisce un heap da
una sequenza
push_heap aggiunge un elemento
pop_heap rimuove un elemento
sort_heap ordina
Minimi e massimi; permutazioni
min il minore di due valori
max il maggiore di due valori
min_element il minore di una sequenza
max_element il maggiore di una sequenza
lexicographical_compare confronto
lessicografico
next_permutation permutazione
successiva, in ordine lessicografico
prev_permutation permutazione
precedente, in ordine lessicografico
Funzioni come parametri
Molti algoritmi che operano su
sequenze hanno la possibilità di
accettare un parametro in più che
indica l’operazione da eseguire
es.
bool minoredi2(int i) {
return i < 2;
}
find_if(v.begin(), v.end(), minoredi2);
Oggetti funzione
Istanze di una classe che ridefinisce l’operatore ()
possono essere usate come funzioni
es.
template<class T> class accumulatore {
T a;
public:
accumulatore(T i = 0) : a(i) { }
void operator()(T x) { a += x; }
T valore() const { return a; }
};
accumulatore<float> acc;
vector<float> v;
// …
acc = for_each(v.begin(), v.end(), acc);
cout << “la somma è “ << s.valore() << endl;
Oggetti funzione standard:
predicati
Un predicato è un oggetto funzione che restituisce un
bool
equal_to
not_equal_to
greater
less
greater_equal
less_equal
logical_and
logical_or
logical_not
Oggetti funzione aritmentici
plus
minus
multiplies
divides
modulus
negate
Connettori e adattatori
Un binder (connettore) consente di utilizzare un
oggetto funzione a due parametri come oggetto
funzione ad un parametro fissando un argomento
bind2nd
binf1st
Un adattatore consente di un funzione come
argomento di un algoritmo
mem_fun usa un puntatore ad un metodo
mem_fun_ref usa un riferimento ad un
metodo
ptr_fun usa un puntatore a funzione
Algoritmi che usano funzioni
membro
class Elemento {
string nome;
public:
void print() {
cout << nome;
}
}
list<Elemento> l;
foreach(l.begin(), l.end(),
mem_fun(&Elemento::print));