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é à: - - - - - - . + . . . . | . . + . . . | . . . + . . | . . . . + . | . . . . . + | . . . . . . |