Polycopealgo1 PDF
Polycopealgo1 PDF
Polycopealgo1 PDF
1 Introduction 3
1.1 Résolution d’un problème en informatique . . . . . . . . . . . . . . . . . . . 3
1.2 Notion d’algorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 Langage algorithmique utilisé . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3 Structures séquentielles 20
3.1 Les listes linéaires chaînées (LLC) . . . . . . . . . . . . . . . . . . . . . . . . 20
3.2 Les piles (stacks) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.3 Les Files d’attente (Queues) . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.4 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4 Structures Hiérarchiques 45
4.1 Les arbres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.2 Les arbres binaires de recherche . . . . . . . . . . . . . . . . . . . . . . . . . 56
4.3 Les tas (Heaps) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.4 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
5 Structures en Tables 69
5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
1
5.2 Accès séquentiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
5.3 Table triée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
5.4 Hachage (HashCoding) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
5.5 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
6 Les graphes 75
6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
6.2 Définitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
6.3 Représentation des graphes . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
6.4 Parcours de graphes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
6.5 Plus court chemin (algorithme de Dijkstra) . . . . . . . . . . . . . . . . . . 83
6.6 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
7 Preuve d’algorithmes 86
7.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
7.2 Méthode de preuve d’algorithme . . . . . . . . . . . . . . . . . . . . . . . . 86
7.3 Outils de preuve d’algorithme (Logique de Hoare) . . . . . . . . . . . . . . . 88
7.4 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
7.5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
8 Sujets d’examens 93
Références 137
2
Chapitre 1
Introduction
L’utilisation d’un ordinateur pour la résolution d’un problème nécessite tout un travail
de préparation. N’ayant aucune capacité d’invention, l’ordinateur ne peut en effet qu’exé-
cuter les ordres qui lui sont fournis par l’intermédiaire d’un programme. Ce dernier doit
donc être établi de manière à envisager toutes les éventualités d’un traitement.
Exemple : le problème Div(a,b), n’oubliez pas le cas b=0 !
3
faire en langage naturel, l’existence d’un langage algorithmique s’impose.
– Etape 4 : Traduction de l’algorithme dans un langage de programmation
Les étapes 1, 2 et 3 se font sans le recours à la machine. Si on veut rendre l’algo-
rithme concret ou pratique, il faudrait le traduire dans un langage de programmation.
Nous dirons alors qu’un programme est un algorithme exprimé dans un langage de
programmation.
– Etape 5 : Mise au point du programme
Quand on soumet le programme à la machine, cette dernière le traite en deux étapes :
Si les résultats obtenus sont ceux attendus, la mise au point du programme se termine.
Si nous n’obtenons pas de résultats, on dira qu’il y a existence des erreurs de logique.
Le programme soit ne donne aucun résultat, soit des résultats inattendus soit des
résultats partiels. Dans ce cas, il faut revoir en priorité si l’algorithme a été bien
traduit, ou encore est-ce qu’il y a eu une bonne analyse.
1.2.1 Définition
1.2.2 Propriétés
On peut énoncer les cinq propriétés suivantes que doit satisfaire un algorithme :
1. Généralité : un algorithme doit toujours être conçu de manière à envisager toutes les
éventualités d’un traitement.
3. Définitude : toutes les opérations d’un algorithme doivent être définies sans ambiguïté
4
4. Répétitivité : généralement, un algorithme contient plusieurs itérations, c’est à dire
des actions qui se répètent plusieurs fois.
5. Efficacité : Idéalement, un algorithme doit être conçu de telle sorte qu’il se déroule
en un temps minimal et qu’il consomme un minimum de ressources.
1.2.3 Exemples
1.2.4 Remarque
5
Algorithme PremierExemple;
Type TTab = tableau[1..10] de reel ;
Const Pi = 3.14 ;
Procédure Double( x : reel);
Début
x x ⇤ 2;
Fin;
Fonction Inverse( x : reel) : reel;
Début
Inverse 1/x ;
Fin;
Var i, j, k : entier ;
T : TTab ;
S : chaine ;
R : reel ;
Début
Ecrire (’ Bonjour, donner un nombre entier 10 :’) ;
Lire (i) ;
Si (i>10) Alors
Ecrire (’Erreur : i doit être 10’)
Sinon
Pour j de 1 à i faire
Lire(R) ;
Double(R) ;
T [j] R;
Fin Pour;
k 1;
Tant que (k i) faire
Ecrire (T [k] ⇤ Inverse(P i)) ;
k k + 1;
Fin TQ;
S ’Programme terminé’ ;
Ecrire(S) ;
Fin Si;
Fin.
6
Algorithme 1: Algorithme type
Chapitre 2
2.1 Introduction
2.2 O-notation
Soit la fonction T (n) qui représente l’évolution du temps d’exécution d’un programme
P en fonction du nombre de données n.
Par exemple :
T (n) = cn2
Où c est une constante non spécifiée qui représente la vitesse de la machine, les per-
formances du langage, ...etc. On dit dans l’exemple précédent que la complexité de P est
O(n2 ). Cela veut dire qu’il existe une constante c positive tel que pour n suffisamment
grand on a :
T (n) cn2
7
Cette notation donne une majoration du nombre d’opérations exécutées (temps d’exé-
cution) par le programme P . Un programme dont la complexité est O(f (n)) est un pro-
gramme qui a f (n) comme fonction de croissance du temps d’exécution.
Une opération élémentaire est une opération dont le temps d’exécution est indépendant
de la taille n des données tel que l’affectation, la lecture, l’écriture, la comparaison ...etc.
Exemple :
3
O( n4 ) = O(n3 )
Si (Cond) Alors
M1 ;
Sinon
M2 ;
Fin Si;
8
est le max entre les complexités de l’évaluation de <Cond>, M1 et M2 .
La complexité d’une boucle est égale à la somme sur toutes les itérations de la com-
plexité du corps de la boucle.
Pm
La complexité de la boucle est : M ax(h(n), f (n)) où m est le nombre d’itérations
exécutées par la boucle.
9
Exemple 1 :
Algorithme Recherche;
Var T : tableau[1..n] de entier ;
x,i : entier ;
trouv : booleen ;
Début
Pour i de 1 à n faire
P
Lire (T[i]) ; O(1) O( n1 1) = O(n)
Fin Pour;
Lire(x) ; O(1)
Trouv faux ; O(1) O(1)
i 1; O(1) O(n)
Tant que (trouv=faux et i<=n [O(1)]) faire
Si (T[i]=x [O(1)]) Alors
Trouv vrai ; [O(1)] O(1) O(n)
Fin Si;
i i + 1 ; [O(1)]
Fin TQ;
10
Exemple 2 : Soit le module suivant :
Pour i de 1 à n faire
P
[n fois O( ni=1 n i))]
Pour j de i+1 à n faire
P
[n i fois O( n1 i
1) = O(n i)]
Si (T[i] > T[j] [O(1)] ) Alors
tmp T[i] ; [O(1)]
T[i] T[j] ; [O(1)] O(1)
T[j] tmp ;[O(1)]
Fin Si;
Fin Pour;
Fin Pour;
P
La complexité = O( n (n i) = O((n 1) + (n 2) . . . + 1)
2
= O( n(n2 1)
) = O( n2 2)
n
= O(n2 )
11
Exemple 3 : Recherche dichotomique
Algorithme RechercheDecho;
Var T : tableau[1..n] de entier ;
x,sup,inf,m : entier ;
trouv : booleen ;
Début
Lire(x) ; [O(1)]
Trouv faux ; [O(1)]
inf 1; [O(1) O(1)]
sup n; [O(1)]
Tant que (trouv=faux et inf<sup) faire
[log2 (n) fois]
m (inf + Sup ) div 2 ; [O(1)]
Si (T[m]=x [O(1)]) Alors
Trouv vrai [O(1)]
Sinon
Si (T[m]<x [O(1)]) Alors
inf m +1 ; [ O(1) O(1) O(log2 (n))]
Sinon
Sup m - 1 ; [O(1)]
Fin Si;
Fin Si;
Fin TQ;
12
O(1) + O(log2 (n)) + O(1) = O(log2 (n)) = O(log(n)).
La complexité d’un algorithme récursif se fait par la résolution d’une équation de ré-
currence en éliminant la récurrence par substitution de proche en proche.
Exemple
Soit la fonction récursive suivante :
Posons T (n) le temps d’exécution nécessaire pour un appel à F act(n), T (n) est le
maximum entre :
– la complexité du test n 1 qui est en O(1),
– la complexité de : Fact 1 qui est aussi en O(1),
– la complexité de : Fact n*Fact(n - 1) dont le temps d’exécution dépend de T (n 1)
(pour le calcul de Fact(n - 1))
On peut donc écrire que :
8
< a si n <= 1
T (n) =
: b + T (n 1) sinon (sin > 1)
– La constante a englobe le temps du test (n <= 1) et le temps de l’affectation
(Fact 1)
– La constante b englobe :
* le temps du test (n <= 1),
* le temps de l’opération * entre n et le résultat de F act(n 1),
13
* et le temps de l’affectation finale (Fact ...)
T (n 1) (le temps nécessaire pour le calcul de F act(n 1) sera calculé (récursivement)
avec la même décomposition. Pour calculer la solution générale de cette équation, on peut
procéder par substitution :
T (n) = b + T (n 1)
= b + [b + T (n 2)]
= 2b + T (n 2)
= 2b + [b + T (n 3)]
= ...
= ib + T (n i)
= ib + [b + T (n i + 1)]
= ...
= (n 1)b + T (n n + 1) = nb b + T (1) = nb b+a
T (n) = nb b+a
1. T (n) = O(1), temps constant : temps d’exécution indépendant de la taille des données
à traiter.
3. T (n) = O(n), temps linéaire : cette complexité est généralement obtenue lorsqu’un
travail en temps constant est effectué sur chaque donnée en entrée.
14
2.6 Exercices
Pour i de 2 à n faire
k i-1 ;
x T[i] ;
Tant que (T[k] > x et k > 0) faire
T[k+1] T[k] ;
k k-1 ;
Fin TQ;
T[k+1] x;
Fin Pour;
i n;
S 0;
Tant que (i > 0) faire
j 2*i ;
Tant que (j > 1) faire
S S+(j-i)* (S+1) ;
j j-1 ;
Fin TQ;
i i div 2 ;
Fin TQ;
15
3. Calculer la complexité de l’algorithme suivant :
i 1;
j 0;
Pour k de 1 à n faire
j i+j ;
i j-i ;
Fin Pour;
16
5. Calculer la complexité de l’algorithme suivant :
P 1;
Pour I de 1 à n faire
J 1;
K 1;
Tant que (K n) faire
P P * (K + J) ;
K K + 1;
Si (K > n) Alors
J J + 1;
Si (J > n) Alors
K 1
Fin Si;
Fin Si;
Fin TQ;
Fin Pour;
i 1;
Tant que (i < n) faire
j 1;
Tant que (j < 2*n) faire
j j*2 ;
Fin TQ;
i i+1 ;
Fin TQ;
17
7. Trouver la complexité de la fonction suivante :
Var x : entier ;
Fonction f( i, j, k : entier) : entier;
Début
Si (k+j = i) Alors
f ((i-j) div k) + 1 ;
Sinon
x f(i, j+1, k-2) ;
f f(i+1, j+x, k-2) ;
Fin Si;
Fin;
i 1;
j 1;
Tant que (i < n) faire
Si (j < n) Alors
j j * 2;
Sinon
j 1;
Fin Si;
i i + 1;
Fin TQ;
18
9. Calculer la complexité de la procédure récursive F(x, y, z) suivante :
Procédure F( x, y, z : reel);
Début
y 2*z ;
Si (x > x/(y - z)) Alors
x x - 2;
y y / 4;
z z / 5;
F(x, y, z) ;
Fin Si;
Fin;
19
Chapitre 3
Structures séquentielles
L’utilisation des tableaux statiques implique que l’allocation de l’espace se fait tout à
fait au début d’un traitement, c’est à dire que l’espace est connu à la compilation. Pour
certains problèmes, on ne connaît pas à l’avance l’espace utilisé par le programme. On est
donc contraint à utiliser une autre forme d’allocation. L’allocation de l’espace se fait alors
au fur et à mesure de l’exécution du programme. Afin de pratiquer ce type d’allocation,
deux opérations sont nécessaires : allocation et libération de l’espace.
Exemple
Supposons que l’on veuille résoudre le problème suivant : "Trouver tous les nombres
premiers de 1 à n et les stocker en mémoire". Le problème réside dans le choix de la
structure d’accueil. Si on utilise un tableau, il n’est pas possible de définir la taille de ce
tableau avec précision même si nous connaissons la valeur de n (par exemple 10000). On
est donc, ici, en face d’un problème où la réservation de l’espace doit être dynamique.
Une liste linéaire chaînée (LLC) est un ensemble de maillons, alloués dynamiquement,
chaînés entre eux. Schématiquement, on peut la représenter comme suit :
20
Un élément ou maillon d’une LLC est toujours une structure (Objet composé) avec
deux champs : un champ Valeur contenant l’information et un champ Adresse donnant
l’adresse du prochain élément. A chaque maillon est associée une adresse. On introduit
ainsi une nouvelle classe d’objet : le type Pointeur qui est une variable contenant l’adresse
d’un emplacement mémoire.
Une liste linéaire chainée est caractérisée par l’adresse de son premier élément souvent
appelé tête. Nil constitue l’adresse qui ne pointe aucun maillon, utilisé pour indiquer la fin
de la liste dans le dernier maillon.
21
3.1.4 Modèle sur les listes linéaires chaînées
Afin de développer des algorithmes sur les LLCs, on construit une machine abstraite
avec les opérations suivantes : Allouer, Libérer, Aff_Adr, Aff_Val, Suivant et Valeur défi-
nies comme suit :
– Allouer(P) : allocation d’un espace de taille spécifiée par le type de P. L’adresse de
cet espace est rendue dans la variable de type Pointeur P.
– Libérer(P) : libération de l’espace pointé par P.
– Valeur(P) : consultation du champ Valeur du maillon pointé par P.
– Suivant(P) : consultation du champ Suivant du maillon pointé par P.
– Aff_Adr(P, Q) : dans le champ Suivant du maillon pointé par P, on range l’adresse
Q.
– Aff_Val(P,Val) : dans le champ Valeur du maillon pointé par P, on range la valeur
Val.
Cet ensemble est appelé modèle.
De même que sur les tableaux, on peut classer les algorithmes sur les LLCs comme
suit :
– Algorithmes de parcours : accès par valeur, accès par position,...
– Algorithmes de mise à jour : insertion, suppression,...
– Algorithmes sur plusieurs LLCs : fusion, interclassement, éclatement,...
– Algorithmes de tri sur les LLCs : trie par bulle, tri par fusion,...
22
Création d’une liste et listage de ses éléments
Algorithme CréerListe;
Type TMaillon = Structure
Valeur : Typeqq ;
Suivant : Pointeur(TMaillon) ;
Fin ;
Var P, Q, Tete : Pointeur(TMaillon ;
i, Nombre : entier ;
Val : Typeqq ;
Début
Tete Nil ;
P Nil ;
Lire(Nombre) ;
Pour i de 1 à Nombre faire
Lire(Val) ;
Allouer(Q) ;
Aff_val(Q, val) ;
Aff_adr(Q, NIL) ;
Si (Tete 6= Nil) Alors
Aff_adr(P, Q)
Sinon
Tete Q
Fin Si;
P Q;
Fin Pour;
P Tete ;
Tant que ( P 6= Nil) faire
Ecrire(Valeur(P)) ;
P Suivant(P) ;
Fin TQ;
Fin.
23
cet algorithme crée une liste linéaire chaînée à partir d’une suite de valeurs données,
puis imprime la liste ainsi créée.
Algorithme Recherche;
Type TMaillon = Structure
Valeur : Typeqq ;
Suivant : Pointeur(TMaillon) ;
Fin ;
Var P, Tete : Pointeur(TMaillon ;
Trouv : booleen ;
Val : Typeqq ;
Début
Lire(Val) ;
P Nil ;
Trouv Faux ;
Tant que ( P 6= Nil et non Trouv) faire
Si (Valeur(P)=Val) Alors
Trouv Vrai
Sinon
P Suivant(P)
Fin Si;
Fin TQ;
Si (Trouv=Vrai) Alors
Ecrire(Val,’Existe dans la liste’)
Sinon
Ecrire(Val,’n”existe pas dans la liste’
Fin Si;
Fin.
24
3.1.6 Listes linéaires chaînées bidirectionnelles
C’est une LLC où chaque maillon contient à la fois l’adresse de l’élément précédent et
l’adresse de l’élément suivant ce qui permet de parcourir la liste dans les deux sens.
Déclaration
25
3.2 Les piles (stacks)
3.2.1 Définition
Une pile est une liste ordonnée d’éléments où les insertions et les suppressions d’éléments
se font à une seule et même extrémité de la liste appelée le sommet de la pile.
Le principe d’ajout et de retrait dans la pile s’appelle LIFO (Last In First Out) : "le dernier
qui entre est le premier qui sort"
Une pile sert à mémoriser les pages Web visitées. L’adresse de chaque nouvelle page
visitée est empilée et l’utilisateur dépile l’adresse de la page précédente en cliquant le
bouton "Afficher la page précédente".
Fact(4)=4*Fact(3)=4*3*Fact(2)=4*3*2*Fact(1)=4*3*2*1=4*3*2=4*6=24
26
3.2.2.4 Parcours en profondeur des arbres
B C
D E F G
Exemple
L’expression ((a + (b ⇤ c))/(c d) est exprimée, en postfixé, comme suit : bc ⇤ a + cd /
Pour l’évaluer, on utilise une pile. On parcourt l’expression de gauche à droite, en exécutant
l’algorithme suivant :
27
i 1;
Tant que (i < Longeur(Expression)) faire
Si (Expression[i] est un Opérateur) Alors
Retirer deux éléments de la pile ;
Calculer le résultat selon l’opérateur ;
Mettre le résultat dans la pile ;
Sinon
Mettre l’opérande dans la pile ;
Fin Si;
i i + 1;
Fin TQ;
28
3.2.4 Implémentation des piles
Les piles peuvent être représentés en deux manières : par des tableaux ou par des LLCs :
L’implémentation statique des piles utilise les tableaux. Dans ce cas, la capacité de la
pile est limitée par la taille du tableau. L’ajout à la pile se fait dans le sens croissant des
indices, tandis que le retrait se fait dans le ses inverse.
L’implémentation dynamique utilise les listes linéaires chinées. Dans ce cas, la pile peut
être vide, mais ne peut être jamais pleine, sauf bien sur en cas d’insuffisance de l’espace
mémoire. L’empilement et le dépilement dans les piles dynamiques se font à la tête de la
liste.
Les deux algorithmes "PileParTableaux" et "PileParLLCs" suivant présentent deux
exemples d’implémentation statique et dynamique des piles.
29
Algorithme PileParTableaux;
Var Pile : Tableau[1..n] de entier ; Sommet : Entier ;
Procédure InitPile();
Début
Sommet 0;
Fin;
Fonction PileVide() : Booleen;
Début
P ileV ide (Sommet = 0) ;
Fin;
Fonction PilePleine() : Booleen;
Début
P ileP leine (Sommet = n) ;
Fin;
Procédure Empiler( x : entier);
Début
Si (PilePleine) Alors
Ecrire(’Impossible d’empiler, la pile est pleine ! !’)
Sinon
Sommet Sommet + 1 ;
P ile[Sommet] x;
Fin Si;
Fin;
Procédure Dépiler( x : entier);
Début
Si (PileVide) Alors
Ecrire(’Impossible de dépiler, la pile est vide ! !’)
Sinon
x P ile[Sommet] ;
Sommet Sommet 1;
Fin Si;
Fin;
Début
... Utilisation de la pile ...
Fin.
30
Algorithme PileParLLCs;
Type TMaillon = Structure
Valeur : entier ;
Suivant : Pointeur(TMaillon) ;
Fin ;
Var P, Sommet : Pointeur(TMaillon) ;
Procédure InitPile();
Début
Sommet N il ;
Fin;
Fonction PileVide() : Booleen;
Début
P ileV ide (Sommet = N il) ;
Fin;
Procédure Empiler( x : entier);
Début
Allouer(P) ; Aff_Val(P,x) ;
Aff_Adr(P,Sommet) ; Sommet P;
Fin;
Procédure Dépiler( x : entier);
Début
Si (PileVide) Alors
Ecrire(’Impossible de dépiler, la pile est vide ! !’)
Sinon
x V aleur(Sommet) ; P Sommet ;
Sommet Suivant(Sommet) ; Libérer(P) ;
Fin Si;
Fin;
Début
... Utilisation de la pile ...
Fin.
31
3.2.5 Exemple d’application : Remplissage d’une zone d’une image
Une image en informatique peut être représentée par une matrice de points 0 Image0
ayant M colonnes et N lignes. Un élément Image[x, y] de la matrice représente la couleur
du point p de coordonnées (x, y). On propose d’écrire ici une fonction qui, à partir d’un
point p, étale une couleur c autour de ce point. La progression de la couleur étalée s’arrête
quand elle rencontre une couleur autre que celle du point p. La figure suivante illustre cet
exemple, en considérant p = (3, 4).
Pour effectuer le remplissage, on doit aller dans toutes les directions à partir du point p.
Ceci ressemble au parcours d’un arbre avec les noeuds de quatre fils. La procédure suivante
permet de résoudre le problème en utilisant une pile.
32
Procédure Remplir( Image : T ableaux[0..M 1, 0..N 1] de couleur ; x, y : entier ;
c : couleur);
Var c1 : couleur ;
Début
c1 Image[x, y] ;
InitPile ;
Empiler((x, y)) ;
Tant que (¬ PileVide) faire
Depiler((x,y)) ;
Si (Image[x, y] = c1 ) Alors
Image[x, y] c;
Si (x > 0) Alors
Empiler((x 1, y))
Fin Si;
Si (x < M 1) Alors
Empiler((x + 1, y))
Fin Si;
Si (y > 0) Alors
Empiler((x, y 1))
Fin Si;
Si (y < N 1) Alors
Empiler((x, y + 1))
Fin Si;
Fin Si;
Fin TQ;
Fin;
33
3.3 Les Files d’attente (Queues)
3.3.1 Définition
La file d’attente est une structure qui permet de stocker des objets dans un ordre donné
et de les retirer dans le même ordre, c’est à dire selon le protocole FIFO ’first in first out’.
On ajoute toujours un élément en queue de liste et on retire celui qui est en tête.
Les files d’attente sont utilisées, en programmation, pour gérer des objets qui sont
en attente d’un traitement ultérieur, tel que la gestion des documents à imprimer, des
programmes à exécuter, des messages reçus,...etc. Elles sont utilisées également dans le
parcours des arbres.
Exercice
De même que pour les piles, les files d’attente peuvent être représentées en deux ma-
nières :
– par représentation statique en utilisant les tableaux,
– par représentation dynamique en utilisant les listes linéaires chaînées.
34
3.3.4.1 Implémentation statique
L’implémentation statique peut être réalisée par décalage en utilisant un tableau avec
une tête fixe, toujours à 1, et une queue variable. Elle peut être aussi réalisée par flot
utilisant un tableau circulaire où la tête et la queue sont toutes les deux variables.
1. Par décalage
35
3.3.4.2 Implémentation dynamique
Une file d’attente avec priorité est une collection d’éléments dans laquelle l’insertion
ne se fait pas toujours à la queue. Tout nouvel élément est inséré, dans la file, selon sa
priorité. Le retrait se fait toujours du début.
Dans une file avec priorité, un élément prioritaire prendra la tête de la file même s’il arrive
le dernier. Un élément est toujours accompagné d’une information indiquant sa priorité
dans la file.
L’implémentation de ces files d’attente peut être par tableau ou listes, mais l’implémen-
tation la plus efficace et la plus utilisée utilise des arbres particuliers qui s’appellent ’les
tas’.
36
Algorithme FileParFlot;
Var File : Tableau[1..n] de entier ; Tête, Queue : Entier ;
Procédure InitFile();
Début
T ête 1 ; Queue 1;
Fin;
Fonction FileVide() : Booleen;
Début
F ileV ide (T ête = Queue) ;
Fin;
Fonction FilePleine() : Booleen;
Début
F ileP leine (((Queue + 1) mod n) = T ête) ;
Fin;
Procédure Enfiler( x : entier);
Début
Si (FilePleine) Alors
Ecrire(’Impossible d”enfiler, la file est pleine ! !’)
Sinon
F ile[Queue] x;
Queue (Queue + 1) mod n ;
Fin Si;
Fin;
Procédure Défiler( x : entier);
Début
Si (FileVide) Alors
Ecrire(’Impossible de défiler, la file est vide ! !’)
Sinon
x F ile[T ete] ;
T ête (T ête + 1) mod n ;
Fin Si;
Fin;
Début
... Utilisation de la File ...
Fin.
37
Algorithme FileParLLCs;
Type TMaillon = Structure
Valeur : entier ;
Suivant : Pointeur(TMaillon) ;
Fin ;
Var P, Tête, Queue : Pointeur(TMaillon) ;
Procédure InitFile();
Début
T ête N il ; Queue N il ;
Fin;
Fonction FileVide() : Booleen;
Début
F ileV ide (T ête = N il) ;
Fin;
Procédure Enfiler( x : entier);
Début
Allouer(P) ; Aff_Val(P,x) ;
Aff_adr(P,Nil) ;
Si (Queue = Nil) Alors
T ête P;
Sinon
Aff_Adr(Queue,P) ;
Fin Si;
P;
Queue
Fin;
Procédure Défiler( x : entier);
Début
Si (FileVide) Alors
Ecrire(’Impossible de défiler, la file est vide ! !’)
Sinon
x V aleur(T ete) ; P T ête ;
T ête Suivant(T ête) ; Libérer(P) ;
Fin Si;
Fin;
Début
... Utilisation de la File ...
Fin. 38
3.4 Exercices
– Ecrire les algorithmes de base suivants sue les listes linéaires chaînées bidirection-
nelles :
2. Fonctions LISP
Soit une liste linéaire chaînée contenant des nombres entiers et dont la tête est L :
(a) Ecrire la fonction CAR(L) qui retourne la valeur du premier élément de la liste.
(b) Ecrire la fonction CDR(L) qui retourne la liste sans le premier élément.
(c) Ecrire la fonction CONS(x, L) qui retourne une liste dont le premier élément
est x et le reste est la liste L.
(d) Ecrire la fonction Triée(L) qui retourne vrai si la liste L est triée dans l’ordre
croissant et faux sinon.
(e) Ecrire la fonction Fusion(L1, L2) qui prend deux listes triées dans l’ordre crois-
sant L1 et L2 et retourne une liste triée, dans le même ordre, contenant les deux
listes et cela en utilisant les fonctions précédentes.
39
qui permet de construire la liste L = L1 L2 contenant tous les éléments appartenant
à L1 et n’appartenant pas à L2 .
5. Listes de caractères
Nous considérons la représentation d’une chaîne de caractères sous forme de LLC où
chaque maillon contient un caractère.
Ecrire la fonction qui vérifie qu’une liste est un palindrome ou non dans le cas de :
6. Matrices creuses
Une matrice est dite creuse lorsque le nombre d’éléments nuls y figurant est très
supérieur à celui des éléments non nuls. On peut représenter une matrice creuse en
ne tenant compte que des éléments non nuls. Chaque ligne de la matrice est une liste
linéaire chaînée ordonnée (selon le rang de la colonne) des éléments non nuls. Une
table de N éléments (N étant le nombre de lignes de la matrice) donne les adresses
de tête de chacune des listes. Un élément de la liste contient l’indice de la colonne et
la valeur de l’élément.
(b) Ecrire la procédure permettant de Remplir une telle structure à partir d’une
matrice A(M, N) donnée.
Sachant qu’un élément de la matrice occupe 4 octets, qu’un pointeur occupe 2 octets
et qu’un indice occupe 2 octets,
40
(b) quelle valeur minimale attribuée à µ pour que l’on puisse opter pour une telle
représentation
Procédure P( L : Pointeur(TMaillon));
Var x : entier ;
Début
Si ( L 6= Nil) Alors
P(Suivant(L)) ;
x Valeur(L) + R ;
Aff_val(L, x mod 2) ;
Si (x=2) Alors
R := 1 ;
Sinon
R := 0 ;
Fin Si;
Fin Si;
Fin;
Donner les différentes valeurs de L et x, dans l’ordre, après l’appel récursif pour la
liste suivante représentant le nombre 1011 :
41
– Ecrire un algorithme qui utilise cette procédure pour incrémenter un nombre bi-
naire ainsi représenté.
(c) Créer une liste ordonnée LD contenant tous les éléments de T en parcourant
parallèlement les n listes de T ( Interclassement )
2. La tour de Hanoi
Il s’agit d’un jeu de réflexion dont voici le principe. Des anneaux de diamètres diffé-
rents sont empilés sur un poteau. Un anneau peut être empilé sur un autre seulement
si il a un diamètre inférieur à celui de l’anneau sur lequel il repose.
Le but du jeu est de déplacer n anneaux initialement empilés sur un seul poteau
vers un autre en respectant les règles du jeu et en n’utilisant qu’un seul poteau
intermédiaire.
42
Ecrire un algorithme qui permette d’afficher les étapes nécessaires pour le dépla-
cement de n anneaux d’un poteau A vers un poteau C en passant par le poteau
intermédiaire B en utilisant trois piles.
ab+c+ab*c/*c/
(b) Donner l’algorithme qui évalue une expression arithmétique post-fixée. On sup-
pose que cette dernière se trouve dans un tableau dont les élément sont de type :
(Valeur, Type (opérateur ou opérande)).
4. Une file d’attente avec priorité est une file où les éléments sont caractérisés par une
priorité de service : un élément de priorité supérieure est servi même s’il n’est pas
arrivé le premier.
(c) Expliquer comment peut-on implémenter une pile à l’aide d’une file d’attente
avec priorité.
43
(d) Expliquer comment peut-on implémenter une file d’attente ordinaire à l’aide
d’une file d’attente avec priorité.
5. Ecrire un algorithme qui permette d’implémenter le modèle des files d’attente utili-
sant deux piles.
(b) Ecrire la procédure qui vérifie s’il existe un chemin allant d’une entrée donnée
vers une sortie donnée en utilisant une pile.
44
Chapitre 4
Structures Hiérarchiques
4.1.1 Introduction
4.1.2 Définitions
Un arbre est une structure non linéaire, c’est un graphe sans cycle où chaque nœud a
au plus un prédécesseur.
Graphe
45
Arbre
46
4.1.2.3 Niveau d’un nœud
– Le niveau de la racine = 0
– Le niveau de chaque nœud est égale au niveau de son père plus 1
– Niveau de E,F,G,H,I,J,K = 2
47
– Représentation d’un arbre généalogique
– Codage
Exemple : coder la chaine "structure arbre"
48
Caractère Code Caractère Code
s 0000 c 0001
t 010 e 001
r 11 a 100
u 011 b 101
4. Coder la chaine :
"structure arbre" ) 0000 010 11 011 0001 010 011 11 001 100 11 101 11 001
Les arbres peuvent être représentés par des tableaux, des listes non linéaires ou tous
les deux :
L’arbre du premier exemple peut être représenté par un tableau comme suit :
49
4.1.4.2 Représentation dynamique
Pour manipuler les structures de type arbre, on aura besoin des primitives suivantes :
– Allouer (N) : créer une structure de type Tnœud et rendre son adresse dans N.
– Liberer(N) : libérer la zone pointée par N.
– Aff_Val(N, Info) : Ranger la valeur de Info dans le champs info du nœud pointé
par N.
– Af f _F ilsi (N1,N2) : Rendre N2 le fils numéro i de N1.
– F ilsi (N) : donne le fils numéro i de N.
– Valeur(N) : donne le contenu du champs info du nœud pointé par N.
Le parcours d’un arbre consiste à passer par tous ses nœuds. Les parcours permettent
d’effectuer tout un ensemble de traitement sur les arbres. On distingue deux types de
parcours :
50
1. Parcours en profondeur
Dans un parcours en profondeur, on descend le plus profondément possible dans
l’arbre puis, une fois qu’une feuille a été atteinte, on remonte pour explorer les autres
branches en commençant par la branche "la plus basse" parmi celles non encore
parcourues. L’algorithme est le suivant :
51
Procédure PPPostfixe( nœud : Pointeur(Tnœud));
Début
Si (nœud 6= Nil) Alors
Pour i de 1 à NbFils faire
PPPostfixe(F ilsi (nœud))
Fin Pour;
Afficher(Valeur(nœud)) ;
Fin Si;
Fin;
A,B,E,F,C,G,H,L,M,I,D,J,K
E,F,B,G,L,M,H,I,C,J,K,D,A
2. Parcours en largeur
Dans un parcours en largeur, tous les nœuds à une profondeur i doivent avoir été
visités avant que le premier nœud à la profondeur i + 1 ne soit visité. Un tel parcours
nécessite que l’on se souvienne de l’ensemble des branches qu’il reste à visiter. Pour
ce faire, on utilise une file d’attente.
52
Procédure PL( nœud : Pointeur(Tnœud));
Var N : Pointeur(Tnœud) ;
Début
Si (nœud 6= Nil) Alors
InitFile ; Enfiler(Neuud) ;
Tant que (Non(FileVide)) faire
Défiler(N) ;
Afficher(Valeur(N)) ;
Pour i de 1 à NbFils faire
Si (F ilsi (N) 6= Nil) Alors
Enfiler(F ilsi (N)) ;
Fin Si;
Fin Pour;
Fin TQ;
Fin Si;
Fin;
A,B,C,D,E,F,G,H,I,J,K,L,M
53
4.1.6.2 Recherche d’un élément
54
4.1.6.3 Calcul de la taille d’un arbre
– Arbre m-aire : un arbre m-aire d’ordre n est un arbre ou le degré maximum d’un
nœud est égal à n.
– B-Arbre : Un arbre B d’ordre n est un arbre où :
– la racine a au moins 2 fils
– chaque nœud, autre que la racine, a entre n/2 et n fils
– tous les nœuds feuilles sont au même niveau
– Arbre binaire : c’est un arbre ou le degré maximum d’un nœud est égal à 2.
– Arbre binaire de recherche : c’est un arbre binaire où la clé de chaque nœud est
supérieure à celles de ses descendants gauche, et inférieure à celles de ses descendants
droits.
55
4.2 Les arbres binaires de recherche
4.2.1 Définition
Les arbres binaires de recherche sont utilisés pour accélérer la recherche dans les arbres
m-aires. Un arbre binaire de recherche est un arbre binaire vérifiant la propriété suivante :
soient x et y deux nœuds de l’arbre, si y est un nœud du sous-arbre gauche de x, alors
clé(y) clé(x), si y est un nœud du sous-arbre droit de x, alors clé(y) clé(x).
Les arbres de recherche binaires sont implémentés de la même manière que celles m-aires
(statique ou dynamique)
56
4.2.2.2 Représentation dynamique
– Allouer (N) : créer une structure de type TNoeud et rendre son adresse dans N.
– Liberer(N) : libérer la zone pointée par N.
– Aff_Val(N, Info) : Ranger la valeur de Info dans le champs info du nœud pointé
par N.
– Aff_Clé(N, Clé) : Ranger la valeur de Clé dans le champs Clé du nœud pointé
par N.
– Aff_FG(N1,N2) : Rendre N2 le fils gauche de N1.
– Aff_FD(N1,N2) : Rendre N2 le fils droit de N1.
– FG(N) : donne le fils gauche de N.
– FD(N) : donne le fils droit de N.
– Valeur(N) : donne le contenu du champs info du nœud pointé par N.
– Clé(N) : donne le contenu du champs Clé du nœud pointé par N.
57
4.2.4 Traitements sur les ABR
4.2.4.1 Parcours
De même que pour les arbres m-aire le parcours des ARB peut se faire en profondeur
ou en largeur :
– En profondeur
Trace : 15 6 3 2 4 7 13 9 18 17 20
58
Procédure Infixe( noeud : Pointeur(TNoeud));
Début
Si (nœud 6= Nil) Alors
Infixe(FG(noeud)) ;
Ecrire(Valeur(noeud)) ;
Infixe(FD(noeud)) ;
Fin Si;
Fin;
Trace : 2 3 4 6 7 9 13 15 17 18 20
Trace : 2 4 3 9 13 7 6 17 20 18 15
– En largeur
59
Procédure PL( noeud : Pointeur(TNoeud));
Var N : Pointeur(TNoeud) ;
Début
Si (noeud 6= Nil) Alors
InitFile ;
Enfiler(noeud) ;
Tant que (Non(FileVide)) faire
Défiler(N) ;
Afficher(Valeur(N)) ;
Si (FG(N) 6= Nil) Alors
Enfiler(FG(N)) ;
Fin Si;
Si (FD(N) 6= Nil) Alors
Enfiler(FD(N)) ;
Fin Si;
Fin TQ;
Fin Si;
Fin;
60
4.2.4.2 Recherche
4.2.4.3 Insertion
L’élément à ajouter est inséré là où on l’aurait trouvé s’il avait été présent dans l’arbre.
L’algorithme d’insertion recherche donc l’élément dans l’arbre et, quand il aboutit à la
conclusion que l’élément n’appartient pas à l’arbre (l’algorithme aboutit sur NIL), il insère
l’élément comme fils du dernier nœud visité.
4.2.4.4 Suppression
61
Cas
Action
FG(N) FD(N) Exemple
Nil Nil Feuille (2,4,17) Remplacer N par Nil
Nil 6= Nil 7 Remplacer N par FD(N)
6= Nil Nil 13 Remplacer N par FG(N)
1- Rechercher le plus petit descendant à droite de
6= Nil 6= Nil 6 N soit P (7)
2- Remplacer Valeur(N) par Valeur(P) (6 7)
3- Remplacer P par FD (P) (7 13 )
4.2.5 Equilibrage
Ces deux ARB contiennent les mêmes éléments, mais sont organisés différemment. La
profondeur du premier est inférieure à celle du deuxième. Si on cherche l’élément 10 on
devra parcourir 3 éléments (50, 20, 10) dans le premier arbre, par contre dans le deuxième,
on devra parcourir 5 élément (80, 70, 50, 20,10). On dit que le premier arbre est plus
équilibré.
Si on calcule la complexité de l’algorithme de recherche dans un arbre de recherche binaire,
on va trouver O(h) ou h est la hauteur de l’arbre. Donc plus l’arbre est équilibré, moins
élevée est la hauteur et plus rapide est la recherche.
On dit qu’un ARB est équilibré si pour tout nœud de l’arbre la différence entre la hauteur
du sous-arbre gauche et du sous-arbre droit est d’au plus égalé à 1. Il est conseillé toujours
de travailler sur un arbre équilibré pour garantir une recherche la plus rapide possible.
L’opération d’équilibrage peut être faite à chaque fois qu’on insère un nouveau nœud où
à chaque fois que le déséquilibre atteint un certain seuil pour éviter le coût de l’opération
d’équilibrage qui nécessite une réorganisation de l’arbre.
62
4.3 Les tas (Heaps)
4.3.1 Introduction
Pour implémenter une file d’attente avec priorité, souvent utilisée dans les systèmes
d’exploitation, on peut utiliser :
– Une file d’attente ordinaire (sans priorité), l’insertion sera alors simple (à la fin) en
O(1), mais le retrait nécessitera la recherche de l’élément le plus prioritaire, en O(n).
– Un tableau (ou une liste) trié où le retrait sera en O(1) (le premier élément), mais
l’insertions nécessitera O(n).
Les tas apportent la solution à ce problème.
4.3.2 Définition
Un tas (heap en anglais) est un arbre qui vérifie les deux propriétés suivantes :
1. C’est un arbre binaire complet c’est-à-dire un arbre binaire dont tous les niveaux sont
remplis sauf éventuellement le dernier où les éléments sont rangés le plus à gauche
possible.
63
4.3.3 Opérations sur les tas
Pour coder une file d’attente avec priorité par un tas, on doit définir les opérations
d’ajout et de retrait.
4.3.3.1 Ajout
Pour ajouter un nouvel élément dans la file avec priorité c-à-d dans le tas on doit :
2. Attacher ce nœud dans le dernier niveau dans la première place vide le plus à gauche
possible (créer un nouveau niveau si nécessaire). On obtient toujours un arbre binaire
complet mais pas nécessairement un tas.
3. Comparer la clé du nouveau nœud avec celle de son père et les permuter si nécessaire,
puis recommencer le processus jusqu’il n’y ait plus d’éléments à permuter.
La complexité de cette opération est de O(h = Log2 (n)) si n est le nombre d’éléments.
4.3.3.2 Retrait
64
1. Remplacer la valeur de la racine par la valeur de l’élément le plus à droite dans le
dernier niveau.
2. Supprimer de l’arbre cet élément (le plus à droite dans le dernier niveau), on obtient
un arbre binaire mais pas nécessairement un tas.
3. On compare la valeur de la racine avec les valeurs de ses deux fils et on la permute
avec la plus grande. On recommence le processus jusqu’il n’y ait plus d’éléments à
permuter.
Exemple :
Les tas peuvent être implémentés dynamiquement exactement comme les ARB, et sont
utilisés par le même modèle.
Une représentation statique très efficace utilisant des tableaux est très utilisée en pratique,
elle consiste à ranger les éléments du tas dans un tableau selon un parcours en largeur :
65
On remarque sur le tableau obtenu que le fils gauche d’un élément d’indice i se trouve
toujours s’il existe à la position 2i, et son fils droit se trouve à la position (2i + 1) et son
père se trouve à la position i/2. Les opérations d’ajout et de retrait sur le tas statique se
font de la même façon que dans le cas du tas dynamique. Avec ce principe les opérations
d’ajout et de retrait se font d’une manière très simple et extrêmement efficace.
Les tas sont utilisés même pour le tri des tableaux : on ajoute les éléments d’un tableau à
un tas, puis on les retire dans l’ordre décroissant.
4.4 Exercices
1. Arbres m-aires
Ecrire sur les arbres m-aires les fonctions récursives qui retournent :
– Le père d’un nœud donné,
– Le maximum dans un arbre donné,
– Le minimum dans un arbre donné.
(a) Compréhension
– Construire un arbre de recherche binaire à partir des clés ordonnées suivantes :
25 60 35 10 5 20 65 45 70 40 50 55 30 15
– Ajouter à l’arbre obtenu et dans l’ordre, les éléments suivants :
22 62 64 4 8
– Supprimer de l’arbre obtenu et dans l’ordre les éléments suivants :
15 70 50 35 60 25
(b) Ecrire sur les arbres de recherche binaires les fonctions récursives qui retournent :
– Vrai si un nœud donné est une feuille et Faux sinon.
– Le nombre de feuilles de l’arbre.
– La taille de l’arbre.
66
– Le père d’un nœud donné.
– Le successeur d’un nœud donné (l’élément immédiatement supérieur).
– Le prédécesseur d’un nœud donné (l’élément immédiatement inférieur).
– Le maximum dans un arbre donné.
– Le minimum dans un arbre donné.
– La hauteur d’un arbre.
(d) Ecrire la fonction qui crée un arbre binaire de recherche équilibré à partir d’un
tableau trié.
4. Algorithme de Huffman
Un village d’Anglesey (petite île au sud-ouest de l’Angleterre) porte l’un des plus long
nom au monde : "Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch" Les
habitants du village sont fières de ce merveilleux nom mais réalisent, avec tristesse,
que (certainement par manque de bois !) toutes les affiches annonçant leur village ne
contiennent qu’une toute petit partie du nom originale : "Llanfairpwll". Pour être
certain de préserver leur héritage culturel, ils décident d’encoder le nom original de
leur village en une séquence de bits. Bien entendu, ils veulent que cette séquence soit
la plus courte possible.
(b) Utiliser ce tableau pour construire, avec l’algorithme de Huffman, l’arbre binaire
donnant le meilleur codage. (Lorsque plusieurs arbres on le même poids - ici
poids = fréquence- choisir les arbres selon l’ordre lexicographique)
(c) Donner un tableau associant à chacune des lettres son code binaire.
(d) Quel est le nombre de bits minimal nécessaire pour encoder le nom de ce char-
mant village.
67
Pour les curieux : Ce nom de village n’est pas une invention ! ! Le nom date du 19ème
siècle et se traduit, plus ou moins, comme : "St Mary’s church in the hollow of the
white hazel near a rapid whirlpool and the church of St Tysilio of the red cave"
(voir http ://www.bbc.co.uk/h2g2/guide/A403642). Le nom complet du village n’est
maintenant utilisé que pour impressionner les touristes. Le nom "Llanfairpwll" est
utilisé par les habitants.
5. Tas
(a) Compréhension
– Construire un tas à partir des clés ordonnées suivantes :
25 60 35 10 5 20 65 45 70 40 50 55 30 15
– Ajouter au tas et dans l’ordre les éléments suivants :
22 62 64 4 8
– Supprimer du tas et dans l’ordre les éléments suivants :
15 70 50 35 60 25
(d) Ecrire un algorithme qui permet de trier un tableau en utilisant un tas. Calculer
la complexité de cet algorithme.
68
Chapitre 5
Structures en Tables
5.1 Introduction
1. Annuaire téléphonique
2. Dictionnaire
3. Codage
69
Clé (Mot) Information(Code)
a 001
b 010
. .
. .
Le problème posé est : comment organiser la table pour que les accès (recherche, inser-
tion, suppression) soient les plus rapides possibles ?
Il consiste à ranger les clés dans la table dans l’ordre de leur arrivée, les une à la suite
des autres, c’est-à-dire que l’ajout se fait toujours à la fin de la table. La recherche d’une
clé consiste à tester les éléments l’un après l’autre jusqu’à la trouver c’est-à-dire passer par
tous les éléments placés avant. La recherche est alors en moyenne de n/2 (O(n)).
La table est triée selon les valeurs des clé : la recherche est en log2 (n) c-à-d dichotomique.
5.4.1 Principe
C’est une technique très utilisée en informatique, elle se base sur une fonction h appelée
fonction de hachage ou de hashcoding, qui appliquée à la clé fournit l’indice correspondant
dans la table.
70
Exemple : Codage
4. Hachage de Fibonacci
C’est une fonction de hachage fréquemment utilisée :
h(clé) = |N ⇥ (clé ⇥ r |clé ⇥ r|)|
p
où || donne la partie entière, avec r = 5 1
2
La fonction de hachage doit donner des valeurs entières dans l’intervalle des indices de la
tables : 0 h(clé) N .
En plus, cette fonction doit être la plus distribuée possible sur cet intervalle, pour que les
informations ne se concentrent pas dans une partie de la table.
71
5.4.3 Problème de collisions
Un problème sérieux se pose avec les fonctions de hachage si deux clés différentes
donnent lieu à une même adresse lorsqu’on leur applique la fonction de hachage, c-à-d
h(clé1 ) = h(clé2 ).
Une telle situation est appelée « collision » et plusieurs solutions existent pour sa résolution.
Elle consiste à placer toutes les clés qui donnent le même indice qu’une clé existante
dans une liste linéaire chainée, appelée liste de débordement :
Cette méthode est généralement utilisée si le nombre d’informations est peu par rap-
port à la taille de la table. On range la clé qui a causé la collision (k par exemple) dans la
première position vide dans la séquence cyclique :
h(k 1), h(k 2), · · · , 0, N 1, N 2, . . . , h(k + 1)
Exemple :
On doit garder, dans ce cas, une case toujours vide pour indiquer la fin de la recherche,
c-à-d une valeur interdite dans les clés.
72
5.4.3.3 Chaînage interne séparé
On ajoute à la table une partie réservée aux collisions de taille M . La taille de la table
sera donc N + M .
On insère l’élément en collision dans la première place vide dans la partie des collisions et
on le relie par un chaînage.
Exemple :
5.5 Exercices
73
– Répéter les mêmes questions en utilisant la méthode de chaînage interne séparé.
74
Chapitre 6
Les graphes
6.1 Introduction
La notion de graphe est une structure qui permet de représenter plusieurs situations
réelles, en but de leur apporter des solutions mathématiques et informatique, tel que :
– Les réseaux de transport (routiers, ferrés, aériens · · · ),
– Les réseaux téléphoniques, électriques, de gaz,· · · etc,
– Les réseaux d’ordinateurs,
– Ordonnancement des tâches,
– Circuits électroniques,
– ···
Les arbres et les listes linéaires chaînées ne sont que des cas particuliers des graphes.
6.2 Définitions
6.2.1 Graphe
Un graphe est défini par un couple (S, A) où S est un ensemble de sommets (nœuds ou
points) et A est un sous ensemble du produit cartésien (S ⇥ S) représentant les relations
existant entre les sommets.
Exemple : S = 1, 2, 3, 4, 5, 6, 7
A = (1, 2), (1, 4), (2, 5)(3, 5), (3, 6), (4, 2), (5, 4), (6, 6)
75
6.2.2 Graphe orienté
C’est un graphe où les relations entre les sommets sont définies dans un seul sens
(exemple précédent). Dans ce cas les relations sont appelées "arcs".
C’est un graphe où les relations sont définies dans les deux sens. Dans ce cas, les
relations sont appelées "arêtes".
C’est un graphe orienté ou non où à chaque arc ou arête correspond une valeur ou une
étiquette représentant son coût (ou distance).
76
6.2.5 Origine et extrémité
6.2.6 Chemin
6.2.7 Circuit
6.2.8 Chaine
6.2.9 Cycle
Un graphe connexe est un graphe où pour tout couple de sommets (x, y), il existe une
chaîne d’arcs les joignant.
Exemple : Pour le couple (1, 6), il existe une chaîne d’arcs, et il n’en existe pas pour (1,7).
Un graphe fortement connexe est un graphe où pour tout couple de sommets (x, y), il
existe un chemin d’arcs les joignant.
77
Exemple : Pour (3, 2) il existe un chemin {(3, 5), (5, 4), (4, 2)} mais il n’en existe pas pour
(2, 3).
Les graphes peuvent être représentés en deux manières : en listes d’adjacence (dyna-
mique) ou en matrice d’adjacence (statique)
Dans cette représentation, les successeurs d’un nœud sont rangés dans une liste linéaire
chainée. Le graphe est représenté par un tableau T où T [i] contient la tête de la liste des
successeurs du sommet numéro i. Le graphe (S, A) présenté au début de cette section peut
être représenté comme suit :
Les listes d’adjacence sont triées par numéro de sommet, mais les successeurs peuvent
apparaître dans n’importe quel ordre.
78
6.3.2 Matrice d’adjacence
Dans cette représentation le graphe est stocké dans un tableau à deux dimensions de
valeurs booléennes ou binaires. Chaque case (x, y) du tableau est égale à vrai (1) s’il existe
un arc de x vers y, et faux (0) sinon. Dans la matrice suivante, on représente le graphe
précédent (1 pour vrai et 0 pour faux ) :
1 2 3 4 5 6 7
1 0 1 0 1 0 0 0
2 0 0 0 0 1 0 0
3 0 0 0 0 1 1 0
4 0 1 0 0 0 0 0
5 0 0 0 1 0 0 0
6 0 0 0 0 0 1 0
7 0 0 0 0 0 0 0
Il est clair que la matrice d’adjacence d’un graphe non orienté est symétrique puisque
chaque arête existe dans les deux sens.
Pour un graphe étiqueté les valeurs de la matrice peuvent être les étiquettes elles-
mêmes, avec une valeur particulière pour les arcs inexistant. Par exemple le graphe étiqueté
de l’exemple peut être représenté comme suit :
1 2 3 4 5 6 7
1 -1 10 -1 200 -1 -1 -1
2 -1 -1 -1 -1 125 -1 -1
3 -1 -1 -1 -1 22 17 -1
4 -1 96 -1 -1 -1 -1 -1
5 -1 -1 -1 12 -1 -1 -1
6 -1 -1 -1 -1 -1 3 -1
7 -1 -1 -1 -1 -1 -1 -1
79
La représentation matricielle permet de tirer des conclusions intéressantes sur les graphes
en utilisant les calculs matriciels.
De même que pour les arbres, il est important de pouvoir parcourir un graphe selon
certaines règles, cependant, le parcours des graphe est un peut différent de celui des arbres.
Dans un arbre, si on commence à partir de la racine on peut atteindre tous les nœuds,
malheureusement, ce n’est pas le cas pour un graphe où on est obligé de reprendre le
parcours tant qu’il y a des sommets non visités. En plus un graphe peut contenir des
cycles, ce qui conduit à des boucles infinies de parcours.
Il existe deux types de parcours de graphes : le parcours en profondeur d’abord (Depth
First Search) et le parcours en largeur d’abord (Breadth First Search).
Le principe du DFS est de visiter tous les sommets en allant le plus profondément
possible dans le graphe.
80
Var Graphe : Tableau[1..n,1..n] de booleen ;
Visité : Tableau[1..nn] de booleen ;
Procédure DFS( Sommet : entier ;);
var i : entier ;
Début
Visité[Sommet] Vrai ;
Afficher(sommet) ;
Pour i de 1 à n faire
Si (Graphe[sommet,i] et non Visité[i]) Alors
DFS(i)
Fin Si;
Fin Pour;
Fin;
Appel :
Pour s de 1 à n faire
Si (Non Visité[s]) Alors
DFS(s)
Fin Si;
Fin Pour;
Trace : 1 2 5 4 3 6 7
81
6.4.2 En largeur d’abord (BFS)
Dans ce parcours, un sommet s est fixé comme origine et l’on visite tous les sommet
situés à une distance k de s avant de passer à ceux situés à k + 1. On utilise pour cela une
file d’attente.
Fin;
Appel :
Pour s de 1 à n faire
Si (non Visité[s]) Alors
BFS(s)
Fin Si;
Fin Pour;
Trace : 1 2 4 5 3 6 7
82
6.5 Plus court chemin (algorithme de Dijkstra)
1- D = xi , i = 0 // xi sommet de départ
j = min{ j , k + lkj }
4- Aller à 2 si D 6= S
Exemple :
83
D 1 2 3 4 5 6
x1 0 3 8 6 1 1
x1 , x2 0 3 8 5 9 1
x1 , x2 , x4 0 3 7 5 9 12
x1 , x2 , x4 , x3 0 3 7 5 8 12
x1 , x2 , x4 , x3 , x5 0 3 7 5 8 10
x1 , x2 , x4 , x3 , x5 , x6 0 3 7 5 8 10
6.6 Exercices
1. Ecrire une fonction permettant de vérifier s’il existe un chemin entre deux sommets
donnés.
2. Ecrire une fonction permettant de vérifier s’il existe une chaîne entre deux sommets
donnés.
3. Ecrire une fonction permettant de vérifier s’il existe un circuit dans le graphe.
4. Ecrire une fonction permettant de vérifier s’il existe un cycle dans le graphe.
6. Ecrire une fonction permettant de détecter les composantes connexes d’un graphe
sachant qu’une composante connexe est un ensemble de sommets dont chaque paire
est reliée par au moins une chaîne.
84
7. Ecrire une fonction permettant de détecter les composantes fortement connexes d’un
graphe sachant qu’une composante fortement connexe est un ensemble de sommets
dont chaque paire est reliée par un chemin.
8. Reprendre les mêmes exercices avec un graphe représenté par des listes d’adjacence.
9. Ecrire une procédure permettant de données les chemins minimums à partir d’un
sommet donné vers tous les autres en utilisant l’algorithme de Dijkstra.
85
Chapitre 7
Preuve d’algorithmes
7.1 Introduction
La preuve d’un algorithme consiste à montrer que cet algorithme transforme bien ses
entrées en les sorties attendues, autrement dit, tout état initial de l’algorithme conduit en
sortie à un état final qui vérifie une certaine propriété (ex : factorielle = n!).
La méthode usuelle pour vérifier la correction du’un algorithme P , devant calculer la
fonction f , est la méthode des tests : on choisit un échantillon fini de données d1 , ..., dn on
fait exécuter l’algorithme P pour chacune d’entre elles et on vérifie que :
8 d 2 D, P (d) = f (d)
L’insuffisance de cette méthode est évidente dès que l’échantillon testé ne recouvre pas
l’ensemble D des données.
La méthode des preuves d’algorithme est bien plus satisfaisante : elle consiste à prouver
mathématiquement que l’algorithme P est correct en démontrant qu’il :
1. termine (terminaison), et
86
Correction totale = Correction partielle + Terminaison
7.2.1 Terminaison
On dit qu’un algorithme P termine, si et seulement si, tout état initial E donne une
exécution terminante de P .
Soit l’algorithme P dont la correction est exprimée par une condition C, On dit que P
est partiellement correct si et seulement si, pour tout état initial E qui donne une exécution
terminante F = P (E) on a F (C) = V rai.
On dit que P est totalement correct si et seulement si tout état initial E donne une
exécution terminante F = P (E) qui vérifie F (C) = V rai.
7.2.4 Exemples :
Fin TQ;
2. Etant donné la propriété C = (r = max(x, y)). L’algorithme suivant n’est pas par-
tiellement correct parce qu’il ne vérifie pas C pour des cas d’exécutions terminantes
(x > y, r =?).
Si (x < y) Alors
r y
Fin Si;
87
3. L’algorithme suivant est partiellement correct et termine ; il est donc totalement
correct.
Si (x < y) Alors
r y
Sinon
r x
Fin Si;
4. L’algorithme suivant est partiellement correct mais ne termine pas (toujours) ; il n’est
donc pas totalement correct
Si (x < y) Alors
r y
Sinon
Tant que (x 6= y) faire
r x
Fin TQ;
Fin Si;
Pour vérifier la correction totale d’un algorithme, on doit vérifier qu’il est partiellement
correct et qu’il se termine. Pour cela, on utilise la logique de Hoare qui représente un
système déductif proposé par Tony Hoare. Elle permette de vérifier si un algorithme vérifie
nécessairement une certaine propriété à la fin de toutes ses exécutions.
Dans la logique de Hoare, la preuve d’un algorithme P est représentée par un triplet
appelé triplet de Hoare :
0
{c} P {c }
tel que
{c} : est une expression booléenne appelée la précondition,
88
P : l’algorithme (le programme),
0
{c } : est une expression booléenne appelée la postcondition.
Ce triplet est interprété comme suit : "Si les variables de P vérifient initialement la condi-
0
tion c alors, si P se termine, ces variables vérifieront la condition c après l’exécution de
P ".
Exemple
Algorithme Div;
Var a,b,r,q : entier ;
Début
Lire(a,b) ;
r a;
q 0;
Tant que (r b) faire
r r - b;
q q + 1;
Fin TQ;
Ecrire(q, r) ;
Fin.
La preuve consiste à démonter que ce triplet soit valide en utilisant un axiome et six
règles :
1. Axiome de l’affectation :
0
{c } x v {c}
0
Tel que c est la condition c où l’on remplace toute occurrence de x par v.
Exemple : {x = y} x 2 ⇤ x {x = 2 ⇤ y}
89
2. Règle de la séquence :
Exemple : Si [ {c}x 2{x = 2} ^ {x = 2}y x{y = 2}] alors [ {c}x 2; y x{y = 2}]
3. Règle de la conditionnelle :
h 0 0
i
Si {c & b} P1 {c } ^ {c & ¬b} P 2 {c }
h 0
i
alors {c} si b alors P1 sinon P2 F si {c }
Exemple :
Si [{x < y} r y {r = max(x, y)} ^ {x y} r x {r = max(x, y)}] Alors
[{V } si x < y alors r y sinon r x f insi {r = max(x, y)}]
4. Règle de la répétitive
5. Règle de conséquence
6. Règle de la conjonction
7. Règle de la disjonction
Pour démonter la terminaison de l’algorithme, il faut démontrer que toutes ses boucles
se terminent, pour cela, il faut démonter que l’expression de la condition de chaque boucle
90
forme une suite convergente. Cette démonstration peut être faite par la logique de Hoare
comme suit :
{c} Boucle {¬c}
7.4 Exemple
i 1;
r 1;
Tant que (i n) faire
r r*i ;
i i+1 ;
Fin TQ;
{n 0} i 1; r 1; T antque i n f aire r r ⇤ i; i
i + 1 f intq {r = n!}
91
{n 0}
{(n 0) ^ (1 = 0!) ^ (1 n + 1)}
i 1;
{(n 0) ^ (1 = (i 1)!) ^ (i n + 1)}
r 1;
{(n 0) ^ (r = (i 1)!) ^ (i n + 1)}
Tant que (i n) faire
{(n 0) ^ (r = (i 1)!) ^ (i n)}
r r ⇤ i;
{(n 0) ^ (r = i!) ^ (i n)}
i i + 1;
{(n 0) ^ (r = (i 1)!) ^ (i n + 1)}
Fin TQ;
{(n 0) ^ (r = (i 1)!) ^ (i n + 1) ^ (i > n)}
{r = n!}
7.5 Conclusion
La preuve d’un algorithme, même petit, est une opération très longue et fastidieuse,
même si l’application des règles est mécanique, l’invention de la précondition et la post-
condition n’est pas évidente et difficilement automatisable.
Malgré tout, la preuve formelle de hoare reste le seul moyen de preuve des algorithmes.
92
Chapitre 8
Sujets d’examens
93
2LMD 12 Fev 2008
La liste verticale contient les catégories des livres avec le nombre de
livres dans chacune, tandis que les listes horizontales contiennent les titres des
Examen d’algorithmique 1 livres avec leurs auteurs dans chaque catégorie.
14h-15h30 A1 1. Donner la déclaration des structures de données nécessaires à
l’implémentation de cette bibliothèque ainsi que la procédure
d’initialisation de ces structures. 1.5
Exercice 1 (10 pts) 2. Ecrire la procédure d’ajout d’une nouvelle catégorie (l’ajout se fait
toujours à la fin de la liste). 1.5
Dans cet exercice, un étudiant en informatique souhaite représenter sa 3. Ecrire la procédure d’insertion d’un nouveau livre (l’ajout se fait au
bibliothèque personnelle en utilisant une structure dynamique. La structure début de la liste) 2
proposée est représentée dans la figure suivante : 4. Ecrite la procédure qui permette d’afficher les livres d’une catégorie
donnée. 1.5
Bibliothèque 5. Ecrire la fonction qui retourne le nombre total de livre dans la
Algorithmique et Introduction to bibliothèque. 1
structures de données algorithms 6. Ecrire la procédure qui permette de supprimer une catégorie avec tous
Algorithmique 2 A. Aho H. Cormen ses livres 2.5
Exercice 2 (5 pts)
Architecture des Structure des
ordinateurs ordinateurs
1. Les listes (1, 6, 1, 6, 7, 9, 1, 10, 6) et (1, 3, 1, 4, 3, 2, 1, 4, 2) peuvent-
Architecture 2 Tenanbum M. Koudil elles représenter un tas statique ? Si non, quels échanges faut–il
effectuer pour obtenir un tas ?
2. Un tableau trié en ordre décroissant représente-t-il un tas ?
3. On veut réaliser une procédure qui purge une pile de toutes les
occurrences d’un entier donné (1 dans l’exemple):
Revues 0 a. Réaliser cette procédure en utilisant une
deuxième pile.
b. Réaliser cette procédure d’une manière
S.E : mécanismes de
récursive sans utiliser aucune autre
base structure (ni pile ni file)
Système A. Belkhir
1
d’exploitation
Tournez la page ../..
Exercice 3 (6 Pts)
1. Donner les déclarations des structures de données nécessaires à
On convient de représenter une image en noire et blanc à l’aide un arbre l’implémentation de ce modèle.
m-aire de degré 4 comme suit : 2. Soit la procédure suivante :
Une image toute noire est représentée par une feuille d’une valeur ‘N’ Procedure Traiter (Racine : Pointeur(TNoeud)) ;
Var P : Pointeur(TNoeud) ;
=> N I : entier ;
Debut
Une image toute blanche est représentée par une feuille d’une valeur ‘B’ Si Racine Nil etValeur(Racine) = ’C’ alors
P Fils1 ( Racine ) ;
=> B Aff_Fils1 ( Racine , Fils3 ( Racine ) ) ;
Aff_Fils3 ( Racine , Fils4 (Racine ) ) ;
Une image contenant les deux couleurs est représentée par un sous arbre dont Aff_Fils4 ( Racine, Fils2 ( Racine ) ) ;
la racine est de valeur ‘C’ et chaque fils représente un quart de l’image. Aff_Fils2 (Racine,P) ;
==>
L’arbre représentant cette image est le suivant :
Image
C
Bon courage
C C B C A.Djeffal
B N B N N N B B N B N B
Corrigé type Si P Nil alors Ecrire ( ‘Cette categorie existe déjà’ ) ;
Sinon
Exercice 1 Allouer ( Q ) ;
1. (1.5 pt) Aff_Val (Q, NCateg, 0, Nil) ;
Type TLivre = Structure Aff_Adr (Q,Nil) ;
Titre, Auteur : chaine ; Si PP = Nil alors Bibliotheque P
Suivant : Pointeur ( TLivre ) Sinon
Fin ; Aff_Adr (PP, Q) ;
FSi ;
Type TCategorie = Structure Fin;
NomCateg : chaine ;
NbLivre : entier ; 3. (2 pts)
TeteListeLivres : Pointeur ( TLivre ) Procedure AjouterLivre(NCateg, NTitre,NAuteur:chaine) ;
Suivant : Pointeur ( TCategorie ) ; Var
Fin ; P : Pointeur (TCategorie) ;
Var Q : Pointeur (TLivre) ;
Bibliotheque : Pointeur ( TCategorie ) ; Debut
P Bibliotheque ;
Procedure Initialisation ; TQ P Nil et NomCateg(P) NCateg Faire
Debut P Suivant ( P ) ;
Bibliotheque Nil ; FTQ ;
Fin ; Si P = Nil alors Ecrire( ‘Cette catégorie n’existe pas’)
Sinon
2. ( 1.5 pt) Allouer (Q) ;
Procedure AjouterCategorie ( NCateg : chaine) ; Aff_Adr(Q, TeteListeLivre(P)) ;
Var Aff _Val(Q, NTitre, NAuteur) ;
P, PP, Q : Pointeur (TCategorie) ; Aff_Val(P, NomCateg (P), NbLivre(P) + 1, Q) ;
Debut FSi
Fin ;
P Bibliotheque ;
PP Nil ;
TQ P Nil et NomCteg(P) NCateg Faire
PP P ;
P Suivant ( P ) ;
FTQ ;
4. (1.5 pt) 6. (2.5 pts)
Procedure Afficher ( NCateg : chaine) ; Procedure SupprimerCategorie ( NCateg : chaine) ;
Var Var
P : Pointeur (TCategorie) ;
Q : Pointeur (TLivre) ; Debut
Debut P Bibliotheque ;
P Bibliotheque ; PP Nil ;
TQ P Nil et NomCateg(P) NCateg Faire TQ P Nil et NomCateg(P) NCateg Faire
P Suivant ( P ) ; Pp Pil.
FTQ ; P Suivant ( P ) ;
Si P = Nil alors Ecrire( ‘Cette catégorie n’existe pas’) FTQ ;
Sinon Si P = Nil alors Ecrire( ‘Cette catégorie n’existe pas’)
Q TeteListeLibre(P) ; Sinon
TQ Q Nil Faire Q TeteListeLivre(P) ;
Ecrite (Titre(Q), Auteur(Q)) ; TQ Q Nil Faire
Q Suivant (Q) ; Q1 Q ;
FTQ ; Q Suivant(Q) ;
FSi Liberer (Q1) ;
Fin ; FTQ ;
Aff_Adr(PP, Suivant(P)) ;
5. (1 pt) Liberer (P) ;
FSi
Fonction NbreLivre :Entier ; Fin ;
Var
P : Pointeur (TCategorie) ; Exercice 2
Nb : entier ; 1. (1 pt)
Debut Le tableau (1,6,1,6,7,9,1,10,6) n’est pas un tas ; pour obtenir
Nb 0 ; un tas, il faut le mettre dans l’ordre suivant : ( 10,7,9,6,6,6,1,1,1)
P Bibliotheque ; Le tableau (1,3,1,4,3,2,1,4,2) n’est pas un tas ; pour obtenir
TQ P Nil Faire un tas, il faut le mettre dans l’ordre suivant : (4, 4,2,3,3,1,1,2)
Nb Nb + NbLivres(P) ; 2. (0.5 pt)
P Suivant (P) ; Oui un tableau trié dans l’ordre décroissant représente un tas.
Fin ;
NbreLivre Nb ;
Fin ;
3.a. (1.5 pt)
C
Procedure Purger ( P : Pile, n : entier) ; 2. (2 pts)
Var
P1 : Pile ;
x : entier ; C
B C C
Debut
InitPile(P1) ;
TQ non Pile_Vide (P) Faire B N B N
B B N N N N B B
Depiler ( P, x) ;
Si x n alors Empiler (P1 , x ) ;
FTQ ;
TQ non Pile_Vide(P1) Faire
Depiler ( P1 , x ) ;
Empiler ( P, x ) ;
FTQ ;
Fin ; L’image résultante est une rotation de 90° au sens des
b. (2 pts) aiguilles d’une montre.
Procedure Purger( P : Pile, n : entier ) ; 3. (3 pts)
Var Procedure Traiter (Racine : Pointeur(TNoeud)) ;
x : entier ; Var P : Pointeur(TNoeud) ;
Debut I : entier ;
Si non Pile_Vide(P) alors Debut
Depiler ( P, x ) ; Si Racine Nil etValeur(Racine) = ’C’ alors
Purger (P, n) ; P Fils1 ( Racine ) ;
Si x n alors Empiler ( P, x) ; Aff_Fils1 ( Racine , Fils3 ( Racine ) ) ;
FSi Aff_Fils3 ( Racine ,P) ;
Fin ; P Fils2 ( Racine ) ;
Aff_Fils2 ( Racine, Fils4 ( Racine ) ) ;
Exercice 3 Aff_Fils4 (Racine,P) ;
Soit une liste linéaire chaînée contenant des nombres entiers et dont la tête 6. Ecrire la fonction Val_Sup (R :Nœud, x :clé) qui retourne la valeur
est L : de la plus petite clé supérieure à x dans l’arbre binaire de recherche de
racine R.
1. Ecrire la fonction CAR(L) qui retourne la valeur du premier élément
de la liste. 7. Ecrire la fonction Fusion(R1,R2 : Nœud) qui prend deux arbres
binaires de recherches de racines R1, R2 et retourne la racine d’un
2. Ecrire la fonction CDR(L) qui retourne la liste sans le premier arbre binaire de recherche contenant les deux. Utilisez les deux
élément. procédures Suppr(R, clé) et Inser(R, clé) qui permettent
respectivement la suppression et l’insertion de clé dans l’arbre de
3. Ecrire la fonction CONS(x, L) qui retourne une liste dont le premier racine R.
élément est x et le reste est la liste L.
4. Ecrire la fonction Triée(L) qui retourne vrai si la liste L est triée dans
l’ordre croissant et faux sinon.
5. Ecrire la fonction Fusion(L1, L2) qui prend deux listes triées dans Bon courage
l’ordre croissant L1 et L2 et retourne une liste triée, dans le même
ordre, contenant les deux listes et cela en utilisant les fonctions
A.Djeffal
précédentes.
23 40
23 40
11 26 58
11 26 58
13 60
13 48
20
20
30 17
5.
26 40 Fonction NB_Supp(R :Nœud, x :clé) :entier ;
Debut
Si R=nil alors NB_Supp 0
11 58 Sinon
Si Clé(R)>x alors
NB_Supp 1 + NB_Supp(FG(R)) + NB_Supp(FD(R))
13 Sinon
NB_Supp NB_Supp(FG(R)) + NB_Supp(FD(R))
FSi
20 FSi
Fin;
6.
Fonction Val_Supp(R :Nœud, x :clé) :clé ;
Var DG,N : Nœud ;
Debut
N R;
TQ N<> Nil et clé(N) <> x Faire
Si Clé(N)>x alors DG N ; N FG(N)
Sinon N FD(N)
FSi
FTQ ;
Si N=Nil alors erreur
Sinon
N FD(N);
Si N=nil alors Val_Supp Clé(DG)
Sinon
TQ FG(N) <> nil faire
N FG(N) ;
FTQ
Val_Supp Clé(N) ;
FSi
FSi
Fin ;
7.
Fonction Fusion(R1,R2 :Nœud) :Noeud ;
Debut
TQ R2<> Nil Faire
Inser (R1, Clé(R2))
Suppr(R2, Clé(R2))
FTQ ;
Fusion R1 ;
Fin;
Il est demandé d’écrire les fonctions suivantes :
2LMD 10 Fev 2009
1. Fonction Moins(N1, N2 : pointeur(TMaillon)) : pointeur(TMaillon) ;
Retourne NIL si N1<=N2 et la liste représentant N1 – N2 sinon.
Examen d’algorithmique 1
14h-15h30 A2, A3 2. Fonction Mult(N1, N2 : pointeur(TMaillon)) : pointeur(TMaillon) ;
Retourne une liste représentant N1*N2.
On suppose que les fonctions suivantes sont disponibles et peuvent être Soit l’arbre binaire de recherche suivant composé de caractères et
utilisées : basé sur l’ordre alphabétique :
- Fonction Nbre(c :car) :entier retourne la valeur entière du caractère
numérique c : Nbre(‘1’)=1
Page 1
1. Donner les chaînes de caractères obtenus en parcourant l’arbre
en profondeur en l’ordre préfixe, infixe puis postfixe. 4. Fonction Caract(Racine:Pointeur(TNoeud), B:chaine):caractère;
qui retourne le caractère correspondant au code binaire donné
2. Donner l’arbre après la suppression de ‘D’ puis de ‘I’.
dans la chaine B.
Exemple : Caract(‘00’) = ‘H’ ; Caract(‘101’) = ‘B’
On associe à chaque caractère un code binaire représentant sa
position dans l’arbre binaire comme suit :
N.B : On utilise la relation d’ordre entre les caractères alphabétiques,
si C1 et C2 sont deux caractères, C1>C2 si C2 se trouve après C1
dans l’ordre alphabétique.
1 0
Bon courage
0 1 0 A. Djeffal
1 0
Page 2
Corrigé type 2. 3 Pts
Exercice 1
Fonction Mult(N1, N2 : pointeur(TMaillon)) : pointeur(TMaillon) ;
1. 4 Pts Var Un, Resultat : pointeur(TMaillon) ;
Debut
Fonction Moins(N1,N2: pointeur(TMaillon)): pointeur(TMaillon); Si N1 = NIL ou N2 = NIL alors Mult NIL ;
Var P, tete,Q : pointeur(TMaillon) ; Sinon
V1, V2, Reste : entier ; Allouer(Un) ; Aff_Adr(Un,Nil) ;
Debut Aff_Val(Un,’1’) ;
Si Comparer(N1,N2)<1 alors Moins NIL ; Resultat NIL ;
Sinon TQ Comparer(N2,NIL) =1 Faire
Reste 0 ; Resultat Somme (Resultats, N1) ;
Tete NIL ; N2 Moins(N2, Un) ;
TQ N1 NIL Faire FTQ ;
Allouer(P) ; Aff_Adr(P,NIL) ; Mult Resultat ;
Si Tete=NIL alors Tete P FSi
Sinon Aff_Adre(Q,P) ; Fin ;
FSi
V1 Nbre(Valeur(N1)) ; 3. 3 Pts
Si N2 NIL alors V2 Nbre(Valeur(N2))
Sinon V2 0 ; Fonction Div(N1, N2 : pointeur(TMaillon)) : pointeur(TMaillon) ;
FSi Var Un, Resultat, Reste : pointeur(TMaillon) ;
Si V1 (V2+ Reste) alors Debut
Aff_Val(P, Car(V1- V2 – Reste))) ; Si Comparer(N1,N2)=-1 ou N1 = NIL ou N2 = NIL alors Div Nil ;
Reste 0 ; Sinon
Sinon Resultat Nil ;
Aff_Val(P, Car(V1 + 10 - V2 - Reste))) ; Reste N1 ;
Reste 1 ; Allouer(Un) ; Aff_Adr(Un,Nil) ;
Fsi Aff_Val(Un,’1’) ;
Q P; TQ Comparer(Reste,N2) 0 Faire
N1 Suivant(N1) ; Resultat Somme(Resultat, Un) ;
Si N2 NIL alors N2 Suivant (N2) ; Reste Moins (Reste, N2) ;
FTQ ; FTQ
Mois tete ; Div Resultat ;
FSi FSi
Fin ; Fin
Page 3
Exercice 2 (2.5 pts) 3. 2.5 Pts
Fonction Code(Racine: Pointeur(TNoeud),C: caractère): chaîne ;
Procedure TrierTas(T :Tableau[1..N]) ; Var N : pointeur(TNoeud) ;
Var i : entier ; S : Chaine ;
Debut Debut
Init_Tas ; N Racine ; S ‘’ ;
TQ N NIL et Valeur(N) C Faire ;
Pour i =1 à N faire
Si Valeur(N)>C et FG(N) NIL alors
Inserer_Tas(T[i]) ;
S S + ‘1’ ; N FG(N) ;
FPour ;
FSi
Si Valeur(N)<C et FD(N) NIL alors
Pour i = 1 à N faire
S S + ‘0’ ; N FD(N) ;
Retirer_Tas(T[i]) ;
FSi
FPour ;
FTQ
Si N =NIL alors Code ‘#’ // Erreur : caractère inexistant
Fin ;
Sinon Code S ;
FSi
Exercice 3 (7.5 pts : + 1 + 2.5 + 2.5)
Fin ;
1. 1.5 Pt
- Parcours en profondeur préfixe : IDACBGEFHOMKJLN
4. 2.5 Pts
- Parcours en profondeur infixe : ABCDEFGHIJKLMNO
- Parcours en profondeur postfixe : BCAFEHGDJLKNMOI Fonction Caract(Racine:Pointeur(TNoeud), B:chaine):caractère;
Var N : pointeur(TNoeud) ;
2. 1 Pt I : entier ;
Debut
N Racine ; I 1;
TQ N NIL et I <= Longeur(B) Faire ;
Si B[I]=’1’ alors N FG(N) ;
Sinon N FD(N) ;
FSi
I I+1;
FTQ
Si N =NIL alors Caract ‘#’ // Erreur : code inexistant
Sinon Caract Valeur(N) ;
FSi
Fin ;
Page 4
2LMD 18 Mars 2009
N.B : Utiliser les primitives suivantes:
2. fonction PValeur(P :Pointeur(TMaillon), x : reel) :reel qui retourne la 1. Ecrite la fonction Hauteur(R: Pointeur(TNoeud)): Entier
valeur du polynôme P pour x donné. (utiliser x ^ y = xy) qui retourne la hauteur de l’arbre de recherche binaire de racine R.
3. fonction Somme(P1,P2 :Pointeur(TMaillon)): Pointeur(TMaillon)) 2. Ecrire la fonction Equilibré(R : Pointeur(TNoeud)) : Booleen
qui retourne la somme des deux polynômes P1 et P2. qui retourne vrai si l’arbre de recherche binaire de racine R est
équilibré et faux sinon.
4. fonction Dérivé(P:Pointeur(TMaillon)): Pointeur(TMaillon)) qui
retourne le polynôme égal à la dérivée du polynôme P.
5. fonction Intégrale(P:Pointeur(TMaillon)): Pointeur(TMaillon)) qui
retourne le polynôme égal à l’intégrale du polynôme P. Bon courage
A.Djeffal
Corrigé type TQ P1 Nil et P2 Nil Faire
Allouer (P) ; Aff_Adr(P,Nil) ;
Si Tete_Sm=Nil alors Tete_Sm P ;
Sinon Aff_Adr(Q,P) ;
Exercice 1 (12 Pts: 1 + 2 + 3 + 3 + 3)
FSi
Q P;
1. (1 Pt)
Si ValE(P1) = ValE(P2) alors
fonction Degré(P :Pointeur(TMaillon)) :entier ;
Aff_ValE(P, ValE(P1)) ; Aff_ValC(P, ValC(P1) + ValC(P2)) ;
Debut
Si P=Nil alors Degré 0 P1 Suivant(P1);
P2 Suivant(P2);
Sinon Degré ValE(P)
Sinon
FSi
Fin ; Si ValE(P1) > ValE(P2) alors
Aff_ValE(P, ValE(P1)) ; Aff_ValC(P, ValC(P1)) ;
P1 Suivant(P1);
2. (2 Pts)
Sinon
fonction PValeur(P :Pointeur(TMaillon), x : reel) :reel Aff_ValE(P, ValE(P2)) ; Aff_ValC(P, ValC(P2)) ;
P2 Suivant(P2);
Var S : reel ;
Debut FSi
S 0; FSi
FTQ ;
TQ P Nil Faire
S S + ValC(P)*(x ^ ValE(P));
P Suivant(P); Si P1 alors P12 P1 // P12 pointe l’éventuel reste de l’une des
Sinon P12 P2 ; // deux listes
FTQ
PValeur S ; FSi
Fin ;
TQ P12 Nil Faire // recopier le reste de la liste
3. (3 Pts) Allouer (P) ; Aff_Adr(P,Nil) ;
Si Tete_Sm=Nil alors Tete_Sm P ;
fonction Somme(P1,P2 :Pointeur(TMaillon)): Pointeur(TMaillon)) ; Sinon Aff_Adr(S,P) ;
Var Tete_Sm, Q, P, P12 : Pointeur(TMaillon); FSi
Debut Q P;
Aff_ValE(P, ValE(P12)) ; Aff_ValC(P, ValC(P12)) ;
Tete_Sm Nil ; // tête de la liste somme P12 Suivant(P12);
Q Nil ; // dernier élément de la liste somme FTQ
Somme Tete_Sm ;
Fin ;
4. (3 Pts) // Ajouter une constante C (supposons 1)
fonction Dérivé(P:Pointeur(TMaillon)): Pointeur(TMaillon)) Allouer (P1) ; Aff_Adr(P1,Nil) ;
Var Tete_D, Q, P1: Pointeur(TMaillon); Si Tete_D = Nil alors Tete_D P1 ;
Debut Sinon Aff_Adr(Q,P1) ;
Tete_D Nil ; // tête de la liste dérivée FSi
Q Nil ; // dernier élément de la liste dérivé Aff_ValC(P1, 1) ;
TQ P Nil et ValE(P) 0 Faire Aff_ValE(P1, 0) ;
Allouer (P1) ; Aff_Adr(P1,Nil) ; Intégrale Tete_Int;
Si Tete_D = Nil alors Tete_D P1 ; Fin ;
Sinon Aff_Adr(Q,P1) ; Exercice 2 (3 Pts: 1.5 + 1 + 0.5)
FSi
Q P1; 1. (1.5 Pt) 12
Aff_ValC(P1, ValC(P) * ValE(P)) ;
Aff_ValE(P1, ValE(P) - 1) ; 8 10
P Suivant(P);
FTQ ;
Dérivé Tete_D ;
Fin ; 6 7 1 2
5. (3 Pts)
fonction Intégrale(P:Pointeur(TMaillon)): Pointeur(TMaillon))
Var Tete_Int, Q, P1: Pointeur(TMaillon); 4 5
Debut
Tete_Int Nil ; // tête de la liste intégrale
Q Nil ; // dernier élément de la liste intégrale 2. Le tas statique : 12 8 10 6 7 1 2 4 5 (1 Pt)
10
TQ P Nil Faire 3. (0.5 Pt)
Allouer (P1) ; Aff_Adr(P1,Nil) ;
Si Tete_D = Nil alors Tete_D P1 ; 8 5
Sinon Aff_Adr(Q,P1) ;
FSi
Q P1;
Aff_ValC(P1, ValC(P) / (ValE(P) + 1)) ; 6 7 1 2
Aff_ValE(P1, ValE(P) + 1) ;
P Suivant(P);
FTQ ;
4
Exercice 3 (5 Pts : 2 + 3)
1. (2 Pts)
2. (3 Pts)
1. Fonction NbreOccur(L :Pointeur(TMaillon), C : caractère) : entier 1. Fonction NbrePréfixes (Racine: Pointeur(TNoeud),Ch: chaîne):entier ;
Qui retourne le nombre d’occurrences du caractère C dans la chaîne de Qui retourne le nombre de caractères dont le code commence par la
caractères représentée par la liste de tête L. chaîne Ch.
Exercice 1 (7 pts: 1 + 2 + 2 + 2) Soit les valeurs des clés triés selon l’ordre d’arrivé :
14, 23, 4, 9, 17, 11, 28, 16, 3, 7
On souhaite représenter les nombres entiers par des listes linéaires
chaînées de caractères où chaque chiffre d’un nombre est rangé dans un
maillon de la liste sous forme d’un caractère: - Dessiner l’arbre binaire de recherche obtenu en insérant ces clés dans l’ordre
Exemple : d’arrivé
Le nombre "678903" est représentée par la liste suivante : - Dessiner l’arbre après la après la suppression des clés : 11, 17, 23, 14
Tete Ecrire les fonctions suivantes :
6 7 8 9 0 3
1. Fonction NbrePairs (Racine: Pointeur(TNoeud)):entier ;
Il est demandé d’écrire en langage algorithmique vu dans le cours les Qui retourne le nombre de clés paires dans l’arbre.
fonctions suivantes :
2. Fonction SommeInterne (Racine: Pointeur(TNoeud)):entier ;
1. Fonction Pair (L :Pointeur(TMaillon)) : Booleen Qui retourne la somme des clés non feuilles dans l’arbre.
Qui retourne Vrai si le nombre représenté par L est pair, et Faux sinon.
Exercice 3 (5 pts : 3 + 1 + 1)
2. Fonction Mult100(L: Pointeur(TMaillon)) : Pointeur(TMaillon) ;
Qui retourne une nouvelle liste représentant le nombre représenté par - Dessiner l’arbre représentant le tas construit après l’insertion dans l’ordre
L multiplié par 100. des clés suivants : 14, 23, 4, 9, 17, 11, 28, 16, 3, 7
16
4 28
3 9
7
Exercice 3 (5 pts : 3 + 1 + 1) - Donner le tas (arbre) après un retrait
28
17 11
17 23
16 14 4 7
16 14 4 11
9 3
9 3 7
28 17 23 16 14 4 11 9 3 7
Université Mohamed Khider-Biskra 3. Ecrire la procédure Acheter(Med, NbBoites, Prix) permet-
Faculté des Sciences Exactes et Sciences de la Nature et de la Vie tant au pharmacien d’alimenter son stock par ’NbBoites’ du
Département d’informatique médicament ’Med’ ayant le prix unitaire ’Prix’ DA. On considère
qu’un médicament prenne toujours le nouveau prix.
2ème année LMD ALGO1 4. Ecrire la fonction PrixStock permettant de calculer le prix total
29 Jan 2012 8:00-9:30, Amphi H des médicaments dans le stock.
PARACETAMOL
Exemple : 5 boîtes
117.00 DA
Stock
PARACETAMOL ACTIFED ASPIRINE
5 boîtes 15 boîtes … 44 boîtes DOLIPRANE UPSA
117.00 DA 125.25 DA 78.25 DA 10 boîtes 44 boîtes
200.48 DA 78.25
On vous demande de :
ACTIFED MENTHOL RUMAFED VICK
1. Donner les structures de données nécessaires à la représentation 15 boîtes 2 boîtes 7 boîtes 40 boîtes
de ce stock. 125.25 DA 171.66 163.56 49.67
94
On vous demande de : 2. Donner cette structure après l’ajout de 40 puis 22.
1. Donner les structures de données nécessaires à la représentation 3. Donner cette structure après la suppression de 19 puis 28.
de ce stock.
2. Réécrire la procédure Vendre décrite dans l’exercice précédent sur
la nouvelle structure.
NB : On donne la procédure Nettoyer (Stock) permettant de FFF Bonne chance FFF
supprimer du stock tous les médicaments ayant une quantité nulle. A.Djeffal
3. Réécrire la procédure Acheter décrite dans l’exercice précédent
sur la nouvelle structure.
4. Réécrire la fonction PrixStock décrite dans l’exercice précédent
sur la nouvelle structure.
Exercice 3 (3 pts : 1 + 1 + 1)
28
17 24
14 16 19 21
95
Corrigé type
Procédure Vendre( Med : chaine, NbBoites : entier);
Var P,PP : Pointeur(TMaillon) ;
Début
P Stock ;
PP Nil ;
Tant que ((P 6= Nil et Libellé(P) 6= Med) faire
PP P;
P Suivant(P) ;
Exercice 1 : Listes linéaires chainées Fin TQ;
Si (P 6= Nil) Alors
Si (Quantité(P)< NbBoites) Alors
Ecrire(’Quantité insuffisantes’)
Sinon
1. Structures de données (1 pt) A↵ Quantité(P,Quantité(P)-NbBoites) ;
Si (Quantité(P) = 0) Alors
Si (PP=Nil) Alors
Stock Suivant(Stock)
Sinon
A↵ Adr(PP,Suivant(P))
Fin Si;
Type TMaillon = Structure
Libérer(P) ;
Libellé : chaine ; Fin Si;
Quantité : entier ;
PrixUnit : réel ; Fin Si;
Suivant : Pointeur(TMaillon) ; Sinon
Fin ; Ecrire(’Ce médicament n’existe pas’) ;
Var Stock : Pointeur(TMaillon) ; Fin Si;
Fin;
96
3. Procédure Acheter(Med, NbBoites, PrixUnit) (2.5 pts)
Fonction PrixStock() : réel;
Var P : Pointeur(TMaillon) ;
S : réel
Début
P Stock ;
S 0;
Procédure Acheter( Med : chaine, NbBoites : entier, PrixU- Tant que ((P 6= Nil) faire
nit : réel); S S + Quantité(P) ⇥ PrixUnit(P) ;
Var P : Pointeur(TMaillon) ; P Suivant(P) ;
Début Fin TQ;
P Stock ; PrixStock S;
Tant que ((P 6= Nil et Libellé(P) 6= Med) faire Fin;
P Suivant(P) ;
Fin TQ;
Si (P 6= Nil) Alors
A↵ Quantité(P,Quantité(P)+NbBoites) ; Exercice 2 : Arbres de recherche binaires
A↵ PrixUnit(P,PrixUnit) ;
Sinon
Allouer(P) ; 1. Structures de données (1 pt)
A↵ Libellé(P,Med) ;
A↵ Quantité(P,NbBoites) ;
A↵ PrixUnit(P,PrixUnit) ; Type TNoeud = Structure
A↵ Adr(P,Stock) ; Libellé : chaine ;
Stock P; Quantité : entier ;
Fin Si; PrixUnit : réel ;
FG,FD : Pointeur(TNoeud) ;
Fin;
Fin ;
Var Stock : Pointeur(TNoeud) ;
97
2. Procédure Vendre(Med, NbBoı̂tes) (3 pts)
Procédure Acheter( Med : chaine, NbBoites : entier, PrixU-
nit : réel);
Var P,PP : Pointeur(TNoeud) ;
Procédure Vendre( Med : chaine, NbBoites : entier); Début
Var P,PP : Pointeur(TNoeud) ; P Stock ; PP Nil ;
Début Tant que ((P 6= Nil et Libellé(P) 6= Med) faire
P Stock ; PP P;
PP Nil ; Si (Libellé(P)> Med) Alors
Tant que ((P 6= Nil et Libellé(P) 6= Med) faire P FG(P)
PP P; Sinon
Si (Libellé(P)> Med) Alors P FD(P)
P FG(P) Fin Si;
Sinon
P FD(P) Fin TQ;
Fin Si; Si (P 6= Nil) Alors
A↵ Quantité(P,Quantité(P)+NbBoites) ;
Fin TQ; A↵ PrixUnit(P,PrixUnit) ;
Si (P 6= Nil) Alors Sinon
Si (Quantité(P)< NbBoites) Alors Allouer(P) ;
Ecrire(’Quantité insuffisante’) A↵ Libellé(P,Med) ;
Sinon A↵ Quantité(P,NbBoites) ;
A↵ Quantité(P,Quantité(P)-NbBoites) ; A↵ PrixUnit(P,PrixUnit) ;
Si (Quantité(P) = 0) Alors A↵ FG(P,Nil) ; A↵ FD(P,Nil) ;
Nettoyer(P) Si (PP=Nil) Alors
Fin Si; Stock P
Fin Si; Sinon
Si (Libellé(P)>Med) Alors
Sinon A↵ FG(PP,P)
Ecrire(’Ce médicament n’existe pas’) ; Sinon
Fin Si; A↵ FD(PP,P)
Fin; Fin Si;
Fin Si;
Fin Si;
Fin;
3. Procédure Acheter(Med, NbBoites, PrixUnit) (3 pts)
98
4. La fonction PrixStock (2 pt) 3. Impossible de supprimer 19 du tas (0.5 pt). Après le retrait de 28,
le tas devient (0.5 pt) :
14 16 19
Exercice 3
40
28 24
22 16 19 21
14 17
99
Université Mohamed Khider-Biskra Exemple : Le polynôme 2x5 + 3x4 + 12 x2 + 1 est représentée par la liste
Faculté des Sciences Exactes et Sciences de la Nature et de la Vie suivante :
Département d’informatique
1
Corrigé type
Procédure Enfiler( x : entier ;);
Exercice 1 : Tas Var P,Pere : entier ;
Début
Si (N=NMax) Alors
1. Tas dynamique (1.5 pt) Ecrire(’le tas est plein’)
Sinon
N N+1 ;
38
Tas[N] x;
P N;
Pere N div 2 ;
33 16 Tant que ((P > 1) et Tas[Pere] < Tas[P])) faire
x Tas[Pere] ;
Tas[Pere] Tas[P] ;
17 22 3 2 Tas[P] x;
P Pere ;
Pere P div 2 ;
5 11 10 Fin TQ;
Fin Si;
Fin;
2. Tas statique (1.5 pt)
1 2 3 4 5 6 7 8 9 10
38 33 16 17 22 3 2 5 11 10
2
6. Tas statique (1 pt)
Fonction Defiler() : entier;
Var P,Pere : entier ; 1 2 3 4 5 6 7 8 9 10 11
Début 22 17 16 11 10 14 2 5 1 3 4
Si (N=0) Alors
Ecrire(’le tas est vide’)
Sinon Exercice 2 : LLCs
Defiler Tas[1] ;
Tas[1] Tas[N] ; 1. Structures de données (1 pt)
N N-1 ;
P 1;
Fils1 2; Type TTerme = Structure
Fils2 3; Coef : réel ;
Tant que (((Fils1 N) et Tas[P] < Tas[Fils1])) Degre : entier ;
ou ((Fils2 N) et Tas[P] < Tas[Fils2])) ) faire Suivant : Pointeur(TTerme) ;
Si (Fils2 > N) Alors Fin ;
PMax Fils1
Sinon
Si (Tas[Fils1] > Tas[Fils2]) Alors
PMax Fils1
Sinon
PMax Fils2
Fin Si;
Fin Si;
x Tas[P] ;
Tas[P] Tas[PMax] ;
Tas[PMax] x;
P PMax ;
Fils1 P * 2;
Fils2 P * 2 + 1;
Fin TQ;
Fin Si;
Fin;
3
2. Fonction Valeur (1.5 pt) 3. Procédure Dériver (2.5 pt)
Fin Si;
Fin TQ;
Fin;
4
4. Procédure Intégrer (2.5 pt)
Fonction Déviation( P : Pointeur(TTerme), x : réel) :
booléen;
Début
Si (P=Nil ou Degré(P)< 2) Alors
Déviation Faux
Procédure Intégrer( P : Pointeur(TTerme)); Sinon
Dériver(P) ;
Var P1,PP1 : Pointeur(TTerme) ;
Dériver(P) ;
Début
PP1 Nil ; Déviation (Valeur(P,x) = 0) ;
P1 P; Fin Si;
Tant que (P1 6= Nil) faire Fin;
A↵ Coef(P1, Coef(P1)/(Degré(P1)+1)) ;
A↵ Degré(P1,Degré(P1)+1) ;
PP1 P1 ;
P1 Suivant(P1) ;
Fin TQ;
Allouer(P1) ;
A↵ Coef(P1,1) ;
A↵ Degré(P1,0) ;
A↵ Adr(P1,Nil) ;
Si (PP1 = Nil) Alors
P P1 ;
Sinon
A↵ Adr(PP1,P1) ;
Fin Si;
Fin;
5
Université Mohamed Khider-Biskra Questions :
Faculté des Sciences Exactes et Sciences de la Nature et de la Vie
Département d’informatique 1. Donner les structures de données nécessaires à la représentation
de la liste des codes morse.
2ème année LMD ALGO1
2. Ecrire la procédure AjouterCode(Tete, car, cde) permettant
27 Jan 2013 10:00-11:30, Amphis 1,2,3,4
d’ajouter la lettre car avec son code cde à la liste des codes.
Examen 3. Ecrire la procédure RetirerCar(Tete, car) permettant de supprimer
le caractère car de la liste des codes.
4. Ecrire la fonction Coder(Tete, Ch) permettant de retourner le code
Exercice 1 LLCs (8.5 pts : 0.5 + 1.5 + 1.5 + 2 + 2 + 1) morse de la chaine de caractères Ch. Les codes morse de deux
caractères sont séparés par un espace, tandis que les codes morses
Le code morse a été inventé par Samuel Morse, peintre et physicien de deux mots sont séparés par deux espaces (blancs). Les codes
Américain. C’est un code permettant de transmettre un texte à l’aide des caractèrés non trouvés dans la liste sont replacés par des " ?".
de séries d’impulsions courtes et longues. Il a été longtemps utilisé pour
5. Ecrire la fonction Decoder(Tete, ChMorse) permettant de retour-
effectuer des liaisons longue distance.
ner la chaine de caractères codée dans la chaine morse ChMorse.
En informatique, et plus particulièrement dans les textes, une impulsion
Les caractères correspondant aux codes non trouvés dans la liste
longue est représentée par un tiret ’-’ et une impulsion courte par un
sont replacés par des " ?".
point ’.’. Chaque caractère de l’alphabet est présené par un code morse.
6. Calculer la complexité des fonctions Coder et Décoder.
Lettre Code Lettre Code Lettre Code Lettre Code Exercice 2 ARB (9.5 pts : 0.5 + 3 + 2 + 3 + 1)
A .- H .... O — V ...- On souhaite représenter la liste des codes morse présentée dans l’exer-
B -... I .. P .–. W .– cice précédent par un arbre de recherche binaire, où l’orientation vers
C -.-. J .— Q –.- X -..- un fils gauche signifie un ’.’ et l’orientation vers un fils droit signifie un
D -.. K -.- R .-. Y -.– ’-’.
E . L .-.. S ... Z –..
F ..-. M – T -
G –. N -. U ..-
Exemple :
1
Questions :
1. Donner les structures de données nécessaires à la représentation
de l’arbre des codes morses.
2. Ecrire la procédure AjouterCode(Racine, car, cde) permettant
d’ajouter la lettre car avec son code cde à l’arbre des codes.
3. Ecrire la fonction Coder(Racine, Ch) permettant de retourner le
code morse de la chaine de caractères Ch. Les codes morse de deux
caractères sont séparés par un espace, tandis que les codes morses
de deux mots sont séparés par deux espaces (blancs). Les codes
des caractèrés non trouvés dans la liste sont replacés par des " ?".
4. Ecrire la fonction Décoder(Racine, ChMorse) permettant de re-
tourner la chaine de caractères codées par la chaine morse
ChMorse. Les caractères correspondant aux codes non trouvés
dans la liste sont replacés par des " ?".
5. Calculer la complexité des fonctions Coder et Décoder. Que peut-
on conclure par rapport à l’exercice précédent ?
1. Donner le tas statique obtenu après l’insertion dans l’ordre des clés
suivantes :
12, 3, 5, 14, 15, 8, 1, 6
2. Donner le tas après deux retraits
2
Université Mohamed Khider-Biskra Initialement, l’arbre et la liste des fréquneces sont vides. Pour réaliser
Faculté des Sciences Exactes et Sciences de la Nature et de la Vie ce travail, on vous demande de :
Département d’informatique
1. Donner les structures de données nécessaires à la représentation
2ème année LMD ALGO1 en mémoire de la liste des fréquences et de l’arbre de Hau↵man
12 Mars 2013 16:30-18:00, Amphis 1,2 avec les initialisations nécessaires.
2. Ecrire la procédure AjouterCar(C :caractère) permettant
Examen de rattrapage d’ajouter le caractère C à la liste des fréquences, avec un pointeur
nil au nœud de l’arbre. (si C existe déjà, on incrémente unique-
On souhaite écrire les algorithmes permettant de créer l’arbre de Hu↵- ment sa fréquence)
man correspondant à une chaı̂ne de caractères donnée, tel que vu dans 3. Ecrire la procédure CreerListeFreq(Ch :chaı̂ne) permettant de
le cours. Pour celà, on vous propose de commencer par créer une liste créer la liste de tête TeteFreq, contenant les caractères de la chaı̂ne
linéaire chainée contenat les caractères de la chaı̂ne à coder avec leurs Ch avec leurs fréquences et des pointeurs nil vers l’arbre, en uti-
fréquences d’apparition et des pointeurs vers leurs noeuds correspon- lisant la procédure précédente.
dants dans l’arbre de Hu↵man, tel que représenté dans la figure sui-
4. Ecrire la procédure CreerFeuilles permettant de créer, pour
vante :
chaque caractère de la liste des fréquences, un nœud feuille de
l’arbre contenant ce caractère, tel que présenté dans la figure sui-
Chaîne!:!"structure!arbre"! vante :
Racine!
!
! TeteFreq!
!
!
! Arbre!de! s! 1! ! ! t! 2! ! ! r! 4! ! !
! ! ! !
Huffman!
! !
! r!
t! t!
! ! s! …! …! r! …! s!
!
! !
1
(a) Créer un nouveau nœud de l’arbre ayant deux fils, les nœuds
pointés par P1 et P2,
(b) Ajouter un nouveau maillon à la liste des fréquences avec Barème : 2 + 3 + 3 + 3 + 3 + 3 + 3
une fréquence égale à la somme des fréquences de P1 et P2,
et avac un pointeur vers le nouveau nœud crée de l’arbre.
Exemple :
FFF Bonne chance FFF
A.Djeffal
!
TeteFreq! !
s! 1! ! ! t! 2! ! !
! ! !
! P1! P2!
t!
s! a! 1! ! ! b! 1! ! !
! ! ! !
a! b!
AjouterNoeud*
TeteFreq!
?! 2! ! ! s! 1! ! ! t! 2! ! !
! ! !
s! t!
?!
a! b!
2
Corrigé type 2. Procédure AjouterCar (3 pts)
3
3. Procédure CreerListeFreq (3 pts) 5. Fonction GetMinFreq (3 pts)
4
6. Procédure AjouterNoeud (3 pts) 7. Procédure CreerArbreHu↵man (3 pts)
5
Références
[2] T.H. Cormen, C.E. Leiserson, R.L. Rivest, T.H. Cormen, and T.H. Cormen. Introduc-
tion à l’algorithmique. Dunod, 1996.
[5] Guillaume Poupard. Algorithmique. Ecole Nationale Supérieure des Techniques Avan-
cées, 2000.
137