Télécharger la présentation
La présentation est en train de télécharger. S'il vous plaît, attendez
Publié parEdgar Beaudet Modifié depuis plus de 9 années
1
Structures de données IFT-2000 Abder Alikacem La STL du C++. La récursivité Semaine 9 Département d’informatique et de génie logiciel Édition Septembre 2009
2
Première partie Standard Template Library du C++ http://www.sgi.com/tech/stl/
3
STL : Standard Template Library Conteneurs: En C++, une classe contenant un ensemble d’éléments d'un certain type est appelée conteneur. Ce sont donc eux qui contiendront les informations que l’on veut stocker. Itérateurs: utilisés pour parcourir les items qui se retrouvent dans les conteneurs, ils jouent un peu le rôle de pointeurs sur des éléments d’un conteneur. Algorithmes: utilisés pour faire des traitements sur les éléments qui se retrouvent dans les conteneurs.
4
Les conteneurs Les conteneurs sont classés suivant trois types: Séquentiels Adapteurs Associatifs vector Tableau list Liste doublement chaînée slist List simplement chaînée queue File- FIFO (first-in, first-out) stack Pile - LIFO (last in, first out) set Ensemble avec des éléments distincts map Table de hachage
5
Conteneurs - Requis L’élément qui sera inclus dans un conteneur doit posséder: constructeur de recopie opérateur = destructeur un constructeur par défaut un test d’égalité (opérateur ==) un critère d’ordre (operateur < et autres)
6
Conteneurs séquentiels vector: tableau dynamique qui ne se remplit qu’à la fin - extensible - accès aléatoire par index en O(1) - insertions et retraits à la fin en O(1) - insertions et retraits lents au milieu list: liste doublement chaînée - accès au début et à la fin en O(1) - accès lent aux autres éléments Une séquence est un conteneur dans lequel les éléments sont organisés linéairement (il y a un premier, un suivant …, un dernier):
7
Liste (list) et vecteur (vector) Résumé des méthodes communes à vector et list void push back(const Object& x):Ajoute x à la fin du conteneur. Notons que si un objet est ajouté à la fin d'un vecteur alors sa taille est automatiquement augmentée. void pop back(): Enlève le dernier objet du conteneur const Object& back() const: Retourne l'objet situé µa la fin du conteneur const Object& front() const: Retourne l'objet situé au début du conteneur Pour les conteneurs de type list seulement void push front(const Object& x): Ajoute x au début du conteneur void pop front(): Enlève le premier objet du conteneur Pour les conteneurs de type vector seulement Object& operator[] (int i): Retourne l'objet situé à la position i du conteneur Object& at (int i): Comme le précédent mais avec un contrôle de la plage des valeurs. Déclenche une exception out of range lorsqu'un indice est incorrect. void resize( int nouvelle taille): Redéfini la taille du conteneur int capacity() const: Retourne la capacité du conteneur void reserve(int nouvelle capacite): Redéfini la capacité du conteneur
8
STL – L’adaptateur de conteneurs Stack ( la pile ) Dérive d’un deque Principe LIFO : push et pop à la même extrémité Queue ( la file ) Dérive d’un deque Principe FIFO (*)deque: tableau dynamique qui peut s’étendre par les deux extrémités. C’est un des conteneurs séquentiels de la STL
9
STL – L’adaptateur de conteneurs #include using namespace std; stack s; s.push(1); s.pop(); int n = s.size(); if(s.empty()){…} int i = s.top(); Lib « stack » stack est générique Déclaration (pile d’entiers) Empiler Dépiler Taille de la pile Pile vide? Sommet de la pile
10
STL – L’adaptateur de conteneurs #include using namespace std; queue f; int n =f.size(); f.push(10); f.pop(); int tete =f.front(); int fin = f.back(); Lib « queue » queue est générique Déclaration Taille Enfiler Défiler Tête de la file Fin de la file
11
Conteneurs associatifs Deux types de conteneur associatif essentiellement set: les éléments sont triés et ne peuvent apparaître qu’une seule fois La valeur est confondue avec la clé Normalement implémenté en un arbre équilibré, fournit donc un algorithme efficace pour la rercherche d’une valeur map: les éléments sont des paires clé/valeur et triés en fonction de la clé; chaque clé ne peut apparaître qu’une seule fois
12
Les itérateurs Exemple d’itérateur
13
Les itérateurs int c[5] = {3,4,5,6,7}; int* it=&c[0]; int* itFin = &c[5]; //Itérateur de fin de conteneur Tester si on a fini de parcourir le conteneur : it!= itFin void affiche( int* itDebut, int* itFin) { while( itDebut!= itFin) { cout << *itDebut; itDebut++; } } Exemple d’itérateur
14
Les itérateurs Chaque conteneur fourni un type d’itérateur Exemple le type list donne un itérateur de type : list :: iterator. Tous les conteneurs offrent les mêmes fonctions de base permettant aux itérateurs d’accéder aux éléments begin() Retourne un itérateur pointant au premier élément du conteneur end() Retourne un itérateur pointant après le dernier élément du conteneur
15
Les itérateurs #include using namespace std; int main( ) { list list1; for (int i = 1; i<=40; i++) list1.push_back(i+i); list :: iterator i; //reverse_iterator //const_iterator for (i = list1.begin( ); i!=list1.end( ); i++) cout <<*i << “ “ ; return 0 ; }
16
Les algorithmes La STL fournit un nombre important d’algorithmes génériques les plus utilisés, tels que les algorithmes de parcours, de recherche et de tri. Ils s’appliquent sur les conteneurs. Les algorithmes ne sont pas des fonctions membres des classes des conteneurs. Ce sont plutôt des fonctions globales qui opèrent avec des intérateurs. Pour manipuler cette bibliothèque, il suffit d‘incorporer dans l’entête #include Quelques exemples d’algorithmes…
17
Les algorithmes Comparaison élément à élément le contenu de deux conteneurs. equal Compter l’apparition d’une valeur dans une séquence. count Trouver la première occurrence d’une valeur donnée. find for_each Réalise sur tous les éléments l’opération passée en paramètre sort trie les éléments remove Supprimer toutes les occurences d’un élément
18
Les foncteurs Un foncteur est un objet se comportant comme une fonction Repose sur la surcharge de l’opérateur () class PrintInt { public: void operator() (int elem) { cout << elem << “ “; } }; int main() { vector coll;... for_each (coll.begin(), coll.end(), PrintInt()); cout << endl; return 0; }
19
Les foncteurs void ajouter10(int & elem) { elem += 10; } int main() { vector unTableau;... for_each(unTableau.begin(), unTableau.end(), ajouter10);... } template void ajouter(int & elem) { elem += laValeur; } int main() { vector unTableau;... for_each(unTableau.begin(), unTableau.end(), ajouter );... } class Ajouter { public: Ajouter(int v) : laValeur(v) {} void operator()(int&elem)const { elem += laValeur; } private: int laValeur; }; int main() { vector unTableau; … int increment; cin >> increment; for_each(unTableau.begin(), unTableau.end(), Ajouter(increment)); … } …connue à l’exécution …connue à la compilation Valeur connue d’avance Exemple. Ajout d’une valeur à tous les éléments d’un vector
20
Deuxième partie Rappel des notions de base Limitations (suite de Fibonacci) Sous-séquence de somme maximale Backtracking
21
Notions de base Définition Un objet est récursif s'il est défini à partir de lui-même. Une fonction est récursive si elle peut s'appeler elle-même de façon directe ou indirecte. Les règles qui régissent la récursivité 1.Trouver la récursion 2.Présence de cas de base pouvant être résolu sans récursivité 3.Toujours progresser vers le cas de base à chaque appel récursif 4.Vérifier que les appels récursifs progressent réellement vers le cas de base. 5.Ne jamais dédoubler du travail dans des appels récursifs différents (voir la fonction récursive de Fibonacci).
22
Récursivité Structure générale d’une fonction récursive { ! if(/* !condition de convergence */) …; if(/*condition d’arrêt*/) return(/*Ce qu’elle doit retourné*/); else appel récursif } Traitement
23
Fonction récursive factorielle Soit la fonction Factorielle, effectuant l’opération n! Règle récursive : fact(n) = n * fact (n-1) Condition d’arrêt : fact (0) =1 Condition de convergence: n 0 int fact (int n){ if (n < 0) throw logic_error( Fact:argument < 0 ); if (n = = 0) return 1; else return (n * fact (n-1)); }
24
Avantages et inconvénients Solution naturelle et facile à concevoir si la fonction est récursive quand la structure de données traitée est récursive Avantages Formulation compacte, claire et élégante. Désavantages Possibilité de grande occupation de la mémoire. Temps d'exécution peut être plus long.
25
Limitations: Fonction récursive Fibonnacci long fibo (long valeur) { if (valeur< 0) throw logic_error( Fibo:argument < 0 ); if (valeur <= 1) return valeur; else return(fibo(valeur-1) + fibo(valeur-2)); } Soit la fonction Fibo (Fibonacci), effectuant l’opération f(n) = f(n-1) + f(n-2)
26
Exécution de Fibonnacci Soit les appels effectués pour fibo(n) : fibo(n) fibo(n-2) fibo(n-4) fibo(n-6)fibo(n-5) fibo(n-3) fibo(n-1) fibo(n-2)fibo(n-3) Règle 5: Ne jamais dupliquer le travail par la résolution d’une même instance d’un problème dans plusieurs appels récursifs. fibo(n-3) fibo(n-4)
27
Champs d'application des algorithmes récursifs Structures de données définies récursivement (listes, arbres, etc..) Équations de récurrence; Rétroaction ("backtracking"). … Nous allons voir ensemble quelques exemples typiques impliquant la récursivité.
28
Sous-séquence de somme maximale Définition (rappel du laboratoire#1): Étant donnée des entiers (possiblement négatifs) A 1, A 2,..., A N, trouver et identifier la séquence correspondante à la valeur maximale de. Résolution (algorithme#4): Application de la technique de diviser et régner (divide-and-conquer), une Méthode de résolution de problèmes basée sur la récursivité: Diviser en plusieurs sous problèmes résolus récursivement. régner, où la solution du problème original est composé de la solution des sous-problèmes.
29
Sous-séquence de somme maximale Rappel. Algorithme #1 Entrée : séquence de n nombres Sortie : la sous-séquence (debut, fin, somme) de somme maximale sousSequence = (0, 0, sequence[0]) //initialisation for i = 0 to n-1 for j = i to n-1 { somme = 0 for k = i to j somme = somme + sequence[k] Si somme > sousSequence.somme sousSequence = (i, j, somme) } Chercher pour tous les débuts possibles, et pour toutes les fins possibles pour un tel début (sans répétition). La boucle la plus intérieure est inutile car pour calculer la somme à "position+1", il suffit d'ajouter sequence[position+1] à l'ancienne somme.
30
Sous-séquence de somme maximale Rappel. Algorithme #2 Entrée : séquence de n nombres Sortie : la sous-séquence (debut, fin, somme) de somme maximale sousSequence = (0, 0, sequence[0]) //initialisation for i = 0 to n-1 { somme = 0 for j = i to n-1 { somme = somme + sequence[j] if (somme > sousSequence.somme) sousSequence = (i, j, somme) }
31
Sous-séquence de somme maximale Rappel. Algorithme #3 On cherche un maximum. Si on trouve une sous-séquence initiale de somme inférieure (ou égale) à 0, on peut ignorer cette sous-séquence car elle apporte moins à la somme totale que de commencer juste après elle. Entrée : séquence de n nombres Sortie : la sous-séquence (debut, fin, somme) de somme maximale sousSequence = (0, 0, sequence[0]) //initialisation i=0; somme = 0 for j = 0 to n-1 { somme = somme + sequence[j] if (somme > sousSequence.somme) sousSequence = (i, j, somme) if (somme <= 0) { i = j + 1; somme = 0; } } 4, -1, 34, -5, 3
32
Sous-séquence de somme maximale Algorithme #4. Cas possibles: Cas 1: La séquence est situé dans la première moitié. Cas 2: La séquence est situé dans la deuxième moitié. Cas 3: La séquence commence dans la première moitié et se termine dans la deuxième moitié. Sommaire de l’algorithme: 1.Déterminer récursivement la sous-séquence de somme maximale uniquement dans la première moitié. 2.Déterminer récursivement la sous-séquence de somme maximale uniquement dans la deuxième moitié. 3.Avec deux boucles consécutives, déterminer la sous-séquence de somme maximale qui débute dans la première moitié et qui termine dans la deuxième moitié. 4.Choisir la somme la plus élevée des trois.
33
SousSequence trancheMax4(Sequence t, int d, int f) { SousSequence rep = { 0, 0, t[0] }; int m = (d+f)/2; if(d==f){rep.debut=d; rep.fin=f; rep.somme= t[d]; return rep;} Sousequence sm1 = trancheMax4(t, d, m); Sousequence sm2 = trancheMax4(t, m+1, f); int s1=t[m]; int s1m=s1; int dmg=m; for(int k = m-1; k>=d; --k) { s1+=t[k]; if(s1>s1m){s1m=s1; dmg=k;} } int s2=t[m+1]; int s2m=s2; int dmd=m+1; for(int k = m+2; k<=f; ++k){ s2+=t[k]; if(s2>s2m){s2m=s2; dmd=k;} } int sm3 = s1m+s2m; if(sm1.somme>=sm2.somme && sm1.somme>=sm3){ return sm1;} if(sm2.somme>=sm1.somme && sm2.somme>=sm3){ return sm2;} rep.debut= dmg; rep.fin = dmd; rep.somme= sm3; return rep; }
34
Sous-séquence de somme maximale (Exemple) 32-50 2 32-50 2 32-50 2 2-50 2 2 3 2 -5 0 012 000 -5 max(2,-5,2-5) 2 max(3,2,3+2) 3 0 max(-1,0,-1+0) 2 max(-1,2,-1+2) max(0,2,0+1) max(5,2,0+0 )=5
35
Algorithme à essais successifs (AES) Problématique Pour résoudre certains types de problèmes, il peut être souvent utile de procéder à l'exploration systématique des différentes solutions possibles. Il est donc essentiel de développer des techniques algorithmiques qui permettent une telle exploration. AES ou encore algorithme de back tracking idée : construire progressivement une solution à un problème donné en essayant toutes les possibilités à chaque étape de la construction. Remarque : la complexité de ce genre d ’algorithme est de nature exponentielle => à utiliser si l ’on n ’en connaît pas de meilleur. Exemple: calcul du trajet d’un robot dans un labyrinthe. Il s'agit de concevoir un algorithme qui permet à un robot de trouver un chemin menant à la sortie d'un labyrinthe. Pour ce faire le robot explore systématiquement les quatre directions vers lesquelles il peut se déplacer. De plus, afin d'éviter que le robot ne se retrouve sur des cases déjà explorées chacune de celles-ci seront marquées à mesure qu'elles sont visitées. C'est de façon récursive que les cases faisant partie du chemin seront identifiées.
36
Programmation du trajet d’un robot mobile #define Y 9 /* Les dimensions du labyrinthe */ #define X 7 char laby[X][Y] = { {'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'}, {'X', ' ', ' ', 'X', ' ', ' ', ' ', ' ', 'X'}, {'X', ' ', 'X', 'X', ' ', 'X', 'X', ' ', 'X'}, {'X', ' ', ' ', ' ', ' ', ' ', 'X', 'X', 'X'}, {'X', 'X', 'X', ' ', 'X', ' ', 'X', ' ', 'X'}, {'X', 's', ' ', ' ', ' ', ' ', ' ', ' ', 'X'}, {'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'}}; int main() { int i, j; bool Parcours(int x, int y); if (Parcours(1,1)) {// Imprimer le résultat de la recherche for (i = 0; i < X; i++, cout<<endl) for (j = 0; j < Y; j++) cout<<laby[i][j]; } else cout<<"Il n'existe aucun chemin.\n"; return 0; }
37
Retour en arrière - Exemple Utiliser des appels récursifs et l’ordre d’appel suivant: Nord Sud Est Ouest 0123456789 A B S C D E F E G H I J
38
Retour en arrière - Exemple 0123456789 A B S C D E F E G H I J bool Parcours(int x, int y) { if (laby[x][y] == 's') { laby[x][y] = 'S'; return true; } else if (laby[x][y] == ' ') { laby[x][y] = 'o'; if (Parcours(x-1, y)) return(true); else if (Parcours(x+1, y)) return(true); else if (Parcours(x, y+1)) return(true); else if (Parcours(x, y-1)) return(true); else laby[x][y] = '-'; } return false; }
39
Retour en arrière - réponse 0123456789 A B C D E F G H I J X E S oo o o ooX X o o o o o ooo o oX o oo o ooo o o o oo oX Xo o
40
Structures de données IFT-2000 Abder Alikacem Semaine 10 Les algorithmes de recherche Département d’informatique et de génie logiciel Édition septembre 2009
41
Les algorithmes de recherche Les algorithmes de recherche La recherche séquentielle La recherche dichotomique Complexité des algorithmes de recherche Recherche dichotomique et arborescence
42
La recherche séquentielle 314281412116910 meilleur cas=O(1) pire cas=O(n) en moyenne= O(n/2) absences=O(n) Données pas triées 123468910111214 meilleur cas=O(1) pire cas=O(n) en moyenne= O(n/2) absences=O(n/2) Données triées
43
Modèles d’implantation tableau : liste chaînée : 123468910111214 123468910111214
44
La recherche binaire implantation en tableau = accès direct à n’importe quel élément en regardant tout de suite au milieu, on peut éliminer la moitié des données 123468910111214
45
La recherche binaire 123468910111214 100
46
La recherche binaire 123468910111214 1005
47
La recherche binaire 123468910111214 1005
48
La recherche binaire 123468910111214 1005
49
La recherche binaire : 10 ? 123468910111214 1005
50
La recherche binaire : 10 ? 123468910111214 1005
51
La recherche binaire : 10 ? 123468910111214 123468910111214 1005 6
52
La recherche binaire : 10 ? 123468910111214 123468910111214 1005 6 8
53
La recherche binaire : 10 ? 123468910111214 123468910111214 1005 6 8
54
La recherche binaire : 10 ? 123468910111214 123468910111214 1005 6 8
55
La recherche binaire : 10 ? 123468910111214 123468910111214 123468910111214 1005 6 8 67
56
La recherche binaire : 10 ? 123468910111214 123468910111214 123468910111214 1005 6 8 67
57
La recherche binaire : 10 ? 123468910111214 123468910111214 123468910111214 1005 6 8 67
58
La recherche binaire : 10 ? 123468910111214 123468910111214 123468910111214 1005 6 8 67 1234689 111214 7
59
La recherche binaire : 10 ? 123468910111214 123468910111214 123468910111214 1005 6 8 67 1234689 111214 7
60
La recherche binaire : 9.5 ? 123468910111214 123468910111214 123468910111214 1005 6 8 67 1234689 111214 7 recherche séquentielle : (données triées) données présentes : O(n/2) données absentes : O(n/2) recherche binaire : (données triées) données présentes : O(log n) données absentes : O(log n) Tableau comparatif
61
Modèles d’implantation tableau : liste chaînée ? 123468910111214 123468910111214 100
62
Structures pointées 123468910111214 012345678910
63
Structures pointées 123468910111214 012345678910
64
Structures pointées 123468910111214 012345678910
65
Structures pointées 12346 8 910111214 01234678910
66
Structures pointées 12346 8 910111214 01234678910
67
Structures pointées 12346 8 910111214 01234678910
68
Structures pointées 12 3 46 8 910 11 1214 013467910
69
Structures pointées 12 3 46 8 910 11 1214 013467910
70
Structures pointées 12 3 46 8 910 11 1214 013467910
71
Structures pointées 1 2 3 4 6 8 9 10 11 12 14
72
Structures pointées 1 2 3 4 6 8 9 10 11 12 14
73
Structures pointées 1 2 3 4 6 8 9 10 11 12 14
74
Arbre binaire ! 1 2 3 4 6 8 9 10 11 12 14
75
Arbre = index 1 2 3 4 6 8 9 10 11 12 14
Présentations similaires
© 2024 SlidePlayer.fr Inc.
All rights reserved.