Tableaux dynamiques avec vector - The IC Home Page is in:ic.epfl.ch

Transcription

Tableaux dynamiques avec vector - The IC Home Page is in:ic.epfl.ch
Tableaux dynamiques avec vector
Tableaux statiques
Les tableaux que nous avons vus jusqu'ici sont des tableaux statiques:
int tab[3];
Cette forme de tableaux vient du langage C, et est encore très utilisée.
Cependant, elle n'est pas très pratique. En particulier:
•  un tableau de cette forme ne connaît pas sa taille.
•  on ne peut pas faire d'affectation globale, par exemple on ne peut
pas faire:
int T1[3] = {1, 9, 2};
int T2[3];
T2 = T1;
•  une fonction ne peut pas retourner de tableaux.
La classe vector
Le C++ a introduit la classe vector, qui n'a pas ces inconvénients.
Un tableau de 3 éléments de type int peut se déclarer ainsi:
vector<int> tab(3);
on peut accéder aux éléments de tab de la même façon qu'on
accéderait aux éléments d'un tableau statique du C:
tab[0] = 4;
Il faut ajouter la ligne
#include <vector>
au début du programme pour pouvoir utiliser la classe vector.
La classe vector
type des éléments
vector<int> tab(3);
nombre d'éléments
attention à ne pas l'oublier. Si on fait:
vector<int> tab;
le tableau n'a pas d'éléments, et essayer d'accéder à
un élément, comme par exemple:
tab[0] = 0;
générera sans doute un Segmentation fault
La classe vector
vector<int> tab(3);
On peut aussi faire:
vector<int> tab(3, 1);
pour initialiser tous les éléments du tableau à 1 au moment de la
déclaration.
et:
vector<int> tab2(tab);
pour initialiser les éléments de tab2 aux mêmes valeurs que tab.
Il suffit de changer int pour changer le type des éléments:
vector<double> tab3(5);
vector<bool> tab4(128);
La classe vector
vector<int> tab(3);
On peut maintenant connaître le nombre d'éléments de tab en
utilisant la fonction size():
int taille = tab.size();
On peut faire des affectations globales, par exemple:
tab[0] = 1;
tab[1] = 9;
tab[2] = 2;
vector<int> tab2(3);
tab2 = tab;
vector en paramètre d'une fonction
void initialise(vector<int> & T)
{
for(int i(0); i < T.size(); ++i) {
T[i] = rand() % 100;
}
}
...
vector<int> tab(3);
initialise(tab);
pas besoin de passer la
taille du tableau en
paramètre, il suffit d'utiliser
la fonction size()
vector en résultat d'une fonction
vector<int> premiers_carres(int n)
{
vector<int> T(n);
for(int i(0); i < n; ++i) {
T[i] = i * i;
}
return T;
}
possible uniquement parce que T est déclaré
en vector.
Pas possible si T avait été déclaré avec:
int T[10];
...
vector<int> tab = premiers_carres(10);
vector<int> premiers_carres(int n)
{
vector<int> T(n);
for(int i(0); i < n; ++i) {
T[i] = i * i;
}
return T;
}
...
vector<int> tab = premiers_carres(10);
10
vector<int> premiers_carres(int n)
{
vector<int> T(n);
for(int i(0); i < n; ++i) {
T[i] = i * i;
}
return T;
}
...
vector<int> tab = premiers_carres(10);
T
10
vector<int> premiers_carres(int n)
{
vector<int> T(n);
for(int i(0); i < n; ++i) {
T[i] = i * i;
}
return T;
}
...
vector<int> tab = premiers_carres(10);
?
?
?
?
?
?
?
?
?
?
T
10
vector<int> premiers_carres(int n)
{
vector<int> T(n);
for(int i(0); i < n; ++i) {
T[i] = i * i;
}
return T;
}
...
vector<int> tab = premiers_carres(10);
0
1
4
9
16
25
36
49
64
81
vector<int> premiers_carres(int n)
{
vector<int> T(n);
for(int i(0); i < n; ++i) {
T[i] = i * i;
}
return T;
}
0
1
...
4
9
16
25
vector<int> tab = premiers_carres(10);
36
49
64
81
vector<int> premiers_carres(int n)
{
vector<int> T(n);
for(int i(0); i < n; ++i) {
tab
?
T[i] = i * i;
}
?
return T;
?
}
0
1
...
4
9
16
25
vector<int> tab = premiers_carres(10);
36
49
64
81
?
?
?
?
?
?
?
vector<int> premiers_carres(int n)
{
vector<int> T(n);
for(int i(0); i < n; ++i) {
T[i] = i * i;
tab
0
}
1
return T;
4
}
9
16
...
vector<int> tab = premiers_carres(10);
25
36
49
64
81
Elements de type string
On peut déclarer un tableau dont les éléments sont de type string:
vector<string> noms(5);
On peut initialiser un élément en faisant par exemple:
noms[1] = "Dupont";
et l'afficher en faisant:
cout << noms[1] << endl;
Accéder à un caractère d'un des
éléments
vector<string> noms(5);
noms[1] = "Dupont";
Rappel: Si mot est déclaré avec:
string mot = "Dupont";
char c = mot[2];
met le caractère p dans la variable c.
Pour accéder au troisième caractère de noms[1], on fera donc:
char c = noms[1][2];
de type string
Elements de type vector
On peut aussi déclarer un tableau dont les éléments sont eux-même
de type vector:
vector< vector<double> > M(5);
Elements de type vector
On peut aussi déclarer un tableau dont les éléments sont eux-même
de type vector:
vector< vector<double> > M(5);
attention à laisser un espace (au moins) entre le premier >
et le deuxième > !
Si on fait
vector< vector<double>> M(5);
le compilateur pense que les deux > successifs
représentent l'opérateur >> utilisé généralement avec cin
Elements de type vector
On peut aussi déclarer un tableau dont les éléments sont eux-même
de type vector:
vector< vector<double> > M(5);
M est un tableau de 5 éléments.
Chaque élément est un tableau.
Plus exactement, chaque élément est un tableau vide.
M
Initialiser un element de type vector
vector< vector<double> > M(5);
On peut faire:
M(0) = vector<double>(3);
pour initialiser le premier élément à un tableau
de 3 éléments.
M
Initialiser un element de type vector
vector< vector<double> > M(5);
M[0] = vector<double>(3);
M[0] est maintenant un tableau de 3 éléments.
M[0][1] est l'élément d'indice 1 du tableau M[0]
M
Tableau de tableaux
Si on fait:
vector< vector<double> > M(5);
M[0] = vector<double>(3);
M[1] = vector<double>(2);
M[2] = vector<double>(5);
M[3] = vector<double>(3);
M[4] = vector<double>(2);
on obtient le tableau de tableaux:
M
Tableau de tableaux
cas particulier:
vector< vector<double> > M(5);
for(int i(0); i < 5; ++i) {
M[i] = vector<double>(3);
}
M
Tableau de tableaux
Cas particulier:
vector< vector<double> > M(5);
for(int i(0); i < 5; ++i) {
M[i] = vector<double>(3);
M
}
M[i][j] est l'élément d'indice j du tableau
d'indice i
on peut représenter M plus simplement:
M[2][1]
Initialiser les éléments à 0
Pour initialiser tous les éléments des tableaux de M, il faut utiliser deux boucles for
imbriquées:
for(int i(0); i < M.size(); ++i) {
for(int j(0); j < M[i].size(); ++j) {
M[i][j] = 0;
}
}
Pas-à-pas
0
i
for(int i(0); i < M.size(); ++i) {
for(int j(0); j < M[i].size(); ++j) {
M[i][j] = 0;
}
}
M[i].s
ize()1
M
0
1
2
0
?
?
?
?
1
?
?
?
?
?
?
?
?
...
...
M.size
()-1
Pas-à-pas
0
0
i
j
for(int i(0); i < M.size(); ++i) {
for(int j(0); j < M[i].size(); ++j) {
M[i][j] = 0;
}
}
M[i]
.siz
e()1
M
0
1
2
0
?
?
?
?
1
?
?
?
?
?
?
?
?
...
...
M.size
()-1
Pas-à-pas
0
0
i
j
for(int i(0); i < M.size(); ++i) {
for(int j(0); j < M[i].size(); ++j) {
M[i][j] = 0;
}
}
M
0
1
2
0
0
?
?
?
1
?
?
?
?
?
?
?
?
...
M[i].si
ze()-1
...
M.size
()-1
Pas-à-pas
0
1
i
j
for(int i(0); i < M.size(); ++i) {
for(int j(0); j < M[i].size(); ++j) {
M[i][j] = 0;
}
}
M
0
1
2
0
0
?
?
?
1
?
?
?
?
?
?
?
?
...
M[i].si
ze()-1
...
M.size(
)-1
Pas-à-pas
0
1
i
j
for(int i(0); i < M.size(); ++i) {
for(int j(0); j < M[i].size(); ++j) {
M[i][j] = 0;
}
}
M
0
1
2
0
0
0
?
?
1
?
?
?
?
?
?
?
?
...
M[i].si
ze()-1
...
M.size(
)-1
Pas-à-pas
0
i
for(int i(0); i < M.size(); ++i) {
for(int j(0); j < M[i].size(); ++j) {
M[i][j] = 0;
}
}
M[i].size()
j
M
0
1
2
0
0
0
0
?
1
?
?
?
?
?
?
?
?
...
M[i].si
ze()-1
...
M.size(
)-1
Pas-à-pas
0
i
for(int i(0); i < M.size(); ++i) {
for(int j(0); j < M[i].size(); ++j) {
M[i][j] = 0;
}
}
M[i].size()
j
M
0
1
2
0
0
0
0
0
1
?
?
?
?
?
?
?
?
...
M[i].si
ze()-1
...
M.size(
)-1
Pas-à-pas
0
i
for(int i(0); i < M.size(); ++i) {
for(int j(0); j < M[i].size(); ++j) {
M[i][j] = 0;
}
}
M
0
1
2
0
0
0
0
0
1
?
?
?
?
?
?
?
?
...
M[i].si
ze()-1
...
M.size(
)-1
Pas-à-pas
1
i
for(int i(0); i < M.size(); ++i) {
for(int j(0); j < M[i].size(); ++j) {
M[i][j] = 0;
}
}
M
0
1
2
0
0
0
0
0
1
?
?
?
?
?
?
?
?
...
M[i].si
ze()-1
...
M.size(
)-1
Pas-à-pas
1
0
i
j
for(int i(0); i < M.size(); ++i) {
for(int j(0); j < M[i].size(); ++j) {
M[i][j] = 0;
}
}
M
0
1
2
0
0
0
0
0
1
?
?
?
?
?
?
?
?
...
M[i].si
ze()-1
...
M.size(
)-1
Pas-à-pas
1
0
i
j
for(int i(0); i < M.size(); ++i) {
for(int j(0); j < M[i].size(); ++j) {
M[i][j] = 0;
}
}
M
0
1
2
0
0
0
0
0
1
0
?
?
?
?
?
?
?
...
M[i].si
ze()-1
...
M.size(
)-1
Affichage: Raisonner sur un exemple
Considérons le cas particulier où M.size() vaut 3 et M[i].size() vaut 2:
Si l'on fait:
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << endl;
}
}
le tableau sera affiché sur une seule longue colonne:
8
3
9
7
12
5
M
0
1
0
8
3
1
9
7
2 12
5
Raisonner sur un exemple
Si on veut afficher le tableau M avec 3 lignes et 2 colonnes:
8 3
9 7
12 5
on pourrait l'afficher sans utiliser de boucles en écrivant:
cout << M[0][0] << " " << M[0][1] << endl;
cout << M[1][0] << " " << M[1][1] << endl;
cout << M[2][0] << " " << M[2][1] << endl;
Afficher une ligne avec une boucle
L'affichage d'une ligne
cout << M[0][0] << " " << M[0][1] << endl;
peut se décomposer en:
cout << M[0][0] << " ";
cout << M[0][1] << " ";
cout << endl;
qui peut s'écrire avec une boucle for:
for(int j(0); j < 2; ++j) {
cout << M[0][j] << " ";
}
cout << endl;
L'instruction
cout << endl;
n'est pas contenue dans la boucle.
Elle est exécutée après.
Afficher plusieurs lignes
Pour afficher toutes les lignes, il suffit d'inclure le code qui affiche une ligne:
for(int j(0); j < 2; ++j) {
cout << M[0][j] << " ";
}
cout << endl;
dans une seconde boucle for.
Le 0 correspondait au numéro de la ligne à afficher, il faut donc le remplacer
par la variable compteur de cette seconde boucle for, ici i:
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
Généraliser
Le cas particulier est valable pour M.size() = 3 et M[i].size() = 2:
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
Le cas général est facile à écrire maintenant:
for(int i(0); i < M.size(); ++i) {
for(int j(0); j < M[i].size(); ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
Pas-à-pas
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
M
1
0
8
3
1
9
7
2 12
0
♦
0
i
5
Pas-à-pas
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
♦
M
0
1
0
8
3
1
9
7
2 12
0
0
i
j
5
Pas-à-pas
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
8 ♦
M
0
1
0
8
3
1
9
7
2 12
0
0
i
j
5
Pas-à-pas
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
8 ♦
M
0
1
0
8
3
1
9
7
2 12
0
1
i
j
5
Pas-à-pas
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
8 ♦
M
0
1
0
8
3
1
9
7
2 12
0
1
i
j
5
Pas-à-pas
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
8 3 ♦
M
0
1
0
8
3
1
9
7
2 12
0
1
i
j
5
Pas-à-pas
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
8 3 ♦
M
0
1
0
8
3
1
9
7
2 12
0
2
i
j
5
Pas-à-pas
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
M
1
0
8
3
1
9
7
2 12
0
8 3
♦
0
i
5
Pas-à-pas
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
M
1
0
8
3
1
9
7
2 12
1
8 3
♦
0
i
5
Pas-à-pas
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
8 3
♦
M
0
1
0
8
3
1
9
7
2 12
1
0
i
j
5
Pas-à-pas
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
8 3
9 ♦
M
0
1
0
8
3
1
9
7
2 12
1
0
i
j
5
Pas-à-pas
for(int i(0); i < 3; ++i) {
for(int j(0); j < 2; ++j) {
cout << M[i][j] << " ";
}
cout << endl;
}
8 3
9 7
12 5
♦
M
0
1
0
8
3
1
9
7
2 12
5
Tableau de tableaux en résultat d'une fonction
vector< vector<int> > initialise2D(int n, int m)
{
vector< vector<int> > resultat(n);
for(int i(0); i < n; ++i) {
resultat[i] = vector<int>(m);
for(int j(0); j < m; ++j) {
resultat[i][j] = rand() % 100;
}
}
return resultat;
}
...
vector< vector<int> > T = initialise(2, 3);
vector< vector<int> > initialise2D(int n, int m)
{
vector< vector<int> > resultat(n);
for(int i(0); i < n; ++i) {
resultat[i] = vector<int>(m);
for(int j(0); j < m; ++j) {
resultat[i][j] = rand() % 100;
}
}
return resultat;
}
...
vector< vector<int> > T = initialise(2, 3);
2
3
vector< vector<int> > initialise2D(int n, int m)
{
vector< vector<int> > resultat(n);
for(int i(0); i < n; ++i) {
resultat[i] = vector<int>(m);
for(int j(0); j < m; ++j) {
resultat[i][j] = rand() % 100;
}
}
return resultat;
}
...
vector< vector<int> > T = initialise(2, 3);
2
3
vector< vector<int> > initialise2D(int n, int m)
{
vector< vector<int> > resultat(n);
for(int i(0); i < n; ++i) {
resultat[i] = vector<int>(m);
for(int j(0); j < m; ++j) {
resultat[i][j] = rand() % 100;
}
}
return resultat;
}
...
vector< vector<int> > T = initialise(2, 3);
resultat
2
3
vector< vector<int> > initialise2D(int n, int m)
{
vector< vector<int> > resultat(n);
for(int i(0); i < n; ++i) {
resultat[i] = vector<int>(m);
for(int j(0); j < m; ++j) {
resultat[i][j] = rand() % 100;
}
}
return resultat;
}
...
vector< vector<int> > T = initialise(2, 3);
resultat
2
3
vector< vector<int> > initialise2D(int n, int m)
{
vector< vector<int> > resultat(n);
for(int i(0); i < n; ++i) {
resultat[i] = vector<int>(m);
for(int j(0); j < m; ++j) {
resultat[i][j] = rand() % 100;
}
}
return resultat;
}
...
vector< vector<int> > T = initialise(2, 3);
resultat
2
3
vector< vector<int> > initialise2D(int n, int m)
{
vector< vector<int> > resultat(n);
for(int i(0); i < n; ++i) {
resultat[i] = vector<int>(m);
for(int j(0); j < m; ++j) {
resultat[i][j] = rand() % 100;
}
}
return resultat;
}
...
vector< vector<int> > T = initialise(2, 3);
resultat
34 45 81
2
3
vector< vector<int> > initialise2D(int n, int m)
{
vector< vector<int> > resultat(n);
for(int i(0); i < n; ++i) {
resultat[i] = vector<int>(m);
for(int j(0); j < m; ++j) {
resultat[i][j] = rand() % 100;
}
}
return resultat;
}
...
vector< vector<int> > T = initialise(2, 3);
resultat
34 45 81
2
3
vector< vector<int> > initialise2D(int n, int m)
{
vector< vector<int> > resultat(n);
for(int i(0); i < n; ++i) {
resultat[i] = vector<int>(m);
for(int j(0); j < m; ++j) {
resultat[i][j] = rand() % 100;
}
}
return resultat;
}
...
vector< vector<int> > T = initialise(2, 3);
resultat
34 45 81
2
3
vector< vector<int> > initialise2D(int n, int m)
{
vector< vector<int> > resultat(n);
for(int i(0); i < n; ++i) {
resultat[i] = vector<int>(m);
for(int j(0); j < m; ++j) {
resultat[i][j] = rand() % 100;
}
}
return resultat;
}
...
vector< vector<int> > T = initialise(2, 3);
resultat
34 45 81
12 90 31
2
3
vector< vector<int> > initialise2D(int n, int m)
{
vector< vector<int> > resultat(n);
for(int i(0); i < n; ++i) {
resultat[i] = vector<int>(m);
for(int j(0); j < m; ++j) {
resultat[i][j] = rand() % 100;
}
}
return resultat;
}
...
vector< vector<int> > T = initialise(2, 3);
resultat
34 45 81
12 90 31
vector< vector<int> > initialise2D(int n, int m)
{
vector< vector<int> > resultat(n);
for(int i(0); i < n; ++i) {
resultat[i] = vector<int>(m);
for(int j(0); j < m; ++j) {
resultat[i][j] = rand() % 100;
}
}
return resultat;
}
...
34
45
81
vector< vector<int> > T = initialise(2, 3);
12
90
31
vector< vector<int> > initialise2D(int n, int m)
{
vector< vector<int> > resultat(n);
for(int i(0); i < n; ++i) {
resultat[i] = vector<int>(m);
for(int j(0); j < m; ++j) {
resultat[i][j] = rand() % 100;
}
}
return resultat;
}
...
vector< vector<int> > T = initialise(2, 3);
T
34 45 81
12 90 31
Exercice
Écrire la fonction d'en-tête:
vector< vector<char> > triangle(int n)
qui retourne un tableau de n tableaux de n éléments chacun, initialisé à:
- - - - - - . + . . . . |
. . + . . . |
. . . + . . |
. . . . + . |
. . . . . + |
. . . . . . |