Commençons avec notre vieil ami, le
vector.
Les vector, encore et toujours
Si vous parlez la langue de Shakespeare, vous aurez certainement reconnu dans le nom de ces objets, le mot "vecteur", ces drôles d'objets mathématiques que l'on représente par des flèches. Eh bien, ils n'ont pas énormément de choses en commun !
Les
vector ne sont vraiment pas adaptés pour effectuer des opérations mathématiques. Et en plus, ils n'en ont même pas les caractéristiques. On pourrait dire que c'est un mauvais choix de nom de la part des concepteurs de la STL. Mais bon, il est trop tard pour changer... Vous allez donc devoir vous habituer à ce faux-ami.
Comme vous l'avez vu depuis longtemps, les
vector sont très simples à utiliser. On accède aux éléments via les crochets [], comme pour les tableaux statiques et l'ajout d'éléments à la fin se fait via la méthode
push_back(). En réalité cette méthode est une opération commune à toutes les séquences. Il en est de même pour
pop_back().
Il existe en plus de ça deux méthodes plus rarement utilisées permettant d'accéder au premier et au dernier élément d'un
vector ou de toute autre séquence. Il s'agit des méthodes
front() et
back(). Mais comme il n'est que peu souvent utile d'accéder qu'au premier ou qu'au dernier élément, ces méthodes ne présentent que peu d'intérêt.
Finalement, il existe la méthode
assign() permettant de remplir tous les éléments d'une séquence avec la même valeur.
Récapitulons tout ça dans un tableau.
| Méthode | Description | Mini exemple |
|---|
| push_back() |
Ajout d'un élément à la fin du tableau. |
Code : C++ | vector<int> a(5,3); //Un vector de 5 entiers valant 3
a.push_back(4); //Ajout d'une case avec le nombre 4 à la fin du tableau
|
|
| pop_back() |
Suppression de la dernière case du tableau. |
Code : C++ | vector<int> a(5,3); //Un vector de 5 entiers valant 3
a.pop_back(); //Suppression de la dernière case
|
|
| front() |
Accès à la première case du tableau. |
Code : C++ | vector<int> a(5,3); //Un vector de 5 entiers valant 3
a.front() = 4; //Le premier élément du tableau vaut maintenant 4
|
|
| back() |
Accès à la dernière case du tableau. |
Code : C++ | vector<int> a(5,3); //Un vector de 5 entiers valant 3
a.back() = 4; //Le dernier élément du tableau vaut maintenant 4
|
|
| assign() |
Modifie le contenu d'un tableau. |
Code : C++ | vector<int> a(5,3); //Un vector de 5 entiers valant 3
a.assign(6,2); //Le tableau contient maintenant 6 fois le nombre 2.
|
|
Si vous appelez assign(4,5) sur un vector de 8 éléments, seuls les 4 premiers seront modifiés. Le tableau sera donc plus petit.
En plus des crochets, il est possible d'accéder aux éléments d'un
vector en utilisant des
itérateurs. C'est ce que nous allons découvrir dans le prochain chapitre.
Pour l'instant, tournons-nous vers les autres types de séquences.
Les deque, ces drôles de tableaux
"deque" est en fait un acronyme (bizarre) pour
double ended queue, ce qui donne en français, "queue à deux bouts". Derrière ce nom un peu original se cache un concept très simple : c'est un tableau auquel on peut ajouter des éléments aux deux extrémités.
Les
vector proposent les méthodes
push_back() et
pop_back() pour manipuler ce qui se trouve à la fin du tableau. Modifier ce qui se trouve au début n'est pas possible. Les
deque lèvent cette limitation en proposant des méthodes
push_front() et
pop_front(). Elles sont aussi très simples à utiliser. La seule difficulté vient du fait que le premier élément possède toujours l'indice 0. Les indices sont donc décalés à chaque ajout en début de
deque.
Code : C++ - Ajout d'éléments au début d'une deque 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | #include <deque> //Ne pas oublier !
#include <iostream>
using namespace std;
int main()
{
deque<int> d(4,5); //Une deque de 4 entiers valant 5
d.push_front(2); //On ajoute le nombre 2 au début
d.push_back(8); //Et le nombre 8 à la fin
for(int i(0); i<d.size(); ++i)
cout << d[i] << " "; //Affiche 2 5 5 5 5 8
return 0;
}
|
Et pour bien comprendre le tout, je vous propose un petit schéma :
Même si l'on ajoute des éléments au début d'une
deque, l'indice du premier élément est toujours le 0. Je vous l'ai déjà dit, mais je préfère vous éviter des soucis avec votre compilateur.
Bon, je crois que vous avez compris.

Si vous avez survécu aux premiers chapitres de ce cours, tout ça doit vous sembler bien facile.
Les stack, une histoire de pile
La classe
stack est la première structure de donnée un peu spéciale que vous rencontrez. C'est un conteneur qui n'autorise l'accès qu'au dernier élément ajouté.
En fait, il n'y a que 3 opérations autorisées :
- Ajouter un élément.
- Consulter le dernier élément ajouté.
- Supprimer le dernier élément ajouté.
Cela se fait via les trois méthodes
push(),
top() et
pop().
Je ne comprends pas bien l'intérêt d'un tel stockage !
En termes techniques, on parle de
structure LIFO. Le dernier élément ajouté est le premier à pouvoir être ôté. Comme sur une pile d'assiette ! Vous ne pouvez accéder qu'à la dernière assiette posée sur la pile.
Cela permet d'effectuer des traitements sur les données en ordre inverse de leur arrivée dans la pile. Comme pour les assiettes. La dernière assiette sale sur la pile est la première à être lavée. Alors que celle arrivée en premier (et qui est donc tout en-bas de la pile) sera traitée en dernier.
Un exemple plus informatique serait la gestion d'un stock. On ajoute le nombre d'articles vendus chaque mois à notre pile et on consulte les trois derniers ajouts sans s'occuper du reste pour créer le bilan trimestriel.
Code : C++ - Utilisation d'une pile 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | #include <stack>
#include <iostream>
using namespace std;
int main()
{
stack<int> pile; //Une pile vide
pile.push(3); //On ajoute le nombre 3 à la pile
pile.push(4);
pile.push(5);
cout << pile.top() << endl; //On consulte le sommet de la pile (le nombre 5)
pile.pop(); //On supprime le dernier élément ajouté (le nombre 5)
cout << pile.top() << endl; //On consulte le sommet de la pile (le nombre 4)
return 0;
}
|
Peut-être que vous aurez un jour besoin de ce genre de structures. Repensez alors à ce chapitre !
Les queue, une histoire de file
Les files sont très similaires aux piles (et pas que pour leurs noms !). En termes techniques, on parle de
structure FIFO. La différence ici est que l'on ne peut accéder qu'au premier élément ajouté. Exactement comme dans une file de supermarché. Les gens attendent les uns derrière les autres et la caissière traite les courses de la première personne arrivée. Quand elle a terminé, elle s'occupe de la deuxième et ainsi de suite.
Le fonctionnement est identique à celui des piles. La seule différence est qu'on utilise
front() pour accéder à ce qui se trouve à l'avant de la file au lieu de
top().
Les priority_queue, la fin de l'égalité
Les
priority_queue sont des
queue qui ordonnent leurs éléments. Un peu comme si les clients avec les plus gros paquets de course passaient avant les gens avec seulement un ou deux articles.
Les méthodes sont exactement les mêmes que dans le cas des files simples.
Code : C++ - Utilisation d'une priority_queue 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | #include <queue> //Attention ! queue et priority_queue sont définies dans le même fichier
#include <iostream>
using namespace std;
int main()
{
priority_queue<int> file;
file.push(5);
file.push(8);
file.push(3);
cout << file.top() << endl; //Affiche le plus grand des éléments insérés (le nombre 8)
return 0;
}
|
Les objets stockés dans une priority_queue doivent avoir un opérateur de comparaison (<) surchargé afin de pouvoir être classés !
On utilise par exemple ce genre de structure pour gérer des évènements selon leur priorité. Pensez aux signaux et slots de Qt. On pourrait leur affecter une valeur pour traiter les évènements dans un certain ordre.
Les list, à voir plus tard
Finalement, le dernier conteneur sous forme de séquence est la liste. Cependant, pour les utiliser de manière efficace il faut savoir manipuler les itérateurs, ce que nous apprendrons à faire dans le prochain chapitre. De toute façon, je crois que je vous ai assez parlé de séquences pour le moment. Il est temps de parler d'une tout autre manière de ranger des objets.
