Algorithmes et Structure de données Gilles Falquet Questions d’examen Arbres Ecrire une procédure qui calcule la somme des valeurs contenues dans les noeuds d’un arbre ternaire (au plus trois descendants pour chaque noeud). On suppose que le type Arbre possède les méthodes suivantes : a.estVide() : retourne vrai si a est un arbre vide et faux sinon a.enfant(i) : retourne l’arbre qui est le i-ème enfant de a (i compris entre 1 et 3) a.valeur() : retourne la valeur de la racine de a Indications : écrivez la procédure en vous basant sur la procédure de parcours en profondeur. Arbres Ecrivez une procédure qui affiche toutes les valeurs qui se trouvent sur des noeuds feuilles d’un arbre. Rappel: un noeud feuille d’un arbre est un noeud qui n’a pas de descendants. On suppose que le type Arbre possède les méthodes suivantes : a.estVide() : retourne vrai si a est un arbre vide et faux sinon a.enfant(i) : retourne l’arbre qui est le i-ème enfant de a a.valeur() : retourne la valeur de la racine de a, de type Val a.nbDesc() : retourne le nombre de descendants du noeud a. On suppose de plus qu’on a une méthode affiche() qui permet d’afficher une valeur de type Val. Indications : écrivez la procédure en vous basant sur la procédure de parcours en profondeur. Hachage Pour stocker un ensemble de nombres entiers on choisit comme structures de données une table de hachage ouvert de 100 éléments avec comme fonction de hachage h(x) = x modulo 100 On considère deux situations a) on stocke 1000 nombres tirés au hasard - quelle sera la taille moyenne des sous-listes ? 1/4 - quelle sera la complexité en temps pour tester si un nombre appartient à l’ensemble (ordre de grandeur du nombre d’opérations nécessaires) ? b) on stocke l’ensemble composé des 1000 nombres {101, 201, 301, …, 99901, 100001} - quelle sera la taille de la plus grande sous-liste ? - quelle sera la complexité en temps pour tester si un nombre de la forme xxx01 (100k+1) appartient à l’ensemble (nombre d’opérations nécessaires) ? Hachage et arbres binaires Dans une application on doit gérer un ensemble d’objets (par exemple des chaînes de caractères). On décide d’étudier deux solutions pour implémenter cet ensemble Solution 1 : un arbre binaire de recherche Solution 2 : le hachage ouvert avec une table de taille 1000 1) Quelle sera la solution qui permettra de tester le plus rapidement si un objet appartient à l’ensemble ? a) Dans le cas où l’ensemble est de taille 500 b) Dans le cas où l’ensemble est de taille 14000 c) Dans le cas où l’ensemble est de taille 100000 2) Pouvez-vous trouver un critère général pour décider de quelle solution utiliser en fonction de la taille N de l’ensemble à représenter ? Nombres réels On considère que l’algorithme ci-dessous travaille sur des nombres réels correspondant au standard IEEE-754 (erreur relative de l’ordre de 10 –7). Que vaudra w à la fin de l’exécution de cet algorithme ? w ← 1000000.0; p ← 0.001; pour i = 1 à 1000000 { w ← w + p; } Justifiez brièvement votre réponse. Nombres réels Soit l’algorithme suivant : fonction f ( réel x, entier n) { réel r ← 0; pour ( i de 1 à n) r ← r + x; 2/4 retourner r; } 1) Que calcule cet algorithme (en théorie) ? 2) Si l’on traduit l’algorithme dans un langage réel (par exemple en C ou en Java) et qu’on l’exécute sur une machine où la représentation des réels se fait selon le standard IEEE 754 en simple précision, on obtient les résultats suivants : x n f(x, n) 0.1 10 1.0000001 0.01 100 0.99999934 0.001 1000 0.9999907 0.00001 100000 1.0009902 0.0000001 10000000 1.0647675 0.00000001 100000000 0.25 0.000000001 1000000000 0.03125 a) Expliquez pourquoi il y a une différence entre f(x, n) et le résultat théorique (1.0). b) Expliquez pourquoi les deux derniers résultats (0.25 et 0.03125) sont aussi éloignés de la valeur théorique. Nombres entiers On considère que les nombres entiers utilisent 8 bits, en complément à 2 (ils vont donc de –128 à +127) et avec une arithmétique modulaire. Que vaudra alors la variable r à la fin de l’exécution de l’algorithme suivant r← 0 pour i = 1 à 8 { r ← r + 32 } Ecriture d’algorithme On a un tableau t qui contient des nombres entiers positifs, nuls ou négatifs, placés dans un ordre quelconque. Ecrivez un algorithme qui déplace les éléments du tableau de telle manière que tous les nombres négatifs se trouvent (dans n’importe quel ordre) avant les nombres nuls ou positifs. En termes formels, après l’exécution de l’algorithme t doit satisfaire la contrainte Pour tout i et j compris dans les indices de t et tels que i < j 3/4 si t[j] < 0 alors t[i] < 0 Par exemple, si t contient (6, -1, 4, 6, -8, 0, -9, 2) au début, après l’exécution de l’algorithme il pourra contenir (-1, -9, -8, 6, 6, 4, 0, 2) ou (-9, -1, -8, 0, 4, 2, 6, 6) ou ...(plusieurs solutions possibles) Ecriture d’algorithme On a une liste L qui contient des nombres entiers positifs, nuls ou négatifs. Ecrivez un algorithme qui compte le nombre de sous-listes triées dans L. Une sous-liste est triée si ses éléments sont rangés en ordre croissant ou décroissant. Par exemple, la liste (-8, 3, 10, 5, 4, 4, 0, 1, 0, 4, 8, 9, 11, -11) contient les 6 sous-listes triées (8, 3, 10), (10, 5, 4, 4, 0), (0, 1), (1, 0), (0, 4, 8, 9, 11), (11, -11). Ce qu’on peut voir sur la représentation graphique ci-dessous. 15 10 5 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 -5 -10 -15 On suppose que le type Liste possède les méthodes suivantes : s.element(i) l’élément à la position i dans s (première position = 0) s.indice(f) position du premier élément égal à f s.longueur() nombre d’éléments dans s 4/4