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.

Slides:



Advertisements
Présentations similaires
Cours n° 7 Standard Template Library II.
Advertisements

Cours n° 6 Standard Template Library I.
Structures de données et complexité
Structures de données et complexité LIFO – FILO – FIFO – etc…
Au programme du jour …. Un peu plus de structures de données
Sensibilisation à l’Algorithmique et structure de données
Cours n° 9 Conception et Programmation à Objets
Cours n° 8 Conception et Programmation à Objets
La programmation générique avec la STL EIUMLV - Informatique et Réseaux 99 Benoît ROMAND.
Approfondissement du langage
ALGORITHMES RECURSIFS
Structures collectives en Java
Structures de données linéaires
IPA – Catherine Faron Zucke et Anne Marie Deryr. suite ordonnée d'éléments de taille variable ArrayList liste; liste = new ArrayList (); Ne peuvent contenir.
Récursivité.
Algorithmique et Programmation
II. Chaînage, SDD séquentielles
Les algorithmes: complexité et notation asymptotique
Leçon 6 : Structures de données dynamiques IUP 2 Génie Informatique Méthode et Outils pour la Programmation Françoise Greffier.
Bibliothèque standard du C++
Introduction au paradigme objet Concepts importants surcharge (overload) redéfinition (override) Définition d’une classe Définition des attributs.
Standard Template Library (STL)
Structures de données IFT-2000
Traiter des Données avec la STL
Structures de données IFT Abder Alikacem La classe vector Édition Septembre 2009 Département dinformatique et de génie logiciel.
Les pointeurs Modes d’adressage de variables. Définition d’un pointeur. Opérateurs de base. Opérations élémentaires. Pointeurs et tableaux. Pointeurs et.
Abder Alikacem Semaine 13 La récursivité
Structures de données IFT Abder Alikacem La classe string Département dinformatique et de génie logiciel Édition Septembre 2009 Département dinformatique.
Structures de données IFT-2000
Structures de données IFT-2000
Structures de données IFT-2000
Structures de données IFT-2000 Abder Alikacem Standard Template library Édition Septembre 2009 Département dinformatique et de génie logiciel.
Structures de données IFT Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009.
Structures de données IFT-2000
Structures de données IFT-10541
Programme de baccalauréat en informatique Programmation Orientée Objets IFT Thierry EUDE Module 7 : Classes et fonctions paramétrables Département.
Conteneurs STL.
Présentation Structures de Données et TDA
Standard Template Library
Leçon 1 : notion dobjet IUP Génie Informatique Besançon Méthode et Outils pour la Programmation Françoise Greffier Université de Franche-Comté.
IFT-2000: Structures de données Piles et files Dominic Genest, 2009.
Structures de données IFT-2000
Structures de données IFT-10541
Structures de données IFT-2000 Abder Alikacem La récursivité Semaine 5 Département dinformatique et de génie logiciel Édition Septembre 2009.
Structures de données IFT-2000 Abder Alikacem Semaine 11 Gestion des arbres binaires de tri et de recherche. Les arbres cousus. Les arbres n-aires Département.
Structures de données IFT-2000 Abder Alikacem Retour sur les listes ordonnées Département dinformatique et de génie logiciel Édition Septembre 2009.
INF1101 Algorithmes et structures de données
Structures de données IFT-2000 Abder Alikacem La récursivité Département d’informatique et de génie logiciel Édition Septembre 2009.
Structures de données IFT-2000
Structures de données IFT-2000
Le langage C Structures de données
LES PILES ET FILES.
La notion de type revisitée en POO
Arbres binaires et tables de hachage
Chaînage et LSC : motivation et principe Manipuler la LSC : exemples Variantes : LDC, liste circulaire, … Etude de cas : réalisation d’un buffer clavier.
ETNA – 1ème année Guillaume Belmas –
Cours LCS N°4 Présenté par Mr: LALLALI
Liste Une liste est une séquence d’éléments. Concept important: Chaque élément possède une position dans la liste. Notation: De quelles opérations a-t-on.
La récursivité Mireille Goud HEG Vd AlgSD - Résurisivité.
8PRO107 Éléments de programmation Les tableaux. Étude de cas 1 Description du problème : Lire une liste d’entiers et l’afficher d’abord dans le même ordre.
La pile de crêpes.
Structures de données IFT-2000
1 Listes des méthodes de la classe string, et exemples.
Structures de données IFT-2000 Abder Alikacem Semaine 14 Les algorithmes de tri Département d’informatique et de génie logiciel Édition septembre 2009.
Structures de données IFT-2000 Abder Alikacem Laboratoire #1 Département d’informatique et de génie logiciel Édition Septembre 2009.
Structures de données IFT-2000 Abder Alikacem Semaine 10 Les algorithmes de recherche Les structures arborescentes Département d’informatique et de génie.
Structures de données IFT-2000 Abder Alikacem La récursivité Semaine 5 Département d’informatique et de génie logiciel Édition Septembre 2009.
Structures de données IFT-2000 Abder Alikacem Standard Template library Semaine 5 Édition Septembre 2009 Département d’informatique et de génie logiciel.
CSI25101 Tri Plus efficace. CSI25102 Tri récursif Le tri récursif divise les données de grande taille en deux presque moitiés et est appelé récursivement.
M. BENJELLOUN : 2005 Le but final est de programmer un jeu où l'ordinateur choisira un nombre aléatoire entre 0 et 100 que vous devez deviner.
Transcription de la présentation:

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

Première partie Standard Template Library du C++

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.

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

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)

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):

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

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

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

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

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

Les itérateurs Exemple d’itérateur

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

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

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 ; }

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…

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

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; }

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

Deuxième partie  Rappel des notions de base  Limitations (suite de Fibonacci)  Sous-séquence de somme maximale  Backtracking

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).

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

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)); }

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.

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)

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)

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é.

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.

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.

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) }

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

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.

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; }

Sous-séquence de somme maximale (Exemple) 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

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.

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; }

Retour en arrière - Exemple  Utiliser des appels récursifs et l’ordre d’appel suivant: Nord Sud Est Ouest A B S C D E F E G H I J

Retour en arrière - Exemple 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; }

Retour en arrière - réponse 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

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

Les algorithmes de recherche  Les algorithmes de recherche  La recherche séquentielle  La recherche dichotomique  Complexité des algorithmes de recherche  Recherche dichotomique et arborescence

La recherche séquentielle  meilleur cas=O(1)  pire cas=O(n)  en moyenne= O(n/2)  absences=O(n) Données pas triées  meilleur cas=O(1)  pire cas=O(n)  en moyenne= O(n/2)  absences=O(n/2) Données triées

Modèles d’implantation tableau : liste chaînée :

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

La recherche binaire

La recherche binaire

La recherche binaire

La recherche binaire

La recherche binaire : 10 ?

La recherche binaire : 10 ?

La recherche binaire : 10 ?

La recherche binaire : 10 ?

La recherche binaire : 10 ?

La recherche binaire : 10 ?

La recherche binaire : 10 ?

La recherche binaire : 10 ?

La recherche binaire : 10 ?

La recherche binaire : 10 ?

La recherche binaire : 10 ?

La recherche binaire : 9.5 ? 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

Modèles d’implantation tableau : liste chaînée ?

Structures pointées

Structures pointées

Structures pointées

Structures pointées

Structures pointées

Structures pointées

Structures pointées

Structures pointées

Structures pointées

Structures pointées

Structures pointées

Structures pointées

Arbre binaire !

Arbre = index