ANNEE UNIVERSITAIRE 2014 / 2015 S1 D’AUTOMNE PARCOURS / ETAPE : IM300/IN301 Code UE : IN3W01 Epreuve : Algorithmique et structures de données 1 Date : 07 janvier Heure : 08h30 Durée : 1h30 Documents : non autorisés Epreuve de M/Mme : Carole Blanc Collège Sciences et technologies Indiquez votre code d’anonymat : N° : La notation tiendra compte de la clarté de l’écriture des réponses. Barème indicatif Question 1 – Connaissances générales : 2 points Question 2 – Containeur liés aux arbres : 6 points Question 3 – Utilisation des structures de données : 4 points Question 4 – Ecriture de fonctions sur les arbres : 4 points Question 5 – Connaissance des structures de données: 4 points Question 1. Cochez les affirmations correctes et quelle que soit la réponse justifiez sur les lignes en pointillé. Dans un arbre binaire de recherche la valeur minimum est dans le sous arbre gauche de la racine. Dans un arbre binaire de recherche, quel que soit x un sommet interne d'étiquette val(x), soit LG(x) (resp. LD(x)), l'ensemble des étiquettes du sous arbre gauche (resp. droit) de x. On a : ∀𝑦 ∈ 𝐿𝐺(𝑥), ∀𝑧 ∈ 𝐿𝐷(𝑥), 𝑦 ≤ 𝑣𝑎𝑙(𝑥) < 𝑧 Donc vrai si le sous arbre gauche de la racine n’est pas vide, sinon le minimum est la valeur de la racine. La suppression sur un tas max ayant N éléments admet une complexité en O(1). Faux : la suppression dans un tas se fait en deux étapes. D’abord on supprime la racine de l’arbre ce qui se fait en O(1). Mais il faut ensuite réorganiser le Tas en remplaçant la racine supprimée par la dernière feuille et faire une réorganisation descendante en O(log2(N)). Dans une table de hachage en adressage chainé il n’y a jamais de problème de collision. Faux : Dans ce type de table une case i de la table de hachage donne accès à une liste chainée qui contient tous les objets de clé k dont la valeur de hachage h(k)= i. Les collisions sont possibles comme avec n’importe quel type de table de hachage elles sont résolues en mettant deux objets qui collisent « vers » la case i de la table dans la même liste. Une file est une structure de données qui permet l’accès en O(1) au dernier élément entré dans la structure. Faux : pour accéder au dernier élément d’une file il faut défiler tous ceux qui le précèdent. Ce qui se fait en O(N) si la file contient N éléments. Le fait qu’on puisse insérer le dernier élément en O(1) dans une file ne le rend pas accessible pour autant. 1/10 Question 2. Soit la liste de clé L=(11, 10, 8, 20, 3, 16, 2, 18, 25). 1. Construisez l’arbre binaire de recherche A correspondant à l’insertion consécutive des clés dans l’ordre où elles se présentent dans L. On dessinera l’arbre après chacune des quatre premières insertions (de 11 à 20) ainsi que l’arbre final lorsque toutes les valeurs de L seront insérées. 11 11 11 11 10 10 10 20 8 8 11 20 10 8 3 16 25 18 2 2. Donnez les mots préfixe, infixe et suffixe obtenus en faisant le parcours de A. Prefixe : 11 10 8 3 2 20 16 18 25 Infixe : 2 3 8 10 11 16 18 20 25 Suffixe : 2 3 8 10 18 16 25 20 11 3. Montrez l’exécution de la suppression de la valeur 20 sur l’arbre A. Le sommet de valeur 20 admet 2 sous arbres on remplace donc 20 par la valeur max de son sous arbre gauche c’est à dire 18. Puis on supprime le sommet de valeur 18. 2/10 11 18 10 16 8 25 3 2 4. Construisez le Tas Min T correspondant à l’insertion consécutive des clés de la liste L. On dessinera l’arbre après chacune des quatre premières insertions ainsi que le Tas final. 5. 11 11 10 10 11 11 3 11 10 8 10 20 20 20 3 2 8 18 20 11 8 8 8 11 8 10 3 11 16 10 25 3/10 10 11 10 6. Montrez l’exécution de la suppression sur le Tas T. La suppression dans un Tas consiste à supprimer la valeur de la racine. Elle est remplacé par la valeur de la dernière feuille. La dernière feuille est alors supprimée et pour finir on réorganise le tas en faisant descendre la nouvelle valeur de la racine à sa place 2 25 8 20 3 16 8 10 20 18 25 16 25 3 8 20 10 16 25 4/10 3 18 10 18 7. Rappel L=(11,10,8,20,3,16,2,18,25). Construisez l’AVL correspondant à l’insertion consécutive de la liste L. On dessinera l’arbre après chacune des quatre premières insertions ainsi que l’arbre final. 0 11 -1 11 10 0 -1 0 8 1 10 11 2ème étape -1 11 8 11 8 1 2 1ère étape 20 20 3 0 0 0 -1 -1 0 3 16 8 3 0 20 20 11 0 11 0 0 20 20 0 1 0 1 16 16 0 10 8 -1 10 0 -1 20 20 16 0 -2 0 8 10 3 0 10 0 10 -1 0 0 11 -2 0 2 2 10 3 8 0 0 11 0 5/10 20 18 0 25 0 Question 3 : On considère une file de caractères ne contenant que des S (déplacement Sud) et des N (déplacement Nord). De façon évidente un déplacement S est compensé par un déplacement N et réciproquement. Ecrivez une fonction simplificationNS(ref F:File_car):entier qui prend en entrée une telle file et simplifie son contenu en produisant toutes les compensations possibles. A la fin il ne restera dans la file que les éléments qui n’ont pas pu être compensés (que des N ou que des S). La fonction retournera le nombre de compensations réalisées lors du traitement de la file. Par exemple : Si en entrée F= ]S,S,S,N,N,S,N,N,S,S,S,N,S[ On aura en sortie : F=] S,S,S [ et la fonction retournera 5. Une solution possible parmi d’autres : Fonction supprimePaireNB(ref F:File_car):entier ; Var Fb,Fn : File_car ; X : car ; Cpt :entier Debut Cpt=0 /*Repartition des éléments dans 2 Files*/ Tant non FileVide(F) faire : X=valeurFile(F) Si x== ‘S’ alors Enfiler(Fs,x) Sinon Enfiler(Fn,x) Finsi Defiler(F) Fintantque /*Construction et comptage des paires */ Tantque non FileVide(Fb) et non FileVide(Fn)faire : Defiler(Fb) Defiler(Fn) Cpt++ Fintantque /*Reconstruction de F avec les éléments restants*/ /*une seule des 2 boucles suivantes s’exécutera*/ Tanque non FileVide(Fb) faire Enfiler(F, valeurFile(Fb) Defiler(Fb) Fintantque Tanque non FileVide(Fn) faire Enfiler(F, valeurFile(Fn) Defiler(Fn) Fintantque Retourner (cpt) Fin ; 6/10 Question 4 : On considère un arbre binaire dont les valeurs des sommets sont des entiers tous distincts. Quel que soit s un sommet de l’arbre binaire : si getValeur(s) < getValeur(filsGauche(s)) on dit que s admet 1 inversion. si getValeur(s) > getValeur(filsDroit(s)) on dit que s admet 1 inversion. si getValeur(s) < getValeur(filsGauche(s)) ET getValeur(s)>getValeur(filsDroit(s)) on dit que s admet 2 inversions. Les feuilles admettent 0 inversion. Le nombre d’inversions d’un arbre est la somme du nombre d’inversions de tous ses sommets. Par exemple, dans l’arbre ci-contre : le sommet de valeur 10 admet 2 inversions, le sommet de valeur 15 admet 1 inversion le sommet de valeur 5 admet 0 inversion. Sachant que les feuilles admettent 0 inversion il y a donc au total 3 inversions sur cet arbre. 10 5 15 7 12 1 1. Ecrivez une fonction nbInversions(ref A :arbreBinaire) :entier qui retourne le nombre d’inversions de A. fonction nbInversions(ref A : arbreBinaire):entier debut si estFeuille(A)alors retourner(0) si filsGauche(A) alors si getValeur(A)<getValeur(filsGauche(A))alors retourner (1+ nbInversions(filsGauche(A))) sinon retourner(nbInversions(filsGauche(A))) finsi si filsDroit(A) alors si getValeur(A)>getValeur(filsDroit(A))alors retourner (1+ nbInversions(filsDroit(A))) sinon retourner(nbInversions(filsDroit(A))) finsi fin 2. Que retourne nbInversions(A) si A est un arbre binaire de recherche ? Justifiez Si A est une arbre Binaire de recherche tous les sommets s de A sont tels que : getValeur(s)>getValeur(filsGauche(s)) et getValeur(s)< getValeur(filsDroit(s)) donc la fonction retourne 0. 7/10 3. Peut-on utiliser la fonction nbInversions pour tester si un arbre binaire est un arbre binaire de recherche ? Justifiez votre réponse Non par exemple pour cet arbre la fonction nbInversions retourne 0 mais il ne s’agit pas d’un ABR 12 8 16 10 Question 5 : Lorsque le père fait sa tournée de Noël pour distribuer les cadeaux il doit régulièrement remplir sa hotte. Compte tenu de son grand âge et de son dos fragile il préfère que le poids de sa hotte pleine varie le moins possible. LUDO, TOBY et ANTON sont 3 candidats au poste de « Lutin du père Noël ». Lors de l’entretien d’embauche vous leur soumettez le problème suivant : Quelle structure de données serait pertinente pour gérer le stock de N cadeaux à distribuer, pour permettre de remplir efficacement la hotte chaque fois qu’elle est vide et pour respecter les souhaits du père noël ? Les 3 candidats pensent qu’il faut remplir la hotte en ajoutant systématiquement ensemble le paquet le plus léger avec le paquet le plus lourd du stock restant jusqu’à ce que la hotte soit pleine. De même ils choisissent tous les 3 d’ordonner leur structure de données selon le poids des paquets. Par contre ils ne choisissent pas la même structure de données : LUDO propose de gérer le stock en utilisant une liste doublement chainée triée. TOBY préfère utiliser deux tas : un tas min et un tas Max. ANTON quant à lui choisit un arbre binaire de recherche. En tant que recruteur vous devez évaluer la pertinence de ces différents choix pour cela vous décidez d’estimer le temps de calcul nécessaire aux actions suivantes : Action 1 : Entrer les N paquets du stock dans la structure de données choisie. Action 2 : Une fois la structure de données remplie, mettre 2 paquets (le plus léger et le plus lourd) dans la hotte. Temps de calcul Action 1 : Méthode LUDO O(N2) au pire on parcourt n fois toute la liste de longueur N pour trouver la place correcte de chaque paquet. Méthode TOBY O(N*log2(N)) pour chaque Tas. N insertions en log2(N) 8/10 Méthode ANTON O(N*h) Avec h hauteur de l’ABR. L’ABR n’est pas nécessairement équilibré donc h n’est pas nécessairement de l’ordre de log2(N). O(1) pour le plus léger et pour le plus lourd. Action 2 : O(log2(N)) pour le plus léger et pour le plus lourd car il faut réorganiser le tas à chaque suppression O(h) pour le plus léger et pour le plus lourd. Quelle est d’après vous la solution la plus efficace en temps de calcul ? On doit faire une fois l’action 1 et N fois l’action 2 (même si on doit remplir plusieurs hottes au final les N paquets seront déplacés du stocka ge vers la hotte). Dans chaque cas cela donne : LUDO : O(N2)+N*O(1) TOBY : O(N*log2(N))+N*O(log2(N)) ANTON : O(N*h)+N*O(h) sachant que la hauteur peut tendre vers N si l’arbre est déséquilibré. donc la solution de TOBY est plus efficace en temps de calcul. Question Bonus : (Hors Barème) Evaluez l’occupation mémoire des solutions proposées : LUDO TOBY Occupation mémoire N 2N ANTON N Quelle est d’après vous la solution pertinente parmi celles proposées? Justifiez. Pour que la solution de TOBY reste pertinente il faudrait limiter l’occupation mémoire et pour cela il faudrait savoir partager les N paquets en 2 sous-ensembles : les plus lourds dans le tas Max et les plus léger dans le tas min ce qui augmenterait la complexité en temps. Par contre si on force l’ABR choisi par ANTON à rester équilibré par exemple en choisissant un AVL alors la complexité en temps devient O(Nlog2(N) et l’occupation mémoire est N. Cette solution est alors la plus efficace. FIN 9/10 Annexe Listes simplement chainées (listeSC) fonction valeur(val L:liste d'objet):objet; fonction debutListe(val L:liste d'objet) :vide ; fonction suivant(val L:liste d'objet) :vide ; fonction listeVide(val L:liste d'objet): booleen; fonction créerListe(ref L:liste d'objet):vide; fonction insérerAprès(ref L:liste d'objet; val x:objet;):vide; fonction insérerEnTete(ref L:liste d'objet val x:objet):vide; fonction supprimerAprès(ref L:liste d'objet):vide; fonction supprimerEnTete(ref L:liste d'objet):vide; fonction detruireListe(ref L:liste d'objet):vide; Listes doublement chainées (listeDC) fonction finListe(val L:liste d'objet):vide; fonction précédent(val L::liste d'objet): vide; Piles fonction valeur(ref P:pile de objet):objet; fonction pileVide(ref P:pile de objet):booléen; fonction créerPile(P:pile de objet) :vide fonction empiler(ref P:pile de objet;val x:objet):vide; fonction dépiler(ref P:pile de objet):vide; fonction detruirePile(ref P:pile de objet):vide; Files fonction valeur(ref F:file de objet):objet; fonction fileVide(ref F:file de objet):booléen; fonction créerFile(F:file de objet);vide; fonction enfiler(ref F:file de objet;val x:objet):vide; fonction défiler (ref F:file de objet):vide; fonction detruireFile(ref F:file de objet):vide; Arbres binaires fonction getValeur(val S:sommet):objet; fonction filsGauche(val S:sommet):sommet; fonction filsDroit(val S:sommet):sommet; fonction pere(val S:sommet):sommet; fonction setValeur(ref S:sommet;val x:objet):vide; fonction ajouterFilsGauche(ref S:sommet,val x:objet):vide; fonction ajouterFilsDroit(ref S:sommet,x:objet):vide; Arbres binaires (suite) fonction supprimerFilsGauche(ref S:sommet):vide; fonction supprimerFilsDroit(ref S:sommet):vide; fonction detruireSommet(ref S:sommet):vide; fonction créerArbreBinaire(val Racine:objet):sommet; fonction detruireArbreBinaire(val Racine:objet):sommet; Arbres planaires fonction valeur(val S:sommetArbrePlanaire):objet; fonction premierFils(val S:sommetArbrePlanaire):sommetArbrePlanaire; fonction frere(val S:sommetArbrePlanaire):sommetArbrePlanaire; fonction pere(val S:sommetArbrePlanaire):sommetArbrePlanaire; fonction créerArborescence(val racine:objet):sommetArbrePlanaire; fonction ajouterFils(ref S:sommetArbrePlanaire,val x:objet):vide; fonction supprimerSommet(ref S:sommetArbrePlanaire):vide; fonction detruireArborescence(val racine:objet):sommetArbrePlanaire; Arbres binaire de recherche fonction ajouter(ref A:arbreBinaire d’objets, val v:objet):vide; fonction supprimer(val A: arbreBinaire d’objets, val v:objet):vide; Tas fonction valeur(ref T:tas d'objet): objet; fonction ajouter(ref T:tas de objet, val v:objet):vide; fonction supprimer(val T:tas de objet):vide; fonction creerTas(ref T:tas,val:v:objet):vide; fonction detruireTas(ref T:tas):vide; File de priorité fonction changeValeur(ref T:tas d'objet,val s:sommet,val v:objet):vide; Dictionnaire fonction appartient(ref d:dictionnaire,val M::mot):booléen; fonction creerDictionnaire(ref d: dictionnaire):vide ; fonction ajouter(ref d:dictionnaire,val M::mot):vide; fonction supprimer(ref d:dictionnaire,val M:mot):vide; fonction detruireDictionnaire(ref d:dictionnaire):vide; Table de Hachage fonction chercher(ref T:tableHash de clés, val v:clé):curseur; fonction créerTableHachage(ref T: tableHash de clé, ref h:fonction):vide; fonction ajouter(ref T:tableHash de clé,val x:clé):booleen; fonction supprimer((ref T:tableHash de clé,val x:clé):vide; fonction detruireTableHachage(ref T: tableHash de clé, ref h:fonction):vide; 10/10