Sie sind auf Seite 1von 7

Chapitre 8 : Les collections STL A.U.

: 2009/2010
ENSI – II2

1. Qu’est-ce que STL?

STL STL = Standard Template Library

• Il s’agit d’une bibliothèque générique qui fournit des


solutions pour gérer un ensemble de données en
1. Qu’est-
Qu’est-ce que STL? utilisant des algorithmes efficaces
2. Composants STL
3. Foncteurs • Du point de vue du programmeur, STL fournit un
groupe de classes répondant à divers besoins.
http://www.cs.rpi.edu/~musser/stl.html • Tous les composants de STL sont des templates

STL 1 STL 2

2. Les composants STL 2.1 Les conteneurs


 Les conteneurs servent à stocker des
collections d'objets d’un même type T.
 STL fournit différentes sortes de conteneurs
pour combler différents besoins. Il existe deux
types de conteneurs:
• Les conteneurs séquentiels, qui conservent la
collection d'objets, sous un format strictement linéaire;
La programmation générique
Il s’agit de connecter des algorithmes génériques • Les conteneurs associatifs triés, qui conservent la
à des structures de données génériques collection selon un ordre de tri basé sur une clé.
en utilisant des itérateurs.

STL 3 STL 4

Les principaux conteneurs de STL 2.1.1. Conteneurs séquentiels


Conteneurs séquentiels Conteneurs associatifs
 Le tableau C++ ordinaire:
• Caractéristiques principales:
 Accès aléatoire par index en temps constant O(1);
Vector  Insertion et retrait lents au milieu du tableau;
 Taille ne pouvant être modifiée pendant
Set/Multiset l'exécution;
 Peut être utilisé avec les algorithmes de la STL
Deque comme tout autre conteneur de séquence.
 Vector =
• Tableau dynamique
• Les éléments sont insérés à la fin du tableau
List
Map/Multimap
STL 5 STL 6

1
Chapitre 8 : Les collections STL A.U. : 2009/2010
ENSI – II2

Conteneurs - vector Spécificité du conteneur Vector


#include <vector>
#include <iostream>  Les conteneurs séquentiels
using namespace std; • Les éléments du conteneur ont une position qui dépend du temps et
de l’endroit de l’insertion
void main() • La position est donc indépendante de la valeur de l’élément
{
vector<int
vector< int>
> iv;  La taille d’un vector est le nombre d’éléments actuellement
for( int i=0; i<10; ++i ) contenu dans le vector
{
iv.push_back( i );  La capacité d’un vector est le nombre maximum d’élements
} qui peuvent contenu dans un sans réallocation.
for( i=0; i<iv.size(); ++i )  La méthode reserve() est utilisée pour élargir la capacité
{
cout << iv[i] << endl;
 La méthode resize() redimensionne le vector à la taille
} spécifié (appelle le constructeur par défaut de chaque
} élément du tableau).

STL 7 STL 8

#include <vector>
#include <iostream> #include <deque>
using namespace std;
void main() Conteneurs - deque #include <iostream>
using namespace std;
{
vector<int> iv; // vector a initialement 0 elements. void main()
iv.push_back(42); // Ajoute 42 à la fin du vector
cout << "location: " << (void*) &iv[0] << endl;
{
int *k = &iv[0]; // Attention ! Location peut changer ! deque<int>
deque< > d;
cout << "iv[0] = " << iv[0] << endl;  Deque = Double-
Double-Ended Queue for(int i=0; i<10; ++i)
cout << "*k = " << *k << endl;  Tableau dynamique {
cout << "sz=" << iv.size() << " cap=" << iv.capacity();
iv.reserve(1024); // augmente la capacité et non pas taille  Les éléments sont insérés à la fin .push_front( i );
d.push_front
cout << "\nlocation: " << (void*) &iv[0] << endl; ou au début du tableau }
cout << "sz=" << iv.size() << " cap=" << iv.capacity(); for(i=90; i<100; ++i )
iv.resize(2048); // augmente taille (et capacité)
cout << "\nlocation: " << (void*) &iv[0] << endl;
{
cout << "sz=" << iv.size() << " cap=" << iv.capacity(); .push_back( i );
d.push_back
cout << "\niv[0] = " << iv[0] << endl; }
cout << "*k = " << *k << endl; // danger! mauvaise valeur .size();++i)
for(i=0;i<d.size
}
location: 007E0EC0 location: 006D5294
{
iv[0] = 42 sz=2048 cap=2048 cout << d[[i]] << endl;
*k = 42
sz=1 cap=1
iv[0] = 42 }
*k = -572662307
location: 006D4260 }
sz=1 cap=1024

STL 9 STL 10

#include <list>
#include <iostream>
using namespace std; Comparaisons
Conteneurs - list
Void main()  Les vector et les deque permettent d’accéder rapidement à un élément de la
{ liste (opérateur []) contrairement aux list
list<int>
list< > l;  Un élément peut être inséré
for( int i=1; i<20; ++i ) • n’importe où pour une list
• Liste doublement chaînée {
• à la fin ou au début pour un deque
d’éléments
• à la fin seulement pour un vector
if( i % 2 == 0 )
 Utiliser un vector est un bon choix lorsque:
.push_front(i);
l.push_front
• on a besoin d’insérer/supprimer des éléments seulement à la fin
• Un élément pointe sur son else • le conteneur doit être compatible au tableau C standard
prédecesseur et son successeur .push_back(i);
l.push_back  Utiliser un deque est un bon choix lorsque:
dans la liste }
.empty() )
while( !l.empty
• on a besoin d’insérer/supprimer des éléments seulement à la fin ou au
début
• Les éléments sont insérés
{ • le conteneur ne doit pas être compatible avec un tableau C standard
n’importe où dans la liste
.front() << " ";
cout << l.front • la taille maximum requise du conteneur n’est pas connue
pop_front();
l.pop_front  Utiliser une list est un bon choix lorsque:
// supprime le 1er élément • on a besoin d’insérer/supprimer des éléments au milieu du conteneur
} • le conteneur ne doit pas être compatible avec un tableau C standard
cout << endl; • la taille maximum requise du conteneur n’est pas connue
}
STL 11 STL 12

2
Chapitre 8 : Les collections STL A.U. : 2009/2010
ENSI – II2

2.1.2.Conteneurs associatifs Conteneurs - set

• Les éléments du conteneur sont automatiquement triés • Les éléments sont triés selon leur valeur. Chacun des
lors de leur insertion selon un critère précis. éléments ne peut exister qu’une fois
• Le critère de tri prend la forme d’une comparaison de #include <set>
la valeur de l’élément ou d’une clé spéciale définie pour set<int> coll;
l’élément. ... 4
coll.insert(3);
• Les conteneurs associatifs sont généralement coll.insert(1);
représentés sous forme d’arbre binaire coll.insert(5); 2 6
• set
set,, multiset
multiset,, map et multimap sont des coll.insert(4);
coll.insert(1);
conteneurs associatifs coll.insert(6); 1 3 5
coll.insert(2);

STL 13 STL 14

Conteneurs - multiset Conteneurs - map


 Les éléments sont triés selon leur valeur. Chacun des • Les éléments sont une paire formée d’une clé jumelée
éléments peut exister plus d’une fois à une valeur.
• Les éléments sont triés selon leur clé.
#include <set>
multiset<int> coll;
• Chacune des clés ne peut exister qu’une fois
4
coll.insert(3); #include <map>
coll.insert(1); map<string, float> coll;
coll.insert(5); 2 5
coll.insert(4);
coll["TVA"] = 0.15; // TVA est la clé
coll.insert(1);
coll.insert(6); coll["Pi"] = 3.1416;
1 3 1 6
coll.insert(2); coll["un nombre arbitraire"] = 4983.223;
coll["zero"] = 0;

STL 15 STL 16

Conteneurs - multimap Conteneurs dérivés

• Même chose que map excepté qu’une clé peut exister • Le standard C++ fournit quelques conteneurs
plus d’une fois. supplémentaires:
• Piles (stacks): conteneur manipulant ses éléments
• On peut donc retrouver des éléments possédant la selon la politique LIFO (last-
(last-in
in--first-
first-out)
même clé mais des valeurs différentes • Files (queues): conteneur manipulant ses éléments
selon la politique FIFO (first-
(first-in
in--first-
first-out)
• Ex: dictionnaire • Queues de priorité:
priorité: conteneur manipulant ses
éléments selon la politique FIFO à priorité (un
élément plus prioritaire se retrouve en tête de file)

STL 17 STL 18

3
Chapitre 8 : Les collections STL A.U. : 2009/2010
ENSI – II2

Conteneurs - requis 2.2 Itérateurs

• L’élément qui sera inclus dans un conteneur  Un itérateur est un objet qui permet de naviguer
doit posséder: dans les éléments d’un conteneur
• constructeur copie
• opérateur d’affectation (operator =)  Un itérateur est un pointeur « intelligent »
• destructeur (considéré comme intelligent car le déplacement dans un
• possiblement, un constructeur par défaut arbre binaire équilibré n’est pas comme un déplacement dans
une liste d’éléments contigüs)
• possiblement, un test d’égalité (operator ==)
• possiblement, un critère de tri (operator <, ...)  L’itérateur fait le lien entre les conteneurs et les
bool operator < (const Complex & z) const { algorithmes
return ((re<z.re) || ((re==z.re) && (im==z.im)));
}

STL 19 STL 20

Itérateurs - opérations Conteneurs – fonctions membres


 Tous les conteneurs offrent les mêmes fonctions de base permettant aux
 L’itérateur a une interface similaire aux pointeurs itérateurs d’accéder aux éléments
(operator*, operator++, operator==, operator!=, operator=, and • begin() : Retourne un itérateur représentant le début des éléments dans le
conteneur
operator->) • end() : Retourne un itérateur représentant la fin des éléments dans le conteneur
• size() : Retourne le nombre d’éléments présents dans le conteneur
 Opérateur * : Retourne l’élément de la position courante • empty() : Retourne vrai si conteneur est vide
• erase(itérateur): retire l’élément se trouvant à la position indiquée par
 Opérateur ++ : Fait pointer l’itérateur à l’élt suivant l’itérateur et retourne un itérateur sur l’élément suivant

 Opérateur == : Indique si 2 itérateurs pointent le même • erase(itérateur, itérateur): retire tous les éléments à partir de la position
indiquée par le premier itérateur jusqu’à la position indiquée par le second
élément • back(): retourne le dernier élément du conteneur
 Opérateur = : Assigne un itérateur • front(): retourne le premier élément du conteneur
• pop_back(): retire le dernier élément du conteneur
• push_back(): insère un nouvel item à la fin du conteneur

STL 21 STL 22

Itérateurs - utilisation Itérateurs - utilisation


- Tous les conteneurs définissent deux types d’itérateur
#include <list
list>>
// création d’une liste de caractères
- container::::iterator
iterator list<char> coll;
list<char> coll;
 permet de naviguer en mode lecture/écriture
- container::::const_iterator
const_iterator for (char c = ‘a’; c<=‘z’; c++)
coll.push_back
coll.push_back(c);
(c);
 permet de naviguer en mode lecture seulement
Template <typename T> // impression de la liste à l’aide d’un itérateur
class vector {
list<char>::
list<char> ::const_iterator
const_iterator pos;
public: Ainsi, un itérateur pour un vecteur d’entiers
class iterator { sera déclaré de la manière suivante:
... for(pos = coll.begin
coll.begin();
(); pos != coll. end();
coll.end pos++)
(); pos++ )
}; vector<int>::iterator
vector<int> ::iterator iter;
iter ; cout << *pos << ‘ ‘;
...
}; *pos = …; // est illégale !

STL 23 STL 24

4
Chapitre 8 : Les collections STL A.U. : 2009/2010
ENSI – II2

#pragma warning(disable:4786)
map>
#include <map
#include <string>
#include <iostream>
using namespace std;
Itérateurs – catégories
void main()
{
map< int, string > m;
• Bidirectionnel
::iterator it;
map< int, string >::iterator • peut itérer en direction avant (++) et arrière (--
(--))
m.insert(map< int, string >::value_type( 2, "Deux" ));
• type d’itérateur des conteneurs list
list,, set
set,, multiset
multiset,,
m.insert(map< int, string >::value_type( 3, "Trois" )); map et multimap
m.insert(map< int, string >::value_type( 5, "Cinq" ));

cout << "Enter a Number: "; • Accès par index


int num; cin >> num;
find( num );
it = m.find
Le type d’un élément de map est une paire • peut itérer en direction avant (++), arrière (--
(--)) et par
if ( it != m.end
end() ) pair < Key, T > index ([])
->second << endl;
cout << it- • type d’itérateur des conteneurs vector et deque
else
cout << "Element absent" << endl;
}

STL 25 STL 26

Les constructeurs des Conteneurs


séquentiels 2.3. Algorithmes
 Tous les conteneurs séquentiels ont quatre constructeurs  STL fournit plusieurs algorithmes
Conteneurs
pour traiter les éléments des
• vector<T>( ) : conteneurs
• vector<T>(taille) :

Itérateurs
 Ces algorithmes offrent les
• vector<T>(taille, valeur) : services fondamentaux tels que
• vector<T>(itérateur, itérateur) : recherche, tri, copie, modification Algorithmes
 Les conteneurs list et deque ont aussi ces constructeurs  Les algorithmes ne sont PAS des
#include <list> #include <deque> fonctions membres des classes rate
u rs
Itér
ate
urs
Ité
list<char>::iterator it; conteneurs
list<char> L(10,’a’); it=L.begin(); it++; it++;  Ce sont plutôt des fonctions Conteneurs Conteneurs

... deque<char> Q(it, L.end()); globales qui opèrent avec des


itérateurs
STL 27 STL 28

Algorithmes - utilisation Algorithmes - utilisation


#include <vector>
#include <algorithm>
#include <iostream> // trouver l’élément avec la valeur 3
using namespace std; pos = find(coll.begin(), coll.end(), // intervalle
3); // valeur
vector<int> coll;
vector<int>::iterator pos;
// renverser l’ordre des éléments, à partir de celui ayant la
// trouver le minimum et le maximum valeur 3 jusqu’à la fin
pos = min_element
min_element(coll.begin(),
(coll.begin(), coll.end()); sort(pos, coll.end());
cout << "min: " << *pos << endl;
pos = max_element
max_element(coll.begin(),
(coll.begin(), coll.end()); // imprimer
cout << "max: " << *pos << endl; for(pos = coll.begin(); pos!=coll.end()); pos++)
cout << *pos << ‘ ‘;
// tri
sort(coll.begin(),
sort (coll.begin(), coll.end());

STL 29 STL 30

5
Chapitre 8 : Les collections STL A.U. : 2009/2010
ENSI – II2

#include <iostream>
#include <list>
#include <algorithm>
typedef list <char> contChar ;

contChar initC ( char * c )


Algorithmes – problème d’utilisation
{
contChar xxx ;  L’algorithme copy écrase les
#include <list>
while ( *c != ‘\0' ) xxx.push_back ( *c++); éléments de la destination
return xxx ;
#include <vector>
 Or, au moment de l’appel, le
}
list<int> coll1;
vecteur (coll2) est vide
void main ( ) vector<int> coll2;  Dans un tel cas, il faudrait créer
{ les éléments lors de la copie
contChar iom = initC ("Un exemple sur les algo. génériques" );
// insertion d’éléments dans la liste plutôt que d’écraser un élément
iom.sort ( ) ; for (int i=1; i<=9; i++) qui n’existe pas!
iom.unique ( ) ;  Solution:: itérateur adaptateur
Solution
coll1.push_back(i);
for ( contChar::iterator i = iom.begin(); i != iom.end(); i++)
cout << *i ; // copie dans le vecteur (PROBLÈME À L’EXÉCUTION)
L’EXÉCUTION)
copy(coll1.begin(), coll1.end(), // source
cout << "." << endl ;
coll2.begin()); // destination
}
STL 31 STL 32

Itérateurs adaptateurs Itérateurs adaptateurs


Il existe trois types d’itérateurs adaptateurs :  Les deux autre types d’itérateur adaptateur sont
insert:: permet aux algorithmes d’opérer en mode insertion plutôt qu’en mode
insert • reverse: opère en mode renversement (pour afficher à l’envers, par exemple)
reverse:
écrasement
Reprenons le cas de la copie…
• stream:: permet de lire ou d’écrire des «stream» (accès direct au clavier et à l’écran
stream
// copie dans un vector
#include <list>
vector<int> coll2;
void main() {
copy(coll1.begin(), coll1.end(), // source
int arr[] = {1, 4, 9, 16, 25};
back_inserter(coll2));
back_inserter (coll2)); // destination
list<int> liste(arr, arr+5);
reverse_iterator revit;
list<int>::reverse_iterator
// copie dans un deque rbegin();
revit = liste.rbegin
deque<int> coll3; rend())
while (revit != liste.rend
copy(coll1.begin(), coll1.end(), // source #include <vector>
cout << *revit++ << ' '; #include <algorithm>
front_inserter(coll3));
front_inserter (coll3)); // destination }
void main() {
// copie dans un set vector<int> coll;
set<int> coll4;
copy(coll1.begin(), coll1.end(), // source copy(coll.begin(), coll.end(),
inserter(coll4,
inserter (coll4, coll4.begin()); // destination ostream_iterator<int>(cout,"- "));
ostream_iterator<int>
}

STL 33 STL 34

Utilisation de fonctions dans les Utilisation de prédicats dans les


algorithmes algorithmes
 Pour encore plus de flexibilité, certains algorithmes  Un prédicat est une fonction qui retourne une valeur booléenne
permettent l’usage de fonctions définies par l’usager  Les prédicats peuvent être utilisés pour spécifier un critère de
 Les fonctions sont appelées à l’interne par l’algorithme recherche ou de tri
• Exemple
Exemple:: recherche d’un nombre premier
Exemple:: l’algorithme for_each
Exemple for_each,, qui appelle une fonction pour
chaque élément d’un intervalle spécifié
bool estPremier
estPremier(int
(int nombre) // prédicat
// fonction usager
{
void print
print(int
(int elem) { cout << elem << ‘ ‘; }
if (nombre == 0 || nombre == 1) return true;
void main() {
vector<int> coll; int diviseur;
... for(diviseur = nombre /2; nombre %diviseur !=0; diviseur--
diviseur--);
);
for_each(coll.begin(),
for_each (coll.begin(), coll.end(), // intervalle
print);
print ); // opération return (diviseur == 1);
}
}

STL 35 STL 36

6
Chapitre 8 : Les collections STL A.U. : 2009/2010
ENSI – II2

Utilisation de prédicats dans les


algorithmes 3.Foncteurs
 Un foncteur est un objet se class PrintInt {
comportant comme une public:
recherche d’un nombre premier (suite)
fonction (en anglais, function void operator() (int elem) {
object) cout << elem << ‘ ‘;
void main() {  Repose sur la surcharge de }
list<int> coll; l’opérateur ()
};
...
list<int>::iterator pos; void main() {
pos = find_if(coll.begin(), coll.end(), // intervalle vector<int> coll;
estPremier);
estPremier ); // prédicat ...
for_each (coll.begin(), coll.end(), // intervalle
if(pos != coll.end()) // si un nombre a été trouvé PrintInt());
PrintInt()); // objet
cout << *pos; }
}

STL 37 STL 38

Foncteurs - utilisation Foncteurs prédéfinis


 STL contient plusieurs foncteurs couvrant les opérations de base
• Quel est l’avantage d’utiliser un foncteur plutôt qu’une Ex : le traitement numérique
fonction? transform (coll.begin(), coll.end(), // source
coll.begin(), // destination
negate<int>()); // foncteur
• Un foncteur est une fonction intelligente, au même titre
qu’un itérateur est un pointeur intelligent  negate<int>() crée un foncteur unaire qui retourne
• Une même fonction, représentée par un foncteur, peut l’élément négatif de type entier pour lequel il est appelé
avoir plusieurs états
 Ex: le conteneur set trie ses éléments en ordre croissant par défaut.
• Un foncteur peut avoir d’autres fonctions membres et Pour effectuer le tri autrement, on n’a qu’à utiliser un foncteur
attributs
• Chaque foncteur a son propre type set<int> coll; // trie en ordre croissant (par défaut)
set<int, greater<int> > coll; // trie en ordre décroissant

 greater<int> est un foncteur binaire

STL 39 STL 40

Conclusion
 La STL est une bibliothèque efficace pour la
manipulation des collections.
 La STL facilite ainsi l’implémentation des
relations entre classes (agrégation,
composition, association).
 La STL fournit un certain nombre de classes
d'exceptions standard, que les fonctions de la
bibliothèque sont susceptibles de déclencher.

STL 41