Les transparents du cours 3
Transcription
Les transparents du cours 3
Algorithmique, C++ Recollement d'images Introduction à C++ Troisième partie STL Plan de la séance Introduction à la STL Les conteneurs Les itérateurs Quelques algorithmes La STL en bref Standard Template Library : Bibliothèque de Modèles Standards Structures de données évoluées : listes, vecteurs, … (conteneurs) Outils pour parcourir les conteneurs : itérateurs Algorithmes optimisés : fonctions de tri, … Objectif Standardiser les composants usuels Pas besoin de redéfinir une liste, un algorithme de tri, ... Intégrée au compilateur : pour utiliser un composant, ajouter simplement #include <list> (ou #include <vector> ou autre) Généricité : list de int, list de vec de int, etc. Les conteneurs Définition : objet qui contient d'autres objets Implémentation : modèles (templates) paramétrés par le type des objets mémorisés 3 conteneurs de base : les séquences vector<T> // Vecteur : accès à un élt O(1), insertion // ou suppression O(n) (sauf en fin) list<T> // Liste doublement chaînée : insertion ou // suppr. O(1), accès à un élt aléatoire O(n) deque<T> // Double ended queue : intermédiaire entre // les 2, ~ vec avec ajout en tête/queue rapide Autres conteneurs 3 adaptateurs de séquences : stack< T, seq<T> > // Pile (LIFO) queue< T, seq<T> > // File (FIFO) priority_queue< T, seq<T>, cmp<T> > // Tas 4 conteneurs associatifs : map<key, T, cmp> // Dictionnaire multimap<key, T, cmp> // Dictionnaire multiple set<key, cmp> // “Ensemble” multiset<key, cmp> // “Ensemble” multiple Les séquences Méthodes disponibles pour toute séquence : Constructeur de recopie, opérateurs == et != Test si vide : empty(), nb d'éléments : size() Premier/dernier élément : front(), back() Itérateur (sur le premier élément) : begin() Itérateur (sur le dernier élément + 1) : end() Insertion/suppression : push_front() (pas vector), push_back(), pop_front() (pas vector), pop_back(), insert(it,T)(insertion avant it), erase(it), clear() Vecteur Opérateur [] (comme les tableaux) capacity() : nombre d'élts alloués Croissance dynamique : ajout à la fin (push_back) => redimensionnement (capacité * 2), coût O(n) en pire cas mais O(1) amorti Méthode reserve() fixe la capacité ne change pas la taille, seule de la mémoire est allouée) Vecteur : exemple #include <vector> std::vector<int> v; // Création d'un vecteur vide v.push_back(1); // La capacité passe à 1, v = (1) v.push_back(2); // Capacité = 2, v = (1 2) v.push_back(3); // Capacité = 4, v = (1 2 3) v.reserve(5); // Capacité = 5, v = (1 2 3) v.pop_back(); // Capacité = 5, v = (1 2) std::cout << v[1]; // Renvoie 2 std::cout << v.capacity(); // Renvoie 5 Liste Occupation mémoire supérieure à vector (pointeurs en plus) Méthode remove(val) : supprime tous les éléments de valeur val Méthode reverse() : inverse la liste Méthode sort() : trie (de manière stable) selon l'opérateur < Méthode merge(L) : fusionne avec la liste L en triant selon l'opérateur < Liste : exemple #include <list> std::list<int> l; // Création d'une liste vide l.push_back(1); // l = 1 l.push_front(2); // l = 2->1 l.push_back(3); // l = 2->1->3 l.reverse(); // l = 3->1->2 l.sort(); // l = 1->2->3 l.push_front(2); // l = 2->1->2->3 l.remove(2); // l = 1->3 Adaptateurs de séquences Piles, files et tas (files de priorité) Construits à partir d'une séquence : Deque toujours conseillée Vecteur et liste pas toujours possibles Pas d'itérateur sur la structure de données, mais 2 méthodes : push(val) et pop() Accès au premier/dernier élément : top() (pile et tas), front() et back() (file) Pile et file : exemple #include <stack> #include <queue> std::stack<int, deque<int> > pile; std::queue<int, deque<int> > file; pile.push(1); pile.push(2); pile.push(3); file.push(1); file.push(2); file.push(3); std::cout << pile.top() << std::endl; // 3 std::cout << file.front() << std::endl; // 1 pile.pop(); file.pop(); // p = 2->1, f = 2->3 Conteneurs associatifs Collections ordonnées d'éléments Objectif : recherche rapide d'éléments à partir d'une clé Le type de la clé doit posséder un opérateur de comparaison impliquant une relation d'ordre total entre les éléments Triple généricité : type des éléments et type des clés fonction de comparaison des clés Les 4 conteneurs associatifs map<key, T, cmp> : dictionnaire, un seul élément par clé multimap<key, T, cmp> : comme map mais plusieurs éléments par clé set<key, cmp> : “ensemble” : valeurs et clés confondues, on ne conserve que les clés => arbre équilibré de clés multiset<key, cmp> : comme set mais peut contenir plusieurs fois la même clé Conteneurs associatifs : méthodes insert(…), erase(…) : insertion/suppression d'un ou plusieurs éléments find(K) : renvoie un itérateur sur le (premier) élément dont la clé vaut K Toutes ces méthodes sont de complexité au pire logarithmique count(K) : nombre d'éléments de clé K empty(), size(), … Conteneurs associatifs : exemple Opérateur de comparaison des clés : struct compar { bool operator() (const char* s1,const char* s2) { return strcmp(s1,s2) < 0; } }; Utilisation : std::map<const char*, int, compar> nb_jours; nb_jours[“janvier”]=31; nb_jours[“fevrier”]=28; … std::cout << "Février : " << nb_jours[“fevrier”]; Itérateurs Objectif : permettre de parcourir les conteneurs de façon uniforme et générique Principe : généralisation de la notion de pointeur L'expression *i a un sens ((*i).m aussi) Opérateurs disponibles : ==, !=, =, * Les conteneurs créent des itérateurs à l'aide des méthodes begin(), end(), etc. Existent en version const et non const Les différents types d'itérateurs It. séquentiels unidirectionnels (forward_iterator) Disposent seulement de l'opérateur ++ Toutes structures de données de la STL It. séquentiels bidirectionnels (bidirectional_iterator) Disposent des opérateurs ++ et - Séquences et conteneurs associatifs It. à accès direct (random_access_iterator) Disposent des opérateurs ++, -- et [] vector et deque Itérateurs : exemple #include <vector> std::vector<int> v; v.resize(10); // et non reserve ! for (int i=0;i<10;i++) std::cin >> v[i]; for (vector<int>::const_iterator it=v.begin(); it!=v.end(); it++) std::cout << *it << ' '; // Attention v.end() = après dernier élément de v for (vector<int>::iterator it=v.begin(); it! =v.end(); it++) if (*it == 0) { v.erase(it); it--; } // Efface tous les 0 du vecteur. Attention, erase() // déplace le pointeur vers l'élément suivant Algorithmes Composants réalisant des traitements sur ou à partir de conteneurs Exemple 1 : renvoie un itérateur sur le premier élément égal à value template<class Iterator, class T> Iterator find(Iterator first, Iterator last, const T& value); Exemple 2 : tri des élts compris entre first et last template<class RAIterator> // RA = Random Access void sort(RAIterator first, RAIterator last); Autres algorithmes : search, for_each, copy, rotate, min, max, … Un dernier exemple #include <vector> #include <fstream> #include <numeric> std::vector<int> v; ifstream f("notes.txt"); copy(istream_iterator<int>(f), istream_iterator<int>(), back_inserter(v)); sort(v.begin(),v.end()); std::cout << “min/max : ” << v.front() << '-' << v.back() << std::endl; std::cout << “médiane : ” << *(v.begin() +v.size()/2) << std::endl; std::cout << “moyenne : ” << accumulate(v.begin(),v.end(),0.0)/v.size() << std::endl;
Documents pareils
STL
std::cout << myList.front()
<< std::endl;
std::cout << myList.back()
<< std::endl;
Le Traitement des données avec la STL (pdf - David Saint
remplacement, la recherche avec un critère, le tri. Elles peuvent :
• S’appliquent à tous les objets d’un conteneur ou seulement une partie.
• Opérer sur 2 conteneurs de nature différents à conditi...
fichier pdf
v.push_back(string("Denmark")); // et oui un vector s'agrandit sans problème
// (mais ça coûte cher)
// aussi on fait plutôt v.resize( taillenettementplusgrande );
vector