Vous êtes sur la page 1sur 169

Algorithmique

http://alexandre-mesle.com
30 octobre 2008
Table des mati`eres
1 Complexite des algorithmes 6
1.1 Borne asymptotique superieure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2 Mesure de temps dexecution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2.1 Algorithmes en temps constant, O(1) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2.2 Algorithmes de complexite lineaire, O(n) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.3 Algorithmes de complexite logarithmique, O(logn) . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.4 Algorithmes de complexite quadratique O(n
2
) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.5 Algorithmes de complexite O(n.logn) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.6 Algorithmes de complexite exponentielle O(k
n
), k > 1 . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.7 Algorithmes de complexite polynomiale O(n
k
), k xe . . . . . . . . . . . . . . . . . . . . . . . 7
2 Algorithmes iteratifs 9
2.1 Invariants de boucle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.1.1 Le principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.1.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2 Terminaison . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.1 Le principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.2 Fin de lexemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2.3 Un autre exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3 Complexite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3 Recursivite 14
3.1 Sous-programmes recursifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.1.1 Factorielle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.2 Sous-programmes recursifs terminaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.2.1 Factorielle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2.2 Exponentiation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2.3 Iterateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.3 Listes chanees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.3.1 Notations et conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.3.2 Redaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.4 Exemple de calcul de complexite dun algorithme recursif . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.4.1 Lalgorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.4.2 Resolution exacte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.4.3 Verication par recurrence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.4.4 Probl`emes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.4.5 Lheure du code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4 Arbres 33
4.1 Denitions par induction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.1.1 Denition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.1.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.1.3 Expressions arithmetiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
1
4.1.4 Application aux arbres binaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.2 Preuves par induction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.2.1 Lien avec les preuves par recurrence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.2.2 Application aux EATPs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.3 Algorithmique dans les arbres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.4 Arbres n-naires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5 Files de priorite 36
5.1 Implementations naves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.2 Tas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.2.1 Denition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.2.2 Extraction du minumum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.2.3 Insertion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.2.4 Suppression du minimum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.2.5 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.3 Tas binomial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.3.1 Arbre binomial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.3.2 Fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.3.3 Tas binomial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.3.4 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.3.5 Extraction du minimum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.3.6 Fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
6 Hachage 40
6.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
6.2 Collisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
6.2.1 Gestion des collisions par chanage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
6.2.2 Gestion des collisions par adressage ouvert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
7 AVL 42
7.1 Arbres binaires de recherche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
7.2 Complexite dans le pire de cas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.3 Rotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.4 AVLs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
7.4.1 Reequilibrage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
7.4.2 Insertion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
7.4.3 Suppression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
7.4.4 Complements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
8 Modelisation 51
8.1 Denition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
8.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
8.2.1 Donnees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
8.2.2 Contraintes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
8.2.3 Question . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
8.3 Sensibilisation `a la complexite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
8.3.1 Le tour de la table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
8.3.2 De la terre `a la Lune . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
8.3.3 En bref . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
8.4 Terminologie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
8.4.1 Diculte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
8.4.2 Rappels de theorie des graphes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
8.4.3 Denition dun probl`eme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
8.4.4 Probl`emes doptimisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
8.5 Probl`emeth`eque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2
8.5.1 Arbre couvrant de poids minimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
8.5.2 Ensemble stable maximal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
8.5.3 Circuit eulerien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
8.5.4 Circuit hamiltonien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
8.5.5 Voyageur de commerce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
8.5.6 SAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
8.5.7 Couverture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
8.5.8 Coloration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
8.5.9 Plus court chemin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
8.5.10 Sac `a dos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
8.6 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
9 Programmation lineaire 61
9.1 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
9.2 Algorithme du simplexe en bref . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
9.3 Modeliser un programme lineaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
9.4 GLPK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
9.4.1 Quest-ce que cest ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
9.4.2 O` u le trouver ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
9.4.3 La documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
9.4.4 Les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
10 Theorie de la complexite 68
10.1 Terminologie et rappels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
10.1.1 Probl`emes de decision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
10.1.2 Instances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
10.1.3 Algorithme polynomial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
10.2 Les classes P et NP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
10.2.1 La classe P . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
10.2.2 La classe NP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
10.2.3 Relations dinclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
10.3 Reductions polynomiales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
10.3.1 Denition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
10.3.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
10.3.3 Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
10.4 Les probl`emes NP-complets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
10.4.1 Courte meditation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
10.4.2 3-SAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
10.4.3 Consequences deprimantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
10.4.4 Un espoir vain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
11 Introduction la cryptographie 74
11.1 Denitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
11.2 La steganographie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
11.3 Les chires symetriques sans cle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
11.4 Les chires symetriques `a cle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
11.4.1 Le chire de Vigen`ere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
11.4.2 Enigma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
11.5 Les algorithmes asymetriques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
11.5.1 Un peu dhistoire[1] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
11.5.2 Le principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
3
12 GnuPG 77
12.1 Presentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
12.2 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
12.2.1 Generation dune cle privee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
12.2.2 Exportation de la cle publique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
12.2.3 Importation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
12.2.4 Liste des cles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
12.2.5 Chirement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
12.2.6 Dechirement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
12.2.7 Signature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
12.2.8 Bref . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
13 GMP 80
13.1 Presentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
13.2 Quelques points delicats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
13.2.1 Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
13.2.2 Initialisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
13.2.3 Les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
13.2.4 Achage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
13.2.5 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
13.2.6 Pour terminer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
14 Arithmetique 84
14.1 Divisibilite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
14.2 Division euclidienne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
14.3 PGCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
14.4 Nombres premiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
14.5 Nombres premiers entre eux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
14.6 Decomposition en produit de facteurs premiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
14.6.1 Application `a la divisibilite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
14.6.2 Application au calcul du PGCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
14.7 Theor`eme de Bezout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
14.7.1 Theor`eme de Gauss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
14.8 Algorithme dEuclide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
14.8.1 Algorithme dEuclide pour le PGCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
14.8.2 Algorithme dEuclide etendu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
14.8.3 Morceaux choisis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
14.8.4 Applications avec GMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
15 Arithmetique modulaire 91
15.1 Congruences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
15.2 Rappels dalg`ebre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
15.2.1 Monodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
15.2.2 Groupes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
15.2.3 Anneaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
15.2.4 Corps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
15.2.5 Relations dequivalence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
15.3 Espaces quotients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
15.3.1 Classes dequivalence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
15.3.2 Z/nZ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
15.4 Inverses modulaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
15.4.1 Elements inversibles et fonction dEuler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
15.4.2 Pratique de linversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
4
16 RSA 97
16.0.3 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
16.0.4 Resistance aux attaques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
A Corriges des programmes 99
A.1 Fonctions recursives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
A.2 Fonctions recursives terminales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
A.3 Iterateurs et applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
A.4 Tours de Hano . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
A.5 Suite de Fibonacci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
A.6 Pgcd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
A.7 Pavage avec des L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
A.8 Complexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
A.9 Listes chanees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
A.10 Tri fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
A.11 Tri par insertion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
A.12 Transformee de Fourier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
A.13 Polynomes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
A.14 Tas binomiaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
A.15 AVL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
A.16 Knapsack par recherche exhaustive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
A.17 Prise en main de GLPK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
A.18 Le plus beau metier du monde . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
A.19 Prise en main de GMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
A.20 Algorithme dEuclide etendu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
A.21 Espaces Quotients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
B Rappels mathematiques 157
B.1 Sommations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
B.1.1 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
B.2 Ensembles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
B.2.1 Denition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
B.2.2 Operations ensemblistes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
B.2.3 Cardinal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
B.2.4 n-uplets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
B.2.5 Parties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
B.2.6 Denition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
B.2.7 Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
B.2.8 Classication des applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
B.2.9 Application reciproque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
B.3 Raisonnements par recurrence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
B.3.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
B.3.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
B.3.3 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
B.4 Analyse combinatoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
B.4.1 Factorielles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
B.4.2 Arrangements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
B.4.3 Combinaisons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
B.4.4 Triangle de Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
B.4.5 Liens avec les ensembles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
B.5 Exercices recapitulatifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
B.5.1 Echauement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
B.5.2 Formule de Poincare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
B.5.3 La moulinette `a meninges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Bibliographie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
5
Chapitre 1
Complexite des algorithmes
Un algorithme, programme dans un langage dierent, ou lance sur une machine dierente, ne mettra pas le temps
`a executer. Il serait pourtant important de trouver un moyen de mesurer son temps dexecution, pour le comparer par
exemple `a dautres algorithmes. Nous nous interesserons `a un crit`ere, appele complexite dans le pire des cas, qui
nous permettra devaluer les performances dun algorithme en terme de temps dexecution.
1.1 Borne asymptotique superieure
Une suite u est de borne asymptotique superieure v si pour n assez grand, u est majoree par v `a une constante
pr`es. Plus formellement,
Denition 1.1.1 u
n
O(v
n
) si N IN, k IR, n N, u
n
k.v
n
Pour n superieur `a N, u est majoree par k.v, donc par v `a la constante k pr`es. Si N et k existent, alors u
n
O(v
n
).
En pratique, on utilise la propriete suivante :
Propriete 1.1.1 u
n
O(v
n
) ssi lim
n+
u
n
v
n
= l
Plus simplement, u
n
O(v
n
) si
un
vn
converge vers une constante (notee l dans la propriete).
1.2 Mesure de temps dexecution
Un algorithme prend en entree une quantite de donnees que nous noterons en r`egle generale n, par exemple la taille
dun tableau, le nombre delement dune liste chanee, le nombre de noeuds dun graphe, etc. Nous considererons le
nombre doperations u
n
execute par lalgorithme et tenterons de classier u en utilisant une fonction v. Ce crit`ere est
interessant pour plusieurs raisons :
Quelle que soit le temps que mette une machine particuli`ere `a executer une operation, nous compterons le nombre
doperations.
Se limiter au denombrement des operations nest pas susant, ce qui nous interesse vraiment est la fa con dont
le nombre doperations eectuees par lalgorithme crot en fonction du nombre n de donnees.
Nous considererons en r`egle generale le temps dexecution dans le pire des cas. Quelques bornes asymptotiques
superieures sont `a considerer avec un attention particuli`ere :
1.2.1 Algorithmes en temps constant, O(1)
Un algorithme est en temps constant si son temps dexecution est independant du nombre de donnees. Par exemple,
retourner le premier element dune liste chanee. En eet, que la liste contienne un seul element ou 10
10
elements, le
temps dexecution de lalgorithme ne variera pas en fonction de n.
6
1.2.2 Algorithmes de complexite lineaire, O(n)
Un algorithme est de complexite lineaire si le temps de calcul crot de fa con lineaire en fonction du nombre de
donnees. Si vous traitez deux fois plus de donnees, le temps dexecution sera multiplie par deux. Par exemple, la
recherche sequentielle dans un tableau non trie est de complexite lineaire. En eet, on eectue une recherche en
parcourant le tableau avec une boucle (ou un algorithme recursif). Chacune des iterations se fait en temps constant,
il sut donc de compter le nombre diterations. Dans le pire des cas, lelement que lon recherche est celui qui est
examine en dernier. Il est donc necessaire deectuer n iterations.
1.2.3 Algorithmes de complexite logarithmique, O(logn)
Un algorithme de complexite algorithmique croit de fa con lineaire en fonction de 2
n
, cela signie que pour doubler
le temps dexecution, il faut mettre au carre le nombre de donnees. Par exemple, la recherche par dichotomie dans un
tableau trie. Si le tableau contient 2
30
elements, il faudra `a peu pr`es 30 iterations pour trouver lelement recherche,
contre 2
30
avec une recherche sequentielle. Pour la plupart, ces algorithmes sont dans la pratique tr`es performants.
1.2.4 Algorithmes de complexite quadratique O(n
2
)
Certains algorithmes de tri, par exemple, sont construits avec deux boucles imbriquees, et eectuent un nombre
diterations de lordre de n
2
. Bon nombre de probl`emes pour lesquels il existe des algorithmes quadratiques admettent
aussi des algorithmes de meilleure complexite.
1.2.5 Algorithmes de complexite O(n.logn)
Dautres algorithmes de tri sont de complexite O(n.logn), cest le meilleur resultat quil est possible dobtenir avec
des tris de comparaisons.
1.2.6 Algorithmes de complexite exponentielle O(k
n
), k > 1
Ces algorithmes sont tellement longs `a lexecution, quon ne les utilise presque jamais. Malheureusement, il existe
des probl`emes pour lesquels les seuls algorithmes de resolution exacte connus `a lheure actuelle sont de complexite
exponentielle.
1.2.7 Algorithmes de complexite polynomiale O(n
k
), k xe
Nous appelons ainsi tous les algorithmes dont le temps dexecution peut etre majore par un polynome. Nous
utiliserons le terme polynomial par opposition `a exponentiel. En algorithmique, il sera tr`es important de faire la
dierence entre les algorithmes polynomiaux, utilisables en pratique, et les algorithmes exponentiels, inutilisables en
pratique.
Exercice 1 - Tableaux
Determiner la complexite dans le pire cas (precisez quel est ce pire cas) des operations suivantes sur un tableau
t = [t
1
, . . . , t
n
] `a n elements non tries,
1. Achage du k-`eme element de t.
2. Achage des elements de t.
3. Calcul de la somme cumulee des elements de t.
4. Decalage vers la droite de la tranche [t
k
, . . . , t
n
] et insertion dun element au rang k.
5. Decalage vers la gauche de la tranche [t
k+1
, . . . , t
n
] pour supprimer t
k
.
6. Recherche sequentielle dun element.
7. Verication de lappartenance de chaque element de t `a un tableau q non trie.
7
Exercice 2 - Listes chanees
Determiner la complexite dans le pire des cas (precisez de quel cas il sagit) des operations ci-dessous sur une liste
chanee l = l
1
l
2
. . . l
n
`a n elements non tries. La seule information `a notre disposition au debut de
lexecution de chacun de ces algorithmes est un pointeur vers le premier element de la liste. :
1. Achage du k-`eme element de l.
2. Achage des elements de l.
3. Calcul de la somme cumulee des elements de l.
4. Suppression du premier element.
5. Suppression de lelement de rang k, adresse du (k 1)-`eme element connue.
6. Suppression de lelement de rang k, adresse du (k 1)-`eme element inconnue.
7. Recherche sequentielle dun element.
8. Verication de lappartenance de chaque element de l `a une liste q non triee.
Exercice 3 - Tri par selection
Le tri par selection dun tableau [t
1
, . . . , t
n
] se fait comme suit. On fait varier i de 1 `a n 1. Pour chaque iteration
de i, on recherche dans la tranche [t
i
, . . . , t
n
] le plus petit element et on lechange avec t
i
. Determiner la complexite
du tri par selection.
Exercice 4 - Hauteur minimale dun arbre binaire
Un arbre binaire est un arbre dont chaque noeud a 2 ls. Un arbre vide, donc sans noeud, note , est de profondeur
h() = 1. Un noeud est une feuille si ses deux ls sont des arbres vides. Soit x un noeud, l et r ses ls la hauteur de x
est alors h(x) = 1 +max(h(l), h(r)). La hauteur dun arbre binaire est la hauteur de son noeud de hauteur maximale,
donc de la racine. La racine r est de profondeur p(r) = 0, tout noeud x de p`ere y est de profondeur p(x) = p(y) + 1.
1. Quelle est la hauteur dune feuille dun arbre binaire ?
2. Comment disposer les noeuds pour que la hauteur dun arbre binaire `a n noeuds soit minimale ?
3. Nous ne considererons dorenavant que des arbres binaires dans lesquels les noeuds sont disposes comme decrit
dans la question precedente. Soit A un arbre de profondeur h, determiner pour tout k {0, . . . , h1} le nombre
de noeuds de A dont la profondeur est k.
4. Encadrer le nombre de noeuds de profondeur h.
5. Donner la borne inferieure du nombre n de noeuds dun arbre binaire de profondeur h.
6. Majorer h en fonction de n.
7. Donner une borne asymptotique superieure de la hauteur h dun arbre binaire `a n noeuds de hauteur minimale.
8
Chapitre 2
Algorithmes iteratifs
Un algorithme iteratif est contruit avec des boucles, par opposition `a recursif qui remplace les boucles par ds appels
`a lui-meme.
2.1 Invariants de boucle
2.1.1 Le principe
On prouve la validite dun algorithme iteratif `a laide de la methode des invariants de boucle.
Denition 2.1.1 Un invariant de boucle est une propriete qui est vraie ` a chaque passage dans la boucle.
On raisonne par recurrence pour montrer quune telle propriete est preservee `a chaque iteration de la boucle. Elle
sut `a prouver la validite de lalgorithme si elle est trivialement vraie `a la premi`ere iteration et qu`a la derni`ere
iteration, sa veracite entrane celle de lalgorithme. Voyons cela sur un exemple.
2.1.2 Exemple
On divise deux entiers strictement positifs a et b en determinant deux entiers q et r tels que a = bq + r avec
0 r < b. Voici un algorithme determinant q et r :
q 0
r a
tant que r b
q q + 1
r r b
n tant que
On choisit comme invariant de boucle la propriete a = bq +r.
Comme q est initialise `a 0 et r `a a, alors la propriete a = bq + r = b.0 + a est veriee avant le premier passage
dans la boucle.
Avant une iteration arbitraire, supposons que lon ait a = bq + r, montrons que cette propriete est conservee
par cette iteration. Soient q

la valeur de q `a la n de literation et r

la valeur de r `a la n de literation. Nous


devons montrer que a = bq

+r

. On a q

= q + 1 et r

= r b, alors bq

+ r

= b(q + 1) + (r b) = bq + r = a.
La propriete est bien conservee.
2.2 Terminaison
2.2.1 Le principe
La demonstration ci-dessus est incompl`ete, dune part on na pas demontre que le programme sarretait, et de plus
rien ne montre (pour le moment) que sil sarrete, on aura bien 0 r < b. On montre quun programme sarrete en
9
prouvant que la sequence formee par les valeurs des variables au l des iterations converge vers une valeur satisfaisant
la condition darret.
2.2.2 Fin de lexemple
Commen cons par montrer que le programme sarrete. La sequence formee par les valeurs de r au l des iterations
est strictement decroissante. Il y a donc necessairement un moment o` u la valeur de r sera strictement inferieure
`a celle de b.
Maintenant, nous pouvons terminer la preuve de validite :
Si le programme sarrete, cest que la condition du Tant que nest plus satisfaite, donc que r < b.
Il reste `a montrer que r 0. Comme r est diminue de b `a chaque iteration, si r < 0, alors `a literation
precedente la valeur de r etait r

= r + b, or r

= r + b < b car r < 0. Nous venons de montrer que si r


etait strictement negatif, alors la boucle se serait arretee `a literation precedente, ce qui est absurde. Donc
necessairement r 0.
Resumons, le programme sarrete avec 0 r < b et la propriete a = bq +r est veriee `a chaque iteration, ces deux
proprietes nous demontrent que lalgorithme eectue bien la division de a par b.
2.2.3 Un autre exemple
Determinons un algorithme qui calcule le produit de deux entiers a et b avec a positif ou nul sans eectuer de
multiplication.
p 0
m 0
tant que m < a
p p +b
m m+ 1
n tant que
Montrons que le programme se termine. La sequence formee par les valeurs prises par m au l des iterations est
strictement croissante, il y a donc un moment o` u m a. Donc lalgorithme se termine.
Considerons comme invariant de boucle p = m.b, montrons par recurrence quil est veriee.
m est p sont initialises `a 0, on a bien 0 = 0.b.
montrons maintenant que la propriete est conservee. Supposons quau debut dune iteration donnee, on ait
p = m.b. Soient p

et m

les valeurs de ces variables `a la n de cette iteration, montrons que lon a p

= m

.b.
On a les relations p

= p + b et m

= m + 1. Donc p

= p + b = m.b + b = (m + 1).b = m

.b. La propriete est


donc conservee par chaque iteration de lalgorithme.
La premi`ere de valeur de m qui nous fera sortir de la boucle est a, donc apr`es la derni`ere iteration on aura
p = mb = ab. Ce programme place donc dans p le produit de a par b.
Exercice 1 - Exponentiation
Ecrire un algorithme de calcul de b
n
o` u n est un entier positif ou nul. Prouver sa terminaison et sa validite.
Exercice 2 - Plus grand element
Ecrire un algorithme de recherche du plus grand element dans un tableau. Prouvez sa terminaison et sa validite.
On rappelle que m est le plus grand element du tableau T = [T
1
, . . . , T
n
] si les deux conditions suivantes sont veriees :
i {1, . . . , n}, m T
i
j {1, . . . , n}, m = T
j
Exercice 3 - Tri par insertion
Nous allons ecrire et demontrer la validite de lalgorithme du tri par insertion. Nous rappelons que T = [T
1
, . . . , T
n
]
est trie si i {1, . . . , n 1}, T
i
T
i+1
. Etant donne le programme suivant :
10
Procedure insere(T, k)
i k tant que i > 0 T[i 1] > T[i]
echanger(T[i 1], T[i])
i i 1
n tant que
FIN
Prouver que si on passe en param`etre `a insere un tableau T dont les k 1 premiers elements sont tries, alors `a la
n de son execution, les k premiers elements dont tries. Etant donne le programme suivant :
Procedure triInsertion(T[n])
pour i {2, . . . , n}
insere(T, i)
n pour
FIN
Demontrer la terminaison et la validite de triInsertion.
Voici le corrige de la premi`ere question : Lalgorithme se termine bien car les valeurs prises par i forment une
sequence de nombres entiers strictement decroissante. Si lon ne sort pas de la boucle avec T
i1
T
i
, on aura forcement
i = 1 apr`es la derni`ere iteration. Prenons comme invariant de boucle la conjonction des conditions suivantes :
La tranche T
1
, . . . , T
i1
est triee
La tranche T
i
, . . . , T
k
est triee
i < k T
i1
T
i+1
Prouvons cette propriete par recurrence :
A la premi`ere iteration, on a i = k. Comme T
1
, . . . , T
i
correspond `a la tranche T
1
, . . . , T
k1
donc par hypoth`ese
cette tranche est triee. La tranche T
i
, . . . , T
k
est reduite au seul element T
k
, elle est donc necessairement triee.
Comme (i < k), la troisi`eme condition est trivialement veriee.
Supposons quau debut dune iteration arbitraire, les trois proprietes soient veriees. Soient i

la valeur de i et
T

le tableau T `a la n de cette iteration. Montrons alors que


La tranche T

1
, . . . , T

1
est triee
La tranche T

i
, . . . , T

k
est triee
i

< k T

1
T

+1
Dune part, on a i > 1 et T
i1
> T
i
. Par ailleurs, i

= i 1, T

i1
= T
i
et T

i
= T
i1
. Tous les autres elements de
T et de T

concident. Montrons les trois proprietes :


Par hypoth`ese de recurrence, la tranche T
1
, . . . , T
i1
est triee, donc la tranche T
1
, . . . , T
i1
que lon obtient en
ne comptabilisant pas le dernier element est aussi triee. Comme les elements de T et T

dindices dierents de
i et i + 1 sont les memes et que i 1 = i

, alors T

1
, . . . , T

i
est triee.
Par hypoth`ese de reccurrence T
i
, . . . , T
k
est triee, en ne considerant pas le premier element, on a T
i+1
, . . . , T
k
,
comme les elements de cette tranche concident avec T

, alors T

+2
, . . . , T

k
est triee. Par ailleurs, on a T

i
= T
i
et T

+1
= T
i1
, comme T
i1
> T
i
, alors T

i
< T

+1
. Si i < k, alors par hypoth`ese de recurrence, on a
T
i1
T
i+1
, donc T

+1
T

+2
. Dans ce cas, on a T

i
< T

+1
T

+2
avec T

+2
, . . . , T

k
triee. Donc
T

i
, . . . , T

k
est triee. Si i = k, alors la tranche T

i
, . . . , T

k
est reduite aux deux elements T

i
< T

+1
, elle est
donc triee.
Quelle que soit la valeur de i, on a necessairement i

< k, il faut donc montrer que T

1
T

+1
. Or
T

1
= T
i2
et T

+1
= T
i1
. Par hypoth`ese de recurrence, T
1
, . . . , T
i1
est triee, donc on a T
i2
T
i1
, do` u
T

1
T

+1
.
Apr`es la deni`ere iteration, si i = 1, alors la premi`ere tranche ne contient aucun element et la deuxi`eme condition
de linvariant de boucle permet de conclure que toute la tranche T
1
, . . . , T
k
est triee. Si par contre, on sort de la boucle
parce que T
i1
T
i
, alors comme, dapr`es linvariant de boucle, T
1
, . . . , T
i1
et T
i
, . . . , T
k
sont triees, alors T
1
, . . . , T
k
est triee.
Exercice 4 - Tri `a bulle
Ecrire et demontrer la validite de lalgorithme du tri `a bulle.
11
2.3 Complexite
On determine la complexite dun programme iteratif en comptant le nombre diterations. Lorsque deux boucles
sont imbriquees, on est amene `a compter pour chaque iteration de la boucle principale le nombre diterations de la
boucle imbriquee et `a les additionner. Par exemple,
pour i {1, . . . , n 1}
pour j {i + 1, . . . , n}
(* operation en O(1) *)
n pour
n pour
A literation i de lalgorithme, la boucle imbriquee eectue n (i + 1) + 1 = n i iterations. On determine donc
le nombre total diterations en sommant les n i, donc avec
(n 1) + (n 2) +. . . + (n (n 1)) =
n1

i=1
(n i) =
((n 1) 1 + 1)(n 1 +n (n 1))
2
=
(n 1)n
2
O(n
2
)
Exercice 5 - Sommations
Simplier les sommes suivantes :

n+2

i=1
i

i=0
i + 1
e

n
i=1
ln(i)

i=1
(3i 2)

i=1
n1

j=i
1

i=1
(3(
n1

j=i
1) 2)

n+3

i=5
(i 1)

i=1
(2n 3i)
Exercice 6 - Tris quadratiques
Calculer les complexites du tri par insertion et du tri `a bulle.
Morceaux choisis
Exercice 7 - Polynomes
Nous representerons un polynome P(x) = p
0
x
n
+p
1
x
n1
+. . . +p
n1
x +p
n
=
n

i=0
p
i
x
ni
de degre n `a laide dun
tableau [p
0
, p
1
, . . . , p
n1
, p
n
] `a n + 1 elements. Notez bien que ce tableau est indice `a partir de 0.
12
1. Que fait la fonction suivante ?
Fonction mystery([p
0
, . . . , p
n
], x)
somme 0
pour i {0, . . . , n}
terme 1
j 1
tant que j n i
terme terme x
j j + 1
n tant que
terme terme p
i
somme somme +terme
n pour
retourner somme
FIN
2. Quelle est la complexite de mystery ?
3.

Ecrire la procedure derive([p
0
, . . . , p
n
]) rempla cant p par sa derivee.
4. Prouver que
k+1

i=0
p
i
x
k+1i
= x
_
k

i=0
p
i
x
ki
_
+p
k+1
5. Deduire de la relation ci-dessus une fonction evalue([p
0
, . . . , p
n
], x) prenant P et x en param`etres, et retournant
P(x).
6. Prouver la validite de la fonction devaluation, vous utiliserez les questions precedentes.
7. Quelle est la complexite de evalue ?
Exercice 8 - Tranche minimale
Etant donne un tableau T[n], un tranche est une suite delements contig us de T. Une tranche [T
i
, . . . , T
j
] est
enti`erement determinee par lindice i de debut et lindice j de n. La valeur de la tranche [T
i
, . . . , T
j
] est donnee par
la somme
V
j
i
=
j

k=i
T
k
Nous souhaitons mettre au point un algorithme de recherhe de la tranche minimale.
1. Ecrivez un algorithme construit avec trois boucles imbriquees. Calculez sa complexite.
2. Utilisez le fait que V
j+1
i
= V
j
i
+ T[j + 1] pour ecrire un algorithme construit avec deux boucles imbriquees.
Calculez sa complexite.
3. Soient M
j
i
la valeur de la tranche minimale incluse dans la tranche [T
i
, . . . , T
j
], et soit

M
j
i
la tranche minimale
de [T
i
, . . . , T
j
] contenant T
j
. Donnez une relation entre M
j+1
i
, M
j
i
et

M
j
i
.
4. En deduire un algorithme de recherche de la tranche minimale construit avec une seule boucle. Determiner sa
complexite.
13
Chapitre 3
Recursivite
3.1 Sous-programmes recursifs
Un sous-programme recursif est un sous-programme qui sappelle lui-meme. Par exemple :
Procedure countDown(n)
si n 0 alors
afficher(n)
countDown(n 1)
n
FIN
Ce sous-programme ache n si celui-ci est positif ou nul, puis se rappelle en passant n 1 en param`etre. Il va se
rappeler jusqu` a ce que le param`etre prenne la valeur 1, achant ainsi un compte `a rebours dont la derni`ere valeur
achee sera 0. Lorsque quun sous-programme se rappelle, on dit quil eectue un appel recursif. Pour observer ce
que cela fait, considerez le programme suivant :
#include<s t di o . h>
void countDown ( i nt n)
{
i f ( n >= 0)
{
pr i nt f ( %d\n , n ) ;
countDown ( n1);
}
}
i nt main ( )
{
countDown ( 1 0 ) ;
return 0 ;
}
Il ache
10
9
8
7
6
5
4
14
3
2
1
0
Observons bien la procedure countdown :
La premi`ere chose faite est le test n 0, il faut toujours tester la condition darret avant de faire quoi que ce
soit. Si cela nest pas fait correctement, le sous-programme peut boucler indeniment.
Dans lappel recursif, la valeur n 1, et non pas n, est passee en param`etre. Si vous ne faites pas decrotre la
valeur de n, le sous-programme se comportera de fa con identique `a chaque appel recursif, donc bouclera.
Lappel recursif est fait apr`es lachage de n, si vous permutez lachage et lappel recursif, les nombres seront
aches dans lordre croissant. un sous-programme est recursif terminal si la derni`ere instruction executee est
un appel recursif, ce qui est le cas ici.
Beaucoup de sous-programmes sont beaucoup plus faciles `a implementer de fa con recursive. Un sous-programme
utilisant des boucles mais pas la recursivite est dit iteratif. Comme la recursivite permet deviter de faire des boucles,
on oppose souvent la mode recursif au mode iteratif. On exposera divers algorithmes simplementant naturellement
de fa con recursive, notamment le tri fusion, et les algorithmes dans les listes et les arbres. Pour le moment nous nous
limiterons au calcul de valeurs denies par recurrence.
3.1.1 Factorielle
Soit n un nombre entier positif ou nul, le nombre n!, dit factorielle n, est deni comme suit :
n! = 1 2 . . . n =
n

i=1
i
avec le cas particulier 0! = 1. On observe que
n! = [1 . . . (n 1)] n = [(n 1)!] n
Cette relation nous permet de reduire le calcul de la factorielle dun nombre n au calcul de la factorielle de n 1.
En utilisant cette relation on obtient un algorithme recursif calculant la factorielle dun nombre n.
Fonction factorielle(n)
si n = 0 alors
retourner 1
sinon
retourner n factorielle(n 1)
n
FIN
Observez bien que la condition darret est testee d`es le debut de lexecution de lalgorithme, et quelle permet
de calculer la valeur 0!
Dans le cas general, le calcul n! se fait en passant par le calcul de (n1)!. Comme la valeur passee en param`etre
dans lappel recursif est n1 et est strictement inferieure `a n, alors la sequence des valeurs passees en param`etre
au l des appels recursifs
n n 1 . . . 1 0
est strictement decroissante et converge vers 0. Il est tr`es important de verier que quelques soient les valeurs
passees en param`etre, la sequence de valeurs formee par les appels recursifs converge vers une valeur satisfaisant
la condition darret, 0 dans le cas present.
On remarque par ailleurs que cet algorithme nest pas recursif terminal, en eet lappel recursif prec`ede une
multiplication par n, la derni`ere instruction nest donc pas un appel recursif.
Les doutes des plus sceptiques seront, je lesp`ere apaises par la vue du sous-programme suivant :
long f a c t o r i e l l e ( long n)
{
i f ( n == 0)
15
return 1 ;
return n f a c t o r i e l l e ( n 1 ) ;
}
Exercice 1 - Operations arithmetiques enti`eres
Considerez lalgorithme suivant :
Fonction addition(a, b)
si a = 0 alors
retourner b
sinon
retourner 1 +addition(a 1, b)
n
FIN
1. Quelle relation arithmetique utilise-t-il ?
2. Modiez-le pour quil puisse additionner des nombres negatifs.
3. Ecrivez un algorithme recursif soustrayant deux nombres de signes quelconques.
4. Ecrivez un algorithme recursif multipliant deux nombres de signes quelconques.
5. Ecrivez un algorithme recursif divisant deux nombres de signes quelconques.
6. Ecrivez un algorithme recursif calculant a
b
, avec des valeurs de b enti`eres positives ou nulles.
Exercice 2 - La fonction mystery
Considerons la fonction suivante :
Fonction mystery(n)
si n = 0 alors
retourner 2
sinon
retourner [mystery(n 1)]
2
n
FIN
1. Que fait cette fonction ?
2. Prouvez par recurrence votre conjecture de la question precedente.
3.

Ecrire une fonction recursive mysteryBis(a, b, n) sur le meme mod`ele que mystery retournant a
(b
n
)
. Vous utili-
serez la fonction puissance(x, m) qui retourne x
m
.
4. Prouvez la validite de mysteryBis.
3.2 Sous-programmes recursifs terminaux
Bon nombre de sous-programmes non terminaux peuvent etre reecrits de fa con terminale. Cela se fait par lajout
dun param`etre, appele accumulateur. La forme dun programme recursif terminal est la suivante :
Fonction f(. . . , r)
si conditionDArret alors
retourner r
sinon
instructions
n
FIN
Il faut faire en sorte quune fois la condition darret veriee le param`etre r contienne le resultat.
16
3.2.1 Factorielle

Etudions un exemple,
Fonction factorielleT(n, r)
si n = 0 alors
retourner r
sinon
retourner factorielleT(n 1, r n)
n
FIN
Tout dabord, on remarque que factorielleT est bien une fonction recursive terminale. Ensuite observons que si
lon invoque factorielleT(n, 1), on obtient la sequence suivante :
(n, 1) (n 1, n) (n 2, n (n 1)) . . .
. . . (i,
n

k=i+1
k) . . .
. . . (2,
n

k=3
k) (1,
n

k=2
k) (0,
n

k=1
k)
Au moment o` u la condition darret est veriee, le param`etre r contient la valeur

n
k=1
k, `a savoir n!. On se sert de
laccumulateur pour fabriquer le resultat. Demontrons par recurrence sur n que factorielleT(n, r) = r(n!) :
Tout dabord, on constate que factorielleT(0, r) = r
Supposons que factorielleT(n 1, r

) retourne la valeur (n 1)! r

, donc factorielleT(n 1, n r) = (n
1)!(r n) = r(n!). Do` u factorielleT(n, r) = factorielleT(n 1, n r) = r(n!)
On en deduit quen posant r = 1, on a factorielleT(n, 1) = n! On encapsule factorielleT dans le sous-programme
factorielle que lon redenit de la sorte :
Fonction factorielle(n)
retourner factorielleT(n, 1)
FIN
3.2.2 Exponentiation
Essayons de creer une fonction recursive terminale calculant b
n
, comme cette valeur sobtient par des multiplications
successives, laccumulateur a est une valeur par lequel le resultat sera multiplie. Nous souhaitons donc mettre un point
une fonction puissanceT(a, b, n) qui retourne a(b
n
). On obtiendra b
n
en initialisant a `a 1. On determine une relation
de recurrence entre b
n
et b
n1
de la sorte : b
n
= b.b
n1
, donc ab
n
= (ab)b
n1
, `a savoir puissanceT(a b, b, n 1).
Allons-y,
Fonction puissanceT(a, b, n)
si n = 0 alors
retourner a
sinon
retourner puissanceT(a b, b, n 1)
n
FIN
Prouvons par recurrence sur n que puissanceT(a, b, n) = ab
n
.
On a bien puissanceT(a, b, 0) = a = ab
0
Supposons que puissanceT(a

, b, n 1) = a

b
n1
, donc puissanceT(ab, b, n 1) = (ab)b
n1
= ab
n
. Do` u
puissanceT(a, b, n) = puissanceT(ab, b, n 1) = ab
n
.
17
On calcule donc b
n
en invoquant puissanceT(1, b, n). On redenit puissance(b, n) de la sorte :
Fonction puissance(b, n)
retourner puissanceT(1, b, n)
FIN
Vous avez des doutes ? Traduisez donc ces sous-programmes en C en observez ce qui se passe...
Exercice 3 - Recursion terminale
Reprennez tous les sous-programmes de lexercice precedent et redigez-les sous forme recursive terminale. Vous
prouverez par recurrence la validite de chacune delle.
3.2.3 Iterateurs
Exercice 4 - Introduction aux iterateurs
Etant donne une fonction f, on note f
n
la composition de f par elle-meme n fois. Par exemple : f
3
= f f f, si
f : x x + 1, alors f
3
(x) = f(f(f(x))) = x + 3. Par convention, on a f
0
= id, avec id : x x.
1. Si f : x x + 1, demontrez par recurrence que f
n
: x x +n
2. Si f : x 2x, demontrez par recurrence que f
n
: x 2
n
x
3. Si f : x x
2
, demontrez par recurrence que f
n
: x x
(
2
n
)
4. Ecrire une fonction recursive applyF non terminale prenant en param`etre une fonction f, un nombre n et un
argument x, et retournant f
n
(x). Ce type de fonction sera appele un iterateur.
5. Ecrire une version recursive terminale de applyF.
6. Soit f : (a, b) (a +b, b), montrez par recurrence que f
n
: (0, b) (bn, b)
7. Ecrire une fonction f prenant en param`etre le couple (a, b) et retournant (a +b, b).
8. Ecrire la fonction multiplie en utilisant f et applyF.
Exercice 5 - Applications des iterateurs
1. Reechir `a un moyen dimplementer les iterateurs en C, noubliez pas que la fonction iteree peut prendre et
retourner plusieurs param`etres.
2. Pour des raisons de lisibilite du code, nous utiliserons des structures pour representer les couples. Cela a pour
inconvenient un manque de genericite de la fonction f. Utiliser des tableaux orirait une souplesse optimale mais
alourdirait considerablement le code du fait des allocations et liberations de la memoire necessaires. Implementez
en C la fonction multiplie de lexercice precedent, vous utiliserez bien evidemment un iterateur.
3. Ecrivez la fonction factorielle `a laide dun iterateur, demontrez sa validite et traduisez-l`a en C.
4. Ecrivez la fonction puissance `a laide dun iterateur, demontrez sa validite et traduisez-l`a en C.
Exercice 6 - Iterateurs et aspirine
Dans les questions precedentes, literateur faisait decrotre n de 1 `a chaque appel recursif. Soit f la fonction `a iterer
et x la valeur en 0, nous pouvons denir un tel iterateur I de la sorte :
I(f, n, x) = f(I(f, n 1, x))
I(f, 0, x) = x
Nous etendons une telle fonction en ajoutant en param`etre une fonction de decrement , on obtient :
I(, f, n, x) = f(n, I(, f, (n), x))
I(, f, 0, x) = x.
1. Implementez la fonction I(, f, n, x) en en utilisant le prototype suivant unsigned long applyFD(int (*delta)(int
k), unsigned long (*f)(couple), int n, unsigned long x).
2. Ecrivez une fonction f telle que I(, f, n, b) = b
n
, vous utiliserez la relation de recurrence b
n
= b.b
n1
et b
0
= 1
et poserez : x x 1.
18
3. Prouvez que I(, f, n, b) = b
n
4. Ecrivez en C la fonction unsigned long slowPuissanceIT(unsigned long b, unsigned long n), vous utili-
serez applyFD et traduirez en C les fonctions f et denies dans la question preccedente.
5. Ecrivez deux fonctions f et telles que I(, f, n, 1) = n!
6. Prouvez que I(, f, n, 1) = n!
7. Ecrivez en C la fonction unsigned long fatorielleIT(unsigned long b, unsigned long n), vous utiliserez
applyFD.
8. Ecrivez une fonction recursive fastPuissance(b, n) calculant b
n
sans utiliser diterateur, vous utiliserez le fait
que b
n
= (b
2
)
n
2
si n est pair et b
n
= b(b
2
)

n
2

sinon.
9. Traduisez-l`a en C en utilisant le prototype suivant unsigned long fastPuissance(unsigned long b, unsigned
long n).
10. Majorez le nombre dappels recursifs en fonction de n, est-ce performant ?
11. Ecrivez la fonction f et la fonction de sorte que I(, f, n, b) = b
n
. Notez le fait que f prend le couple (n, b) en
param`etre.
12. Prouvez par recurrence la validite de I(, f, n, b) = b
n
.
13. Ecrivez en C la fonction unsigned long fastPuissanceIT(unsigned long b, unsigned long n), vous utili-
serez la fonction applyFD.
Exercice 7 - Iterateurs et nombres de Fibonacci
1. Soit
_
F
n
F
n1
_
, un vecteur de deux nombres de bonacci consecutifs. Que donne le produit
_
1 1
1 0
_ _
F
n
F
n1
_
?
2. Prouvez par recurrence que
_
1 1
1 0
_
n
_
F
1
F
0
_
=
_
F
n+1
F
n
_
.
3. On calcule donc le n-`eme nombre de Fibonacci en mettant prealablement la matrice
_
1 1
1 0
_
`a la puissance
n. Nous allons utiliser pour ce faire la meme r`egle que pour fastPuissance. Ecrivez une fonction multMat
prenant en param`etre deux quadruplets (x
11
, x
12
, x
21
, x
22
) et (y
11
, y
12
, y
21
, y
22
) representant deux matrices X =
_
x
11
x
12
x
21
x
22
_
et Y =
_
y
11
y
12
y
21
y
22
_
. multMat retourne un quadruplet representant le produit matriciel XY .
4. Denir une fonction matPow(X, n) mettant un matrice X, `a la puissance n. Vous utiliserez I(, multMat, n, X).
5. Ecrire une fonction multMatV ec retournant le produit dune matrice, representee par un quadruplet, et dun
vecteur, represente par un couple.
6. Ecrire en C la fonction quadruplet applyFDQ(int (*delta)(int k), unsigned long (*f)(int, quadruplet),
int n, quadruplet x), vous utiliserez le meme mod`ele mathematique, mais en transmettant comme deuxi`eme
param`etre `a f un quadruplet.
7. Ecrire la fonction fastFibonacci(n), retournant le n-i`eme nombre de bonacci.
8. Quelle est la complexite de fastFibonacci ?
9. Implementer les fonctions :
(a) quadruplet multMat(quadruplet x, quadruplet y)
(b) quadruplet applyFDQ(unsigned long (*delta)(unsigned long), quadruplet (*f)(unsigned long,
quadruplet), unsigned long n, quadruplet x
(c) quadruplet matPow(quadruplet x, unsigned long n)
(d) couple multMatVec(quadruplet x, couple y)
(e) unsigned long fastFibonacciIT(unsigned long l).
19
3.3 Listes chanees
3.3.1 Notations et conventions
La recursivite est particuli`erement adaptee lorsque lon souhaite manipuler des listes chanees. Nous utiliserons
pour ce faire les fonctions suivantes :
1. premier(l) retourne la donnee se trouvant dans le premier element de la liste chanee l.
2. suivants(l) retourne un pointeur l

vers le deuxi`eme element de l, cette fonction ne produit aucun eet de bord


et ne modie pas le chanage.
3. ajoute(z, l) ajoute la donnee z au debut de la liste l et retourne un pointeur vers la liste obtenue, elle modie
le chanage.
4. estV ide(l) retourne vrai si et seulement si la liste l ne contient aucun element.
5. listeV ide() retourne une constante que nous identierons `a la liste vide, cest-`a-dire ne contenant aucun element.
Vous prendrez soin de ne pas confondre les listes et les donnees. Ces derni`eres sont generiques, vous pouvez placer
dans une liste des donnees de nimporte quel type, meme dautres listes... Nous noterons mathematiquement les listes
entre des crochets, par exemple [1, 4, 3, 7]. La liste vide, retournee par la fonction listeV ide() sera notee []. Vous pourrez
creer une liste `a un element par exemple en ecrivant
ajoute(4, listeV ide())
Cette instruction cree la liste [4]. Pour creer une liste ` a deux elements, vous utiliserez le meme principe :
ajoute(3, ajoute(4, listeV ide()))
Cette instruction cree la liste [3, 4]. Les elements de la liste sont indices `a partir de 1. Nous ne gererons pas la
memoire, on considerera quun garbage collector sen occupera.
3.3.2 Redaction
Les r`egles de la recursivite sont les memes quand on manipule des listes chanees, on teste le cas de base en premier :
la liste vide, et on fait en sorte que la sequence formee par les valeurs passees en param`etre au le des appels recursifs
converge vers la liste vide. Par exemple,
Procedure sommeListe(l)
si estV ide(l) alors
retourner 0
sinon
retourner premier(l) +sommeListe(suivants(l))
n
FIN
Cette fonction retourne la somme des elements de l.
Exercice 8 - Prise en main
Ecrire les fonctions suivantes en pseudo-code :
listPrint(l), ache les elements de la liste l.
listDeleteByIndex(l, k) retourne une liste contenant les elements de la liste l sauf celui dindice k.
listDeleteByV alue(l, a), retourne une liste contenant les elements de l sauf le premier rencontre `a avoir la valeur
a.
listDeleteAllByV alue(l, a), retourne une liste contenant les elements de l sauf tous les elements ayant la valeur
a.
listOcurrences(l, a), retourne une liste contenant les indices de toutes les ocurrences de a dans l.
listIndexesUnsorted(l, i) retourne une liste contenant tous les elements de la liste l dont lindice se trouve dans
la liste i. i nest pas supposee triee.
20

listIndexesSorted(l, i) retourne une liste contenant tous les elements de la liste l dont lindice se trouve dans la
liste i. i est supposee triee.
listDeleteByIndexes(l, i) retourne une liste contenant tous les elements de l dont lindice se trouve dans i, i est
supposee triee.
Exercice 9 - Tris
Ecrire les fonctions suivantes en pseudo-code :
listInsert(l, a), ins`ere la donnee k dans la liste l, retourne un pointeur vers le premier element de la liste.
listInsertionSort(l), retourne les elements de l tries par la methode du tri par insertion.
listSplit(l), retourne un couple de listes (m, n) dans lesquelles ont ete repartis de fa cons arbitraire les elements
de l et telle que le nombre de donnees de m et n di`ere au plus de 1.
listMerge(l1, l2), retourne une liste l triee contenant les elements de l1 et de l2. l1 et l2 sont supposees triees.
listFusionSort(l) retourne une liste contenant les elements de l tries avec la methode du tri fusion.
3.4 Exemple de calcul de complexite dun algorithme recursif
3.4.1 Lalgorithme
La complexite dun algorithme recursif sexprime en r`egle generale par lintermediaire dune relation de recurrence.
Par exemple, lachage des elements dune liste chanee, donne par lalgorithme suivant :
Procedure afficheListe(l)
si estV ide(l) alors
afficher(premier(l))
afficheListe(suivants(l))
n
FIN
Soit u
n
le nombre dinstructions elementaires executees par afficheListe si la liste l comporte n maillons. Si n = 0,
lalgorithme sexecute en temps constant. Sinon, lappel recursif necessite u
n1
operations, les autres operations (au
nombre de k) sexecutent en temps constant. On denit donc u comme suit : u
n
= u
n1
+ k, comment exprimer u
n
en fonction de u
0
, de n et de k ?
3.4.2 Resolution exacte
Il apparat que u est une suite arithmetique de raison k et de premier terme u
0
, donc u
n
= u
0
+ kn. Comme
u
0
+kn
n
k, alors u
n
O(n), donc afficheListe est de complexite lineaire. On remarque que, dans ce type
de suite, u
o
et k sont des valeurs nayant pas de consequence sur le caract`ere lineaire de la complexite de ce type
dalgorithme. On se permettra donc, dans la plupart des cas, de les remplacer par 1. Nous aurons donc les fois
suivantes u
0
= 1 et u
n
= u
n1
+ 1, le resultat, en terme de complexite sera le meme.
3.4.3 Verication par recurrence
Il est frequent que lon ne parvienne pas `a exprimer u
n
en fonction de u
0
et de n, certaines recurrences sont tr`es
dicile `a resoudre. Une autre fa con de classier une suite u
n
dans un O est de conjecturer ce O, puis de le demontrer
par recurrence. Par exemple, demontrons par recurrence que u
n
O(n). Si cest le cas, supposons que u
n
est majoree
par une suite lineaire, cest `a dire de la forme an +b. Choisissons b tel que b u
0
= 1 et a > 1.
Lhypoth`ese sur b implique que a(0) +b u
0
.
Supposons que si an + b u
n
, alors montrons que a(n + 1) + b u
n+1
. On a u
n+1
= u
n
+ 1 an + b + 1
an +b +a = a(n + 1) +b.
21
On montre aisement que a et b choisis conformement aux conditions precedant la demonstration par recurrence
determine une suite an+b qui majore u
n
. On remarque que an+b crot de fa con lineaire, en eet
an +b
n
a, donc
on a an +b O(n). Comme u
n
est majoree par une suite lineaire, u
n
O(n).
Prouvons pour le sport que si u
n
v
n
et v
n
O(w
n
), alors u
n
O(w
n
). Comme v
n
O(w
n
), alors k, N, n >
N, v
n
k.w
n
, comme u
n
v
n
, alors pour les memes valeurs k et N, u
n
v
n
k.w
n
et de ce fait u
n
k.w
n
.
Deux ensembles de methodes ressortent dans les exemples :
La resolution exacte, elle necessite le connaissance de bon nombre de methodes mathematiques, bien quelegante,
elle devient vite tr`es compliquee.
La conjecture dune majoration suivie dune preuve par recurrence de cette majoration. La preuve est en r`egle
generale plus simple `a mettre en oeuvre, la partie la plus dicile est de conjecturer une majoration valide et la
moins grossi`ere possible.
3.4.4 Probl`emes
Exercice 10 - Tours de Hano
On dispose de n disques numerotes de 1 `a n. Les disques peuvent etre empiles sur des socles `a partir du moment
o` u tout disque repose sur un disque de numero plus eleve. On dispose de trois socles S
1
, S
2
et S
3
, les n disques sont
empiles sur le socle de gauche S
1
, ceux du milieu et de droite S
2
et S
3
sont vides. Le but est de deplacer toute la
pile de disques sur le socle de droite, sachant quon ne peut deplacer les disques que un par un, et quil ne faut qu`a
aucun moment, un disque numerote k se trouve sur un disque numerote m avec m < k (i.e un disque plus petit). Par
exemple, si n = 3, on a
1
2
3
------------
2
3 1
------------
3 2 1
------------
1
3 2
------------
1
2 3
------------
1 2 3
------------
2
1 3
------------
1
2
3
------------
On dispose dun sous-programme deplaceDisque(S
i
, S
j
) qui enl`eve le disque se trouvant au sommet de la pile S
i
et la place au sommet de la pile S
j
.
1. Trouver un algorithme recursif deplaceDisques(n, S
from
, S
via
, S
to
) permettant de deplacer n disques du socle
S
from
au socle S
to
en utilisant S
via
comme socle intermediaire.
2. Codez en C un programme qui ache chaque etape du deplacement des n disques, que remarquez-vous lorsque
lon prend des grandes valeurs de n?
22
3. Determiner une relation de recurrence permettant de denombrer le nombre detapes necessaires pour deplacer n
disques. Resolvez-l`a.
4. Est-il envisageable de deplacer 100 disques en un temps raisonnable ?
Exercice 11 - Suite de Fibonacci
1. Ecrire une fonction recursive unsigned long fibo(unsigned long l) calculant le n-`eme nombre de bonacci
F
n
deni par recurrence de la sorte : F
n
= F
n1
+F
n2
avec F
0
= 0 et F
1
= 1.
2. Soit u
n
le nombre dappels recursifs necessaires pour calculer F
n
. Prouvez par recurrence que u
n
F
n
.
3. Exprimer F
n
en fonction de n en resolvant la recurrence lineaire.
4. Determiner la complexite de fibo en passant par une borne asymptotique inferieure.
5. On consid`ere la fonction : (a, b) (a +b, a). Prouvez que (F
n1
, F
n2
) = (F
n
, F
n1
).
6. On note
k
la composition de k fonctions . Par exemple,
2
= et
2
(a, b) = ((a, b)) = (a+b, a) = (2a+
b, a+b). Par convention,
0
est la fonction identite, notee id. Prouver par recurrence que (F
n+1
, F
n
) =
n
(F
1
, F
0
)).
7. Implementez avec le sous-programme void phi(unsigned long* l1, unsigned long* l2), notez que les
deux variables l1 et l2 sont passees en param`etre par reference.
8. Ecrivez le corps du sous-programme void applyF(void (*f)(unsigned long*, unsigned long*), int n,
unsigned long* l1, unsigned long* l2), applyF applique n fois la fonction f, en utilisant comme param`etre
lors du premier appel les variables pointees par l1 et l2.
9. Utilisez applyF et phi pour coder unsigned long fastFibo(unsigned long l)
10. Majorer la complexite de applyF lorsquon lui passe le sous-programme phi en param`etre, prouver ce resultat
par recurrence.
11. Quelle est la complexite de fastFibo? Porte-t-elle bien son nom?
Exercice 12 - Pgcd
Le plus grand commun diviseur de deux entiers relatifs a et b, note pgcd(a, b), est deni par la relation de recurrence
pgcd(a, b) = pgcd(b, a mod b), avec pgcd(a, 0) = a.
1. Ecrire une fonction recursive calculant le pgcd de deux entiers relatifs.
2. Ecrire une fonction iterative retournant le i-`eme nombre de bonacci.
3. Ecrire les deux sous-programmes unsigned long pgcd(unsigned long a, unsigned long b) et unsigned
long fibonacci(unsigned long l)
4. Tester la fonction pgcd avec des nombres de bonacci consecutifs. Quobservez-vous ?
5. Si on sinteresse au nombre dappels recursifs necessaires pour calculer un pgcd, quel est le pire des cas ?
6. Quel est la valeur du quotient
F
n+1
F
n
?
7. En deduire que les entrees de la forme (F
n+1
, F
n
forment les pires cas.
8. Combien diterations sont necesaires pour calculer pgcd(F
n+1
, F
n
) ?
9. Prouver que F
n
est majore par une suite geometrique.
10. Prouver que le nombre dappels recursifs est majore par un logarithme de base =
1 +

5
2
.
11. Quelle est la complexite de pgcd, est-ce ecace ?
Exercice 13 - Pavage avec des L
Soit n un nombre positif xe. On consid`ere une grille carree de 2
n
2
n
cases. Un case arbitraire est noircie, toutes
les autres sont libres. Le probl`eme consiste `a paver toute la grille sauf la case noircie avec des pi`eces en forme de L.
Ces pi`eces occupent trois cases :
1. resolvez le probl`eme pour n = 0.
23
2. resolvez le probl`eme pour tout n 0, vous montrerez que si lon est capable de resoudre ce probl`eme pour une
valeur n donnee, alors il est possible de le resoudre pour une valeur n + 1.
3. programmez cet algorithme en C, remplissez chaque case avec un caract`ere. Vous representerez une pi`ece en
aectant le meme caract`ere `a toutes les cases occupees par cette pi`ece. Par exemple (avec n = 4),
@ @ ? ? ; ; : : + + * * & & % %
@ > > ? ; 9 9 : + ) ) * & $ $ %
A > B B < < 9 = , ) - - $ (
A A B 8 8 < = = , , - # # ( (
E E D 8 J J I I 0 0 / # 5 5 4 4
E C D D J H H I 0 . / / ! 5 3 4
F C C G K H L L 1 . . 2 6 3 3 7
F F G G K K L " 1 1 2 2 6 6 7 7
U U T T P P O " " j i i e e d d
U S S T P N O O j j h i e c c d
V S W W Q N N R k h h l f f c g
V V W M Q Q R R k k l l b f g g
Z Z Y M M _ ^ ^ o o n b b t s s
Z X Y Y _ _ ] ^ o m n n t t r s
[ X X \ ] ] a p m m q u r r v
[ [ \ \ a a p p q q u u v v
Vous remarquez que la case noircie est celle avec le point dexclamation. Representez la matrice en memoire
de sorte `a faciliter limplementation recursive de lalgorithme. Cest `a dire en indicant de la fa con suivante (si
n = 3) ;
0 1 4 5 16 18 20 21
2 3 6 7 17 19 22 23
8 9 12 13 24 25 28 29
10 11 14 15 26 27 30 31
32 33 36 37 48 49 52 53
34 35 38 39 50 51 54 55
40 41 44 45 56 57 60 61
42 43 46 47 58 59 62 63
3.4.5 Lheure du code
Maintenant cest lheure du code. Etes-vous capable de programmer les algorithmes etudies dans les exercices
precedents ? Cest ce que nous allons voir...
Exercice 14 - Echauement : representation des complexes
Ecrivez les fonctions du chier complexe.c correspondant au chier complexe.h ci-dessous :
#i f ndef COMPLEXEH
#define COMPLEXEH
#include l i nke dLi s t . h
/
Type complexe
/
typedef struct
{
24
/
Part i e r e e l l e
/
double r e ;
/
par t i e i magi nai re
/
double im;
/
module
/
double mod;
/
argument , nul s i l e nombre es t 0 + 0 i
/
double arg ;
}complexe , pComplexe ;
double reComplexe ( compl exe c ) ;
/
Retourne l a par t i e i magi nai re
/
double imComplexe( compl exe c ) ;
/
Retourne l e module
/
double modComplexe ( compl exe c ) ;
/
Retourne l argument
/
double argComplexe ( compl exe c ) ;
/
Af f i che c sous forme exponent i el l e
/
void printExpComplexe ( compl exe c ) ;
/
Af f i che l a f f i x e de c
/
void pri ntAf f Compl exe( compl exe c ) ;
/
Cree un complexe a par t i r de son a f f i x e
/
compl exe makeAffComplexe ( double re , double im) ;
/
Cree un complexe a par t i r de sa forme exponent i el l e
/
compl exe makeExpComplexe( double mod, double arg ) ;
/
Retourne l e conjugue de c
/
compl exe conj ugueComplexe( compl exe c ) ;
/
Sous t r ai t c1 et c2
/
compl exe subComplexe ( compl exe c1 , compl exe c2 ) ;
/
Additionne c1 et c2
/
compl exe addComplexe( compl exe c1 , compl exe c2 ) ;
/
Mul t i pl i e c1 et c2
/
compl exe multComplexe ( compl exe c1 , compl exe c2 ) ;
/
Mul t i pl i e c par l e r e el d
25
/
compl exe multReelComplexe ( double d , compl exe c ) ;
/
Di vi se c2 par c1
/
compl exe divComplexe ( compl exe c1 , compl exe c2 ) ;
/
El eve c a l a pui ssance n
/
compl exe pui ssCompl exe ( compl exe c , unsigned long n ) ;
/
Retourne un poi nt eur vers une copi e du complexe c .
/
pComplexe copyComplexe ( compl exe c ) ;
#endif
Exercice 15 - Une biblioth`eque de listes chanees
Ecrivez les fonctions du chier linkedList.c correspondant au chier linkedList.h ci-dessous :
#i f ndef LINKED LIST H
#define LINKED LIST H
/
Mail l on de l a l i s t e chai nee
/
typedef struct l
{
/
poi nt eur vers l a donnee
/
void data ;
/
poi nt eur vers l e mai l l on sui vant
/
struct l next ;
} l i nk ;
/
Type encapsul ant l a l i s t e chai nee
/
typedef struct
{
/
nombre d el ement s de l a l i s t e chai nee
/
i nt s i z e ;
/
poi nt eur vers l e premier el emtn de l a l i s t e chai nee
/
l i nk f i r s t ;
/
poi nt eur vers l e derni er el ement de l a l i s t e chai nee
/
l i nk l a s t ;
} l i nke dLi s t ;
/
Cree une l i s t e chai nee ne contenant aucun el ement .
/
l i nke dLi s t l i nke dLi s t Cr e at e ( ) ;
/
Ajoute l el ement x dans a l a f i n de l a l i s t e chai nee l
/
void l i nkedLi stAppend ( l i nke dLi s t l , void x ) ;
26
/
Ajoute l e mai l l on l k a l a f i n de l a l i s t e l
/
void l i nkedLi stAppendLi nk ( l i nke dLi s t l , l i nk l k ) ;
/
Ajoute l el ement x dans au debut de l a l i s t e chai nee l
/
void l i nkedLi st Push ( l i nke dLi s t l , void x ) ;
/
Ajoute l e mai l l on l k au debut de l a l i s t e l
/
void l i nkedLi st PushLi nk ( l i nke dLi s t l , l i nk l k ) ;
/
Retourne l a t a i l l e de l a l i s t e l
/
i nt l i nke dLi s t Ge t Si z e ( l i nke dLi s t l ) ;
/
Retourne un poi nt eur vers l e premier mai l l on de
l a l i s t e chai nee l , NULL s i l es t vi de .
/
l i nk l i nke dLi s t Ge t Fi r s t ( l i nke dLi s t l ) ;
/
Retourne un poi nt eur vers l e premier mai l l on de l ,
enl eve ce mai l l on de l a l i s t e l . Retourne NULL
s i l es t vi de .
/
l i nk l i nke dLi s t Unl i nkFi r s t ( l i nke dLi s t l ) ;
/
Retourne une l i s t e chai nee contenant t out es l e s images
des donnees par l a f onct i on f . En posant f = id , on obt i ent
une f onct i on de copi e .
/
l i nke dLi s t l i nkedLi stMap ( l i nke dLi s t l , void ( f ) ( void ) ) ;
/
Concatene l es deux l i s t e s begi n et end , l a deuxieme es t aj out ee
a l a f i n de l a premiere .
/
void l i nkedLi st Concat ( l i nke dLi s t begi n , l i nke dLi s t end ) ;
/
Appl ique l a f onct i on f a t out es l e s donnees de l a l i s t e l .
Passer une f onct i on d af f i chage permet par exemple d af f i c he r
l e s donnees de chaque mai l l on .
/
void l i nkedLi st Appl y ( l i nke dLi s t l , void ( f ) ( void ) ) ;
/
Desal l oue l et t ous ses mai l l ons , appl i que l e dest ruct eur f r
a l a donnee de chaque mai l l on .
/
void l i nke dLi s t De s t r oy ( l i nke dLi s t , void ( f r ) ( void ) ) ;
#endif
Exercice 16 - Tri par insertion
Nous allons implementer le tri par insertion dune liste chanee : Vous utiliserez les sous-programmes suivants et
nutiliserez aucune boucle, seule la recursivite est autorisee.
link* insert(link* list, link* item, int (*estInf)(void*, void* )), ins`ere dans la liste list triee le
maillon item. On a estInf(i, j) si et seulement si la cle de i est strictement inferieure `a celle de j.
27
link* triInsertion(link* list, int (*estInf)(void*, void*)), trie par insertion la liste list en utili-
sant la fonction de comparaison estInf.
void linkedListSort(linkedList* l, int (*estInf)(void*, void*)), trie la liste l en modiant le chanage,
vous noublierez pas de mettre `a jour l->first et l->last.
Identifez le pire des cas et observez la fa con dont le temps dexecution crot avec le nombre de maillons. Est-ce
que cela corrobore les conclusions theoriques ?
Exercice 17 - Tri fusion
Le tri par fusion se fait en coupant un tableau en deux sous-tableaux de tailles egales `a un element pr`es, en triant
recursivement les deux sous-tableaux puis en interclassant leurs elements. Ecrire en C une fonction de tri fusion de
listes chanees. Vous prendrez garde `a ne pas recopier les maillons, et `a seulement modier le chanage. Vous utiliserez
les sous-programmes enonces ci-apr`es. Notez bien le type des param`etres.
void split(linkedList* source, linkedList* dest1, linkedList* dest2), repartit les maillons de source
dans dest1 et dest2.
void merge(linkedList* source1, linkedList* source2, linkedList* dest, int (*inf) (void*, void*)),
interclasse les listes source1 et source2 et place le resultat dans la liste dest. Le fonction pointee par f retourne
1 si la cle premier param`etre est inferieur ` a la cle du deuxi`eme param`etre, 0 sinon.
void triFusion(linkedList* l, int (*inf)(void*, void*)), tri la liste l en modiant le chanage.
Comparez son temps dexecution `a celui du tri par selection. Determinez sa complexite. Est-ce un algorithme de
tri ecace ?
Exercice 18 - Transformee discr`ete de Fourier
Nous allons etudier la transformee discr`ete de Fourier et la fa con dont on peut la calculer ecacement. Etant
donne un vecteur a = (a
0
, . . . , a
n1
), la transformee discr`ete de Fourier de a est un vecteur b = (b
0
, . . . , b
n1
), note
b = TF(a) dont le p-`eme element est
b
p
=
n1

k=0
a
k
(e
p
n
2i
)
k
1. Commen cons par etudier les racines complexes de 1. Vous vous doutez probablement 1 a deux racines carrees
1 et 1. Veriez que 1,
1
2
+

3
2
i et
1
2

3
2
i sont 3 racines cubiques de 1.
2. Veriez que 1, 1 +i, 1 et 1 i sont 4 racines quatri`emes de 1.
3. Veriez que W
n
= {e
1
n
2i+
k
n
2i
|k {0, . . . , n 1}} est lensemble des racines n-`emes de 1.
4. Posons
n
= e
1
n
2i
, veez que W
n
= {
k
n
|k {0, . . . , n 1}}.
5. Prouvez que pour tous n et k,
k+n
n
=
k
n
.
On consid`ere lalgorithme
Fonction A(a, x, n)
r 0
pour i {0, . . . , n 1}
y 1
pour j {1, . . . , i}
y y x
n pour
r r +a
i
y
n pour
retourner r
FIN
1. Soit P(x) = a
0
+
n1

i=1
a
i
x
i
un polynome de degre n 1. Que vaut lalgorithme A(P, x, n) ?
28
2. Quelle est la complexite de A?
3. La methode de Horner est basee sur la relation suivante P(x) = a
0
+x(a
1
+x(a
2
+x(. . .))). Ecrivez lalgorithme
recursif horner qui calcule P(x) en utilisant cette relation.
4. Quelle est la complexite de horner ?
5. Soit P(x) = a
0
+
n1

i=1
a
i
x
i
un polynome de degre n 1 et b = TF(a). Montrez que b
p
= P(w
p
n
).
6. Comment calculer TF(a) en utilisant le sous-programme horner ? Ecrivez le sous-programme TF.
7. On note TF
1
la transformee inverse de Fourier, nous admettrons que si a = TF
1
(b), alors
a
q
=
1
n
n1

k=0
b
k

kq
n
Ecrivez le sous-programme TF
1
.
8. Quelle sont les complexites de TF et de TF
1
?
9. Prouvez que pour tous n et k,
2k
2n
=
k
n
.
10. Supposons que n est pair, donc quil existe mtel que n = 2m. Soit a
[0]
= (a
0
, a
2
, . . . , a
2m
), a
[1]
= (a
1
, a
3
, . . . , a
2m+1
),
b
[0]
= TF(a
[0]
) et b
[1]
= TF(a
[1]
). Soit q {0, . . . , m1}, montrez que
b
q
= b
[0]
q
+
q
n
b
[1]
q
puis que
b
q+m
= b
[0]
q
+
q+m
n
b
[1]
q
11. Ecrire le sous-programme FFT qui calcule la transformee discr`ete de Fourier dun vecteur de taille n = 2
k
en
utilisant la relation de recurrence ci-dessus.
12. Quelle est la complexite de FFT ?
13. Supposons que n est pair, donc quil existe mtel que n = 2m. Soit b
[0]
= (b
0
, b
2
, . . . , b
2m
), b
[1]
= (b
1
, b
3
, . . . , b
2m+1
),
y
[0]
= TF
1
(b
[0]
) et y
[1]
= TF
1
(b
[1]
). Soit p {0, . . . , m1} et y = TF
1
(b). Montrez que
y
p
=
1
2
(y
[0]
p
+
p
n
y
[1]
p
)
puis que
y
p+m
=
1
2
(y
[0]
p
+
(p+m)
n
y
[1]
p
)
14. Ecrire le sous-programme FFT
1
qui calcule la transformee inverse de Fourier dun vecteur de taille n = 2
k
en
utilisant la relation de recurrence ci-dessus.
15. Quelle est la complexite de FFT
1
?
16. Ecrivez les fonctions du chier fourier.c correspondant au chier fourier.h ci-dessous.
#i f ndef FOURIER H
#define FOURIER H
#include l i nke dLi s t . h
#include compl exe . h
/
Retourne l a t ransf ormee di s c r e t e de Fourier du vect eur l .
Al gorithme i t e r a t i f en O(n2).
/
l i nke dLi s t t r ans f or me e Four i e r I t ( l i nke dLi s t l ) ;
/
Retourne l a t ransf ormee di s c r e t e de Fourier i nverse
du vect eur l . Al gorithme i t e r a t i f en O(n2).
/
l i nke dLi s t t r ans f or me e I nve r s e Four i e r I t ( l i nke dLi s t l ) ;
29
/
Retourne l a t ransf ormee di s c r e t e de Fourier du vect eur l , de t a i l l e
n = 2m. Al gorithme r ec ur s i f en O(n l og n) .
/
l i nke dLi s t FFT( l i nke dLi s t l ) ;
/
Retourne l a t ransf ormee di s c r e t e de Fourier i nverse
du vect eur l de t a i l l e n = 2m. Al gorithme r e cur s i f en
O(n l og n) .
/
l i nke dLi s t i nverseFFT( l i nke dLi s t l ) ;
#endif
Vous utiliserez les fonctions auxiliaires suivantes :
1. linkedList* uniteRacinesComplexe(complexe c, unsigned long n), retourne les n racines n-`eme de 1.
2. complexe horner(link* p, complexe x), retourne limage de x par le polynome p.
Exercice 19 - Representation des polynomes
Nous souhaitons implementer une biblioth`eque de representation des fonctiosn polynomes. La plupart des operations
sont relativement simples `a rediger. La plus delicate est la multiplication. Prenons un exemple, pour multiplier P(x) =
1 +x + 2
2
et Q(x) = 1 x +x
2
, il y a deux fa cons de proceder.
1. En multipliant betement : P(x)Q(X) = (1+x+2
2
)(1x+x
2
) = 1(1x+x
2
)+x[(1x+x
2
)+2x(1x+x
2
)] =
(1 x +x
2
) +x[1 +x x
2
+ 2x
3
] = 1 x +x
2
+x +x
2
x
3
+ 2x
4
= 1 + 2x
2
x
3
+ 2x
4
.
2. Une autre methode consiste `a passer par une interpolation. Le polynome PQ sera evidemment de degre 4, donc
en ayant 5 points par lesquels passa la courbe de PQ, il est possible dinterpoler ses coecients. Pour trouver
ces points, il sut devaluer P et Q en 5 points, par exemple {1, 2, 3, 4, 5}, On obtient 2 vecteurs
{(1, P(1)), (2, P(2)), (3, P(3)), (4, P(4)), (5, P(5))}
et
{(1, Q(1)), (2, Q(2)), (3, Q(3)), (4, Q(4)), (5, Q(5))}
Cela nous donne 5 points par lesquels passe la courbe de PQ :
{(1, P(1)Q(1)), (2, P(2)Q(2)), (3, P(3)Q(3)), (4, P(4)Q(4)), (5, P(5)Q(5))}
Il sut ensuite deectuer une interpolation des coecients a, b, c, d et e de la courbe de PQ, cela se fait en
resolvant le syst`eme dequations
{a1
4
+b1
3
+c1
2
+d1
1
+e = P(1)Q(1), a2
4
+b2
3
+c2
2
+d2
1
+e = P(2)Q(2), . . .}
Chacune de ces methoes requiert O(n
2
) operations. Il est cependant possible daner la deuxi`eme en choisissant
judicieusement les points servant `a evaluer puis `a interpoler. En prenant W
n
comme ensemble de points, on ram`ene les
evaluations de ces points `a des transformees de Fourier et linterpolation `a une transformation inverse de Fourier. Cela
permet de multiplier des polynomes en O(nlog
2
n). Voyez [2] pour un expose davantage detaille. Ecrivez les fonctions
du chier polynomes.c correspondant au chier polynomes.h ci-dessous. Vous prendrez soin de vous assurer que la
multiplication `a laide de la transformee de Fourier est plus rapide que la version pour boeufs.
#i f ndef POLYNOMEH
#define POLYNOMEH
#include l i nke dLi s t . h
#include compl exe . h
#include f o u r i e r . h
/
Nous represent erons un polynome avec une l i s t e chai nee contenant
l e s c oe f f i c i e nt s du polynome par ordre de degre cr oi s s ant .
/
/
Retourne un polynome vi de .
/
30
l i nke dLi s t makePolynome ( ) ;
/
Retourne une copi e de l , copi e aussi l e s c o e f f i c i e nt s .
/
l i nke dLi s t copyPolynome ( l i nke dLi s t l ) ;
/
Det rui t l e polynome l et ses c oe f f i c i e nt s .
/
void destroyPol ynome ( l i nke dLi s t l ) ;
/
Af f i che polynome l e pl us proprement pos s i b l e .
/
void pri ntPol ynome ( l i nke dLi s t polynome ) ;
/
Retourne l e degre de l .
/
i nt degreePol ynome( l i nke dLi s t l ) ;
/
Ajoute un monome de c o e f f i c i e nt c oe f f a l a f i n du polynome , f ai s ant
ai ns i crout re son degre de 1.
/
void appendCoeffPolynome ( l i nke dLi s t polynome , double c o e f f ) ;
/
Cree et ret ourne l e polynome de degre n1 dont l e s
c o e f f i c i e n t s sont passes dans l e t abl eau d .
/
l i nke dLi s t makeArrayPolynome( double d , i nt n ) ;
/
Retourne l e polynome nul .
/
l i nke dLi s t zeroPol ynome ( ) ;
/
Retourne l e polynome uni t e .
/
l i nke dLi s t uni tPol ynome ( ) ;
/
Ajoute l a const ant e d au polynome l .
/
void addRealPolynome( l i nke dLi s t l , double d ) ;
/
Mul t i pl i e l e polynome l par l e r e el d .
/
void multRealPolynome( l i nke dLi s t l , double d ) ;
/
Mul t i pl i e l e polynome l par Xn
/
void multXNPolynome ( l i nke dLi s t l , i nt n ) ;
/
Mul t i pl i e l e polynome l par c oe f f Xexp
/
void multMonomePolynome ( l i nke dLi s t l , double c oe f f , i nt exp ) ;
/
Addi t i one l es deux polynomes a et b , ret ourne c e t t e somme.
/
l i nke dLi s t addPolynome( l i nke dLi s t a , l i nke dLi s t b ) ;
/
Mul t i pl i e a et b avec l a recurrence
( a 0 + a 1X + . . . + a nXn)Q(X)
= a 0 Q(X) + X ( a 1 + a 2 X. . . + a n X(n1)) Q(X)
/
l i nke dLi s t slowMultPolynome( l i nke dLi s t a , l i nke dLi s t b ) ;
/
Mul t i pl e a et b en passant par une t ransf ormee de f our i er .
/
l i nke dLi s t multPolynome ( l i nke dLi s t a , l i nke dLi s t b ) ;
31
/
Eval ue l e polynome l en x avec l a methode de Horner .
/
double eval uatePol ynome ( l i nke dLi s t l , double x ) ;
#endif
32
Chapitre 4
Arbres
4.1 Denitions par induction
On remarque que lensemble des arbres binaires est deni par induction. Cest-`a-dire `a partir dun ensemble
datomes et de r`egles. Les atomes sont les elements de lensemble qui sont indecomposables, par exemple larbre vide
. Les r`egles permettent `a partir delements dun ensemble de creer dautres elements. Par exemple, si A et B sont des
arbres binaires, et r un noeud, alors le triplet (A, r, B) est un arbre binaire.
4.1.1 Denition
On denit un ensemble E par induction en deux etapes :
La base La base est une liste delements de E qui sont des atomes. On les notes A et on la propriete A E.
Linduction Linduction est un ensemble de r`egles permettant de creer un element de E avec dautres elements
de E. Chaque r`egle est une fonction f : E
k
E telle que si (E
1
, . . . , E
k
) est un k-uplet delements de E, alors
f(E
1
, . . . , E
k
) E.
4.1.2 Exemple
Considerons lensemble IN des entiers naturels, on le denit de la sorte :
Base la seul atome de IN est 0. Donc On les note A = {0}.
Induction On prend comme unique r`egle la fonction s : x x + 1 appelee successeur. Pour tout element n de
IN, on a s(n) N.
On conviendra donc que IN est lensembles de tous les elements faisant soit partie de A, soit pouvant etre obtenu
par application dun nombre ni de r`egles. Par exemple, 0 IN, car 0 A, 4 IN, car 0 A et 4 = s(s(s(s(0)))) IN
(vous remarquez que 4 sobtient par application dun nombre ni de r`egles).
4.1.3 Expressions arithmetiques
Une expression arithmerique totalement parenthesee (EATP) se denit de la sorte,
Base Tout nombre x IR est une EATP.
Induction Soit E, E

deux EATPs, alors (E +E

), (E E

), (E E

) et (E/E

) sont des EATPs.


Une juxtaposition de symboles X est une EATP sil est possible de generer X en applicant un nombre ni de fois les
r`egles precedentes. Si lon souhaite denir formellement une EATP, il convient de les representer de fa con ensembliste.
On redenit donc lensemble E des EATPs de la sorte :
Base IR E
Induction E, E

E, +(E, E

), (E, E

), (E, E

), /(E, E

) E.
Cette denition met en correspondance des expressions comme (3 + (4 5)) avec des ensembles de la forme
+(3, (4, 5)), plus faciles `a manier dans des algorithmes. Naturellement, on representera toute expression arithmerique
par un arbre binaire. Les feuilles representeront les atomes de nos expressions et les noeuds representeront les r`egles.
33
4.1.4 Application aux arbres binaires
Soit f une fonction prenant an argument un arbre binaire, la fa con la plus claire et la precise de denir une telle
fonction est souvent de la caracteriser par induction. Par exemple
Denition 4.1.1 On note h(A) la hauteur de larbre A. On la denit par induction :
h() = 1
h((A
g
, r, A
d
)) = 1 + max(h(A
g
), h(A
d
))
Denition 4.1.2 On note |A| le nombre de noeuds dun arbre A. On le denit par induction :
|| = 0
|(A, r, B)| = 1 +|A| +|B|
4.2 Preuves par induction
4.2.1 Lien avec les preuves par recurrence
Si on veut montrer que tout element de IN verie une propriete, par exemple n IN, n(n + 1) est pair, on va
construire par induction lensemble E IN des n IN tels que n(n + 1) est pair. Si les atomes de IN et de E sont
les memes et que lon parvient `a construire IN et E avec les memes r`egles, alors IN = E. Nous avons deux etapes `a
eectuer pour le verier :
Base la seul atome de IN est 0. Comme 0 1 = 0 est pair, alors 0 E.
Induction La seule r`egle que nous avons ` a examiner est s : x x + 1. Prenons un element arbitraire de E (E
nest pas vide puisquil contient 0), notons-le n. Montrons que s(n) E. On a s(n) = n + 1, donc s(n) E si
(n + 1)(n + 1) est pair. Or (n + 1)(n + 2) = (n + 1)n + (n + 1)2, comme n E, alors n(n + 1) pair. Par ailleurs
2(n + 1) est evidemment pair. Comme la somme de deux nombres pairs est paire, alors s(n) E.
Nous venons de montrer que IN peut etre construit de la meme fa con que E, donc IN E (et par consequent
E = IN). Comme E est lensemble des entiers n tels que n(n + 1) est pair, alors pour tout element n de IN, n(n + 1)
est pair. Ce que nous venons de faire est en fait une preuve par recurrence. La raisonnement par recurrence est un cas
particulier du raisonnement par induction.
4.2.2 Application aux EATPs
On veut demontrer que toute EATP contient au moins autant de parenth`eses que doperateurs. Procedons en ayant
`a lesprit la denition dune EATP :
Base Les seules EATPs atomiques les expressions reduites `a un reel, dont ne contenant ni parenth`ese, ni
operateur.
Induction Les quatre r`egles `a considerer sont de la meme forme : E = (E
g
oE
d
) o` u o est un operateur binaire,
E
g
, E
d
deux EATPs, et E une EATP non atomique pour laquelle on cherche `a demontrer la propriete. Par hy-
poth`ese dinduction, E
g
et E
d
contiennent au moins autant de parenth`eses que doperateurs. Et dans lexpression
(E
g
oE
d
) on ajoute plus de parenth`eses que doperateurs, donc E contient au moins autant de parenth`eses que
doperateurs.
Exercice 1 - Operandes et operateurs
Demontrez par induction que dans toute EATP, il y a une operande de plus quil ny a doperateurs.
4.3 Algorithmique dans les arbres
On denit une bijection cle entre les noeuds de A et un ensemble (E, >) totalement ordonne. On note cle(x) la cle
du noeud x. En general, on prend E = IN.
Nous representerons chaque noeud dun arbre binaire avec une structure ABR contenant les champs suivants :
cle
g
d
34
Si a est une variable de type AB alors a.cle est la cle de la racine de larbre a, a.d est un pointeur vers le sous-arbre
droit, a.g est un pointeur vers le sous-arbre gauche. Si un pointeur ne pointe vers aucune valeur, on dira quil prend
la valeur null. On fera une allocation dynamique en utilisant la fonction AB(f
g
, c, f
d
) pour creer un noeud de cle c et
de sous-arbre gauche (resp. droit) f
g
(resp. f
d
) de type AB.
Exercice 2 - Nombre de noeuds
Ecrire une fonction retournant le nombre de noeuds formant un arbre A.
Exercice 3 - Hauteur
Ecrire une fonction retournant la hauteur dun arbre A.
Exercice 4 - Profondeur
Ecrire une fonction retournant la profondeur dun noeud x dans un arbre A.
4.4 Arbres n-naires
Denition 4.4.1 A est un arbre n-aire de si une des conditions suivantes est veriee
A est un arbre vide, on le note abusivement A = .
A = (d, l) o` u
d est la racine de A
l est un k-uplet (k n) darbres n-aires.
On remarque quun arbre 1-aire est une liste chanee. Nous representerons un arbre n-aire avec une structure
ARBRE, dont le constructeur est de meme nom.
35
Chapitre 5
Files de priorite
Une le de priorite est une structure de donnee permettant de stocker un ensemble delements munis dune cle
dordre total, et dans laquelle on sinteresse aux operations suivantes :
Extraction du plus petit element
Ajout dun element
Suppression du plus petit element
5.1 Implementations naves
Une premi`ere idee serait dimplementer une le de priorite avec un tableau non trie. Dans ce cas, on a :
Extraction du plus petit element en O(n)
Ajout dun element en O(1)
Suppression du plus petit element O(n)
Cette solution est peu satisfaisante. Avec un tableau trie, une liste chanee triee ou non, on obtient des resultats
peu satisfaisants. Nous allons devoir mediter sur des solutions permettant dobtenir des temps de calcul au moins
inferieurs `a O(log
2
n).
Exercice 1 - Tableau non trie
Justier les resultats de complexite.
Exercice 2 - Tableau trie
Determiner les complexites des trois operations dans le cas o` u le tableau est trie.
Exercice 3 - Liste chanee non triee
Determiner les complexites des trois operations dans le cas o` u on utilise une liste chanee non triee.
Exercice 4 - Liste chanee triee
Determiner les complexites des trois operations dans le cas o` u on utilise une liste chanee triee.
5.2 Tas
5.2.1 Denition
Un tas est un arbre binaire veriant les proprietes suivantes :
1. Tous les niveaux sont remplis sauf eventuellement le dernier.
2. Dans le dernier niveau, les noeuds sont disposes le plus ` a gauche possible.
36
3. Tous noeud poss`ede une cle inferieure `a celle de ses deux ls.
Par exemple,
1
2 6
7 3 7 11
8 12
Vous remarquez que les trois premiers niveaux sont remplis et que dans le quatri`eme niveau, les noeuds disposes
le plus `a gauche possible. De meme, on constate que chaque noeud a une cle inferieure `a celle de ses ls.
Exercice 5 - Denition
Representer un tas contenant les elements suivants : {3, 87, 1, 0, 3, 9, 54, 3}. Vous disposerez les elements `a votre
convenance du moment que larbre considere est bien un tas.
Exercice 6 - Hauteur
Majorer la hauteur dun tas contenant n elements.
5.2.2 Extraction du minumum
Vous remarquez que le plus petit element est `a la racine. Par consequent lextraction est trivialement en temps
constant.
5.2.3 Insertion
Pour inserer un element dans un tas, on choisit lunique emplacement qui permet de conserver les deux premi`eres
proprietes ? Ensuite on reequilibre le tas. Le soin de cette procedure vous est laisse en exercice.
Exercice 7 - Ajout
Decrire la procedure permettant de determiner o` u inserer un nouvel element dans un tas.
5.2.4 Suppression du minimum
Supprimer la derni`ere feuille du tas est simple, cest la seule operation qui conserve les deux premi`eres proprietes.
La solution que nous preconiserons sera de permuter la racine avec le dernier element. Il sura ensuite dequiliber le
tas autour de la racine.
Exercice 8 - Equilibrage dun tas
Decrire une fa con dequilibrer un tas apr`es insertion dun nouvel element. Donner un invariant de boucle. Est-ce
que le programme se termine ?
5.2.5 Implementation
En r`egle generale, on implemente un tas avec un tableau. Les elements sont disposes dans lordre dun parcours en
largeur de la gauche vers la droite.
37
Exercice 9 - Indices
Nous indicerons les tableaux `a partir de 1. Determinez une relation de recurrence entre lindice dun noeud et les
indices de ses voisins (p`ere, ls gauche, ls droit).
Exercice 10 - Performances
Faites le point sur les temps dexecution des diverses operations. Est-ce ecace ?
5.3 Tas binomial
Ajoutons maintenant une operation : la fusion. Etant donnees deux ls de priorites, comment les fusionner eca-
cement ?
5.3.1 Arbre binomial
Un arbre binomial dordre n (note B
n
) est deni par induction de la fa con suivante :
B
0
est reduit `a un seul noeud.
B
n
est construit de la fa con suivante :
B
n1
B
n1
Voici par exemple B
0
, B
1
, B
2
, B
3
et B
4
:
Exercice 11 - Representation graphique
Representer les 5 premiers arbres binomiaux.
Exercice 12 - Proprietes
Prouver par induction les proprietes suivantes :
1. B
n
contient 2
n
noeuds.
2. B
n
est de hauteur n.
3. La racine de B
n
a n ls.
4. Les n ls de la racine de B
n
sont B
0
, B
1
, . . ., B
n1
.
5. Il y a C
k
n
noeuds de profondeur k dans B
n
.
5.3.2 Fusion
Etant donnes deux arbres binomiaux, on les fusionne en faisant de lun un ls de la racine de lautre. Cette operation
(jeu dadresses) se fait en temps constant.
38
5.3.3 Tas binomial
Un tas binomial est une liste darbres binomiaux veriant les proprietes suivantes :
Dans chaque arbre, tout noeud est de cle inferieure `a ses ls.
Tous les arbres sont dordres distincts.
5.3.4 Implementation
Les tas binomiaux ne sont pas triviaux `a implementer. On represente un tas binomial par une liste chanee darbre
binomiaux. Chaque arbre binomial est represente par un ordre, une cle, et un pointeur vers la liste chanee de ses ls.
Le premier des ls est larbre dordre le plus eleve.
Exercice 13 - Implementation
Representer graphiquement la representation en memoire dun tas binomial.
Exercice 14 - Representation binaire de n
Montrer quil est toujours possible de repartir n cles dans des arbres binomiaux dordres distincts. Majorer le
nombre darbres binomiaux necessaires en fonction de n.
5.3.5 Extraction du minimum
Comme tous les arbres sont equilibres, le plus petit element du tas est necessairement une racine. Il sut donc
dexaminer tous les racines.
Exercice 15 - Complexite
Quelle est la complexite de lextraction du minimum?
5.3.6 Fusion
Etant donnes deux tas binomiaux, il est possible de les fusionner en utilisant comme sous-programme la fusion de
deux arbres.
Exercice 16 - Fusion
Decrire une methode recursive permettant de fusionner deux tas binomiaux. Quelle en est la complexite ?
Exercice 17 - Autres operations
Decrire de quelle fa con ramener `a une fusion linsertion dun nouvel element. Que se passe-t-il si lon supprime la
racine dun arbre binomial ? En deduire un moyen de ramener la suppression dun element `a une fusion. Determiner
les complexites de ces deux operations.
39
Chapitre 6
Hachage
6.1 Principe
Une table de hachage est une structure de donnees indexee par des valeurs V = {1, . . . , m}, comme un tableau.
On dit alors que cette table est de taille m. Une table de hachage contient des elements posedant chacun une cle, on
note C = {1, . . . , n} lensemble des cles. Il existe en r`egle generale beaucoup plus de cles que dindices dans une table.
On aecte `a chaque element, donc `a chaque cle, un (ou plusieurs) indice dans la table. Pour ce faire, on dispose dune
fonction de hachage h : C V , qui `a toute cle c associe un indice h(c) permettant de placer (rechercher, ou
supprimer) un element dans la table de hachage.
6.2 Collisions
Comme |C| > |V |, h ne peut etre injective. Par consequent, il est possible que des elements se telescopent, cest-`a-
dire que deux cles distinctes aient la meme image par h. Deux techniques existent pour gerer les collisions :
1. Le chanage
2. Ladressage ouvert
6.2.1 Gestion des collisions par chanage
Pour resoudre les collisions par chanage, on place dans chaque emplacement de la table non pas les elements
eux-memes, mais un pointeur vers une liste chanee contenant ces elements. Si un emplacement est dej` a ocupe par
un ensemble delements T au moment de linsertion de e, alors on place e `a la n de la liste chanee formee par les
elements de e.
6.2.2 Gestion des collisions par adressage ouvert
Ladressage ouvert consiste `a etendre la fonction de hachage en un ensemble de fonctions {h
i
|i V }, lors de
linsertion dun element e, on applique dabord h
1
`a la cle de e, si lemplacemnet est disponible, alors on y place e,
sinon on lui cherche un nouvel emplacement avec la fonction h
2
, etc.
Nous ne travaillerons dorevavant que sur des tables dans lesquelles les collisions sont gerees par chanage.
Exercice 1 - Resolution par chanage
Soit h la fonction de hachage denie par h(k) = kmod8 et soit une table de hachage de taille m = 8 dans laquelle
les collisions sont resolues par chanage. Donner letat de la table apr`es linsertion des cles 5, 28, 19, 15, 20, 33, 12, 17
et 10.
40
Exercice 2 - Temps moyen de recherche dun noeud
On consid`ere une fonction de hachage h qui repartit uniformement les cles dans une table de hachage de taille m
dans laquelle les collisions sont resolues par chanage.
1. Si n cles sont presentes dans la table, quelle est la longueur moyenne dune liste.
2. Quelle est la duree moyenne dune recherche infructueuse dans la table ?
3. On part du principe que si r(x) est le rang dinsertion de la cle x dans la table, les n valeurs que peut prendre
r(x) sont equiprobables. Determiner la duree moyenne dune recherche de x.
4. Quelle est la duree moyenne de recherche dune cle presente dans la table ?
5. Quelle est la duree moyenne moyenne de recherche dune cle dans une table de hachage de taille m contenant
O(m) cles ?
41
Chapitre 7
AVL
7.1 Arbres binaires de recherche
Denition 7.1.1 Soit A un arbre binaire dont chaque noeud est muni dune cle. A est un arbre binaire de recherche
si pour tout noeud x,
y A
g
(x), cle(y) < cle(x)
z A
d
(x), cle(x) < cle(z)
Pour davantage dinformations, voir [2].
Exercice 1 - Denition
Construire tous les ABR contenant les valeurs {1, 2, 3}
Exercice 2 - Notation ensembliste
1. Ecrire un algorithme pla cant dans une variable v larbre ((, 3, ), 1, (, 2, ))
2. Dessiner le graphe obtenu
3. Est-ce un ABR bien forme ?
Exercice 3 - Insertions
1. Dessiner larbre A(v) deni comme suit :
a = (, 4, )
b = ((, 11, ), 7, )
c = (, 3, (, 9, ))
d = ((, 12, ), 6, (, 2, ))
v = ((a, 5, b), 1, (c, 10, d))
2. Est-ce un ABR bien forme ?
3. Changer lordre des noeuds de sorte que A(v) devienne un ABR.
4. Inserez le noeud de cle 8 dans cet arbre
Exercice 4 - Suppression
On notera
succ
A
(x) le successeur de x dans A, cest-`a-dire lelement de A(x) de plus petite cle parmi les elements de cle
superieure `a celle de x.
premier(A(x)) le plus petit element de A(x)
1. Prouvez que si un noeud x dun arbre A a deux ls, alors succ
A
(x) na pas de ls gauche.
2. Montrez que y = succ
A
(x) si et seulement si y = premier(A
d
(x) ou x = dernier(A
g
(y)).
3. Supprimez la racine de larbre de lexercice precedent
42
Exercice 5 - Fonctions recursives
1. Ecrire une fonction inserant une cle x dans un arbre A et retournant larbre obtenu.
2. Ecrire une fonction retournant la cle minimale de larbre A.
3. Ecrire une fonction prenant un arbre A en param`etre et retournant le couple (A prive de sa cle minimale, la cle
minimale de A).
4. Ecrire une fonction retournant vrai si et seulement si larbre A passe en param`etre est un ABR bien forme.
5. Ecrire une fonction prenant en param`etres un arbre A est une valeur c, et retournant larbre A dans lequel aura
ete supprime le noeud de cle c.
Exercice 6 - Application au tri
Ecrire une fonction triAbr(l) prenant en param`etre une liste l contenant des elements dun ensemble totalement
ordonne et retournant un liste contenant les elements de la liste l tries par ordre croissant. Vous denirez pour ce faire
toutes les fonctions auxiliaires necessaires pour rendre lalgorithme lisible.
7.2 Complexite dans le pire de cas
La complexite dans le pire des cas est peu satisfaisante. Inserons dans un arbre des elements par ordre croissant,
et il seront disposes en liste. Chaque operation se fera de la sorte en un temps O(n). Ces performances sont les memes
quavec des listes chanees. On en conclut que dans le pire des cas, les ABR ne sont pas plus performants que des
vulgaires listes chanees. Nous allons nous interesser, dans la suite de ce cours, `a des arbres binaires de recherche
quelque peu particuliers, dans lesquels toute operation se fera en temps O(log
2
(n)).
Exercice 7 - complexite moyenne dune recherche
Soit un ensemble E = {1, . . . , n} de n cles. Nous voulons determiner le nombre moyen a
n
de noeuds visites lors
de la recherche dune de ces cles dans un ABR contenant les cles de E. On suppose que les ordres dinsertion sont
equiprobables. Par ailleurs, on consid`ere que la probabilite de rechercher la cle i E est
1
n
.
1. Montrer que la probabilite que la racine ait la cle i est
1
n
.
2. Notons a
i
n
le nombre moyen de comparaisons necessaires pour trouver une cle dans un arbre `a n cles dont la
racine porte la cle i. Exprimer a
n
en fonction de {a
i
n
|i E}.
3. On pose a
0
= 0. Combien valent a
1
1
et a
1
?
4. Montrer que i E, a
i
n
= (a
i1
+ 1)
i 1
n
+
1
n
+ (a
ni
+ 1)
n i
n
5. En deduire que a
n
= 1 +
2
n
2
n1

i=1
ia
i
6. En deduire que a
n
=
1
n
2
((n
2
1)a
n1
+ 2n 1)
7. Utiliser le fait que log
2
(n 1) =
1
ln2
_
n1
1
dx
x
et que
1
n

_
n
n1
dx
x
pour prouver par recurrence quil existe
tel que a
n
log
2
(n)
8. Quelle est la complexite moyenne de la recherche dune cle de E dans un ABR?
7.3 Rotations
Nous allons etudier une operation sur les ABR sappelant la rotation (je vous conseille de faire des dessins si vous
tenez `a vous representer les choses concr`etement). Il existe deux rotations simples (la rotation droite et la rotation
gauche), et deux rotations doubles (la rotation droite-gauche et la rotation gauche-droite). La rotation droite est denie
de la sorte :
43
rotationDroite(((B, y, C), x, D)) = (B, y, (C, x, D))
De fa con symetrique, on denit la rotation gauche :
rotationGauche((B, x, (C, y, D)) = ((B, x, C), y, D)
La rotation gauche-droite se denit `a laide des deux precedentes :
rotationGaucheDroite((G, x, D)) = rotationDroite(rotationGauche(G), x, D)
Et on denit pour nir la rotation droite-gauche de fa con symetrique
rotationDroiteGauche((G, x, D)) = rotationGauche(G, x, rotationDroite(D))
7.4 AVLs
Si pour un noeud v dun ABR, les hauteurs des sous-arbres droit et gauche de v di`erent de au plus 1, on dit que
ce noeud est equilibre. Un AVL est un ABR dans lequel tous les noeuds sont equilibres.
7.4.1 Reequilibrage
Les rotations vont servir `a maintenir lequilibre de chaque noeud. Nous allons nous interesser `a lequilibre dun
arbre de racine v dont les deux sous-arbres (G et D) sont equilibres, et ont des hauteurs qui di`erent de 2. Supposons,
sans perte de generalite, que h(D) = n, et que h(G) = n + 2. Soit G = (B, y, D), alors deux cas se presentent :
si h(B) = n + 1, alors une rotation droite de v equilibre larbre.
si h(B) = n + 1, alors une rotation gauche-droite de v equilibre larbre.
7.4.2 Insertion
Pour inserer un noeud, procedez comme avec des ABR pour lajouter en tant que feuille. Ensuite, controlez
lequilibre de chaque noeud et faites des rotations si necessaire sur le chemin allant de la feuille nouvellement inseree
`a la racine.
7.4.3 Suppression
De la meme fa con quavec des ABR, on supprime un noeud en le rempla cant par le noeud du plus grande cle du
sous-arbre gauche, ou celui de plus petite cle du sous-arbre droit. La suppression du minimum ou du maximum a
les memes consequences que pour linsertion, il est necessaire de controler lequilibre de chaque noeud sur le chemin
menant du p`ere de la feuille supprimee `a la racine.
7.4.4 Complements
Pour plus de details, je vous conseille de vous reporter `a [3]. Lapplet [4] illustre graphiquement le fonctionnement
dun AVL.
Exercices
Exercice 8 - Implementation en C
Ecrivez les fonctions du chier avl.c correspondant au chier avl.h ci-dessous :
#i f ndef AVL H
#include l i nke dLi s t . h
#define AVL H
typedef struct
{
44
/
Pointeur vers une f onct i on permettant de
recuperer l a cl e de chaque donnee .
/
i nt ( getKey ) ( void) ;
/
Pointeur vers une f onct i on permettant de
de det r ui r e chaque donnee .
/
void ( f r eeDat a ) ( void) ;
/
Pointeur vers l a raci ne de l arbre .
/
void r oot ;
} avl ;
//
/
Retourne un AVL vi de .
/
avl avl Cr eat e ( i nt ( getKey ) ( void) , void ( f r eeDat a ) ( void ) ) ;
/
Modifie l a f onct i on de des t r uct i on des donnees .
/
void avl Set Fr eeFunct i on( avl a , void ( f r eeDat a ) ( void ) ) ;
/
Af f i che l e s c l es de l AVL a dans l ordre croi ssant , O(n) .
/
void avl Pri ntKeys ( avl a ) ;
/
Insere l a donnee v dans l AVL a , O( l og n) .
/
void av l I ns e r t ( avl a , void v ) ;
/
Retourne l a donnee de cl e x s i e l l e se t rouve dans l AVL a ,
NULL sinon , O( l og n) .
/
void avl Fi nd ( avl a , i nt x ) ;
/
Supprime l e noeud de cl e k de l AVL a , appl i que l a f onct i on
de des t r uct i on a l a donnee de cl e k , O( l og n) .
/
void avlRemove ( avl a , i nt k ) ;
/
Det rui t l AVL a , appl i que l a f onct i on de des t r uct i on a
t out es l e s donnees du sousarbre , O(n) .
/
void avl Dest r oy ( avl a ) ;
/
Retourne une l i s t e chai nee contenant t out es l e s donnees
de l AVL a di sposees dans l ordre croi ssant , O(n) .
/
l i nke dLi s t avl ToLi st ( avl a ) ;
#endif
Et voici avl.c.
#include<s t di o . h>
#include<mal l oc . h>
#include avl . h
//
45
/
Noeud de l ABR.
/
typedef struct nd
{
/
key es t l a cl e du noeud courant .
/
i nt key ;
/
poi nt eur vers l el ement de cl e key
/
void data ;
/
hauteur du sousarbre :
0 s i ce noeud es t une f e u i l l e .
/
i nt hei ght ;
/
Pointeur vers l e sousarbre dr oi t .
/
struct nd l e f t ;
/
Pointeur vers l e sousarbre gauche .
/
struct nd r i ght ;
}node ;
//
/
Retourne l a hauteur de l arbre de raci ne l ,
1 s i l es t vi de .
/
i nt get Hei ght ( node l )
{
}
//
/
Retourne l a pl us grande des deux val eurs i et j .
/
i nt max( i nt i , i nt j )
{
}
//
/
Met a j our l a hauteur de l a raci ne l en f onct i on des
haut eurs des raci nes des deux sousarbres .
/
void set Hei ght ( node l )
{
}
//
/
Cree un noeud contenant l a donnee data ,
ayant pour sousarbre gauche l et
pour sousarbre dr oi t r .
/
node nodeCreate ( i nt ( getKey ) ( void) , node l , void data , node r )
{
}
//
/
Retourne un avl vi de
46
/
avl avl Cr eat e ( i nt ( getKey ) ( void) , void ( f r eeDat a ) ( void) )
{
}
//
/
Fai t de f reeDat a l a f onct i on de des t r uct i on des donnees .
/
void avl Set Fr eeFunct i on( avl a , void ( f r eeDat a ) ( void) )
{
}
//
/
Af f i che t out es l e s c l es du sousarbre de raci ne n dans
l ordre cr oi s s ant .
/
void nodePri ntKeys ( node n)
{
}
//
/
Af f i che pour t ous l e s noeuds du sousarbre de raci ne n
l a di f f er ence ent re l e s haut eurs du sousarbre dr oi t et
gauche .
/
void nodePr i nt Level s ( node n)
{
}
//
/
Ef f ect ue une r ot at i on dr oi t e de l arbre de raci ne x ,
ret ourne l a raci ne de l arbre apres r ot at i on .
/
node r ot at eRi ght ( node x)
{
}
//
/
Ef f ect ue une r ot at i on gauche de l arbre de raci ne x ,
ret ourne l a raci ne de l arbre apres r ot at i on .
/
node r ot at e Le f t ( node x)
{
}
//
/
Ef f ect ue une r ot at i on gauchedr oi t e de l arbre de raci ne x ,
ret ourne l a raci ne de l arbre apres r ot at i on .
/
node r ot at e Le f t Ri ght ( node x)
{
}
//
/
Ef f ect ue une r ot at i on droi t e gauche de l arbre de raci ne x ,
ret ourne l a raci ne de l arbre apres r ot at i on .
/
node r ot at e Ri ght Le f t ( node x)
{
47
}
//
/
Reequi l i bre l arbre de raci ne x , ret ourne l a raci ne de
l arbre apres r e equi l i b r ag e . On part du pri nci pe
que l e s haut eurs des sousarbres dr oi t et gauche d i f f e r e nt
de au pl us 1.
/
node bal ance ( node x)
{
}
//
/
Insere l a donnee v dans l arbre de raci ne n
et r e e q ui l i b r e l arbre , ret ourne l a raci ne de
l arbre apres i ns er t i on et r e equi l i br age .
/
node nodeI nser t ( i nt ( key ) ( void) , node n , void v)
{
}
//
/
Insere l a donnee v dans l arbre a , O( l og n) .
/
void av l I ns e r t ( avl a , void v)
{
}
//
/
Af f i che l e s c l es de l AVL a dans l ordre croi ssant , O(n)
/
void avl Pri ntKeys ( avl a)
{
}
//
/
Af f i che pour chaque noeud l a di f f er ence ent re l e s haut eurs
des sousarbres dr oi t et gauche de l AVL.
/
void avl Pr i nt Le ve l s ( avl a )
{
}
//
/
Retourne l a donnee de cl e k s i e l l e se t rouve dans l e sousarbre
de raci ne n, NULL sinon .
/
void f i ndNode ( node n , i nt k)
{
}
//
/
Retourne l a donnee de cl e x s i e l l e se t rouve dans l AVL a ,
NULL sinon , O( l og n)
/
void avl Fi nd ( avl a , i nt x)
{
}
//
48
/
Fai t poi nt er max vers l e noeud de cl e maximale dans
l e sousarbre de raci ne n, det ache l e noeud max de l arbre
et ret ourne l a raci ne de l arbre apres suppressi on .
/
node removeMax( node n , node max)
{
}
//
/
Fai t poi nt er min vers l e noeud de cl e minimale dans
l e sousarbre de raci ne n, det ache l e noeud min de l arbre
et ret ourne l a raci ne de l arbre apres suppressi on .
/
node removeMin ( node n , node min)
{
}
//
/
Supprime l e noeud de cl e k du sousarbre de raci ne n,
appl i que l a f onct i on de des t r uct i on a l a donnee de ce noeud ,
et ret ourne l a raci ne de l arbre apres l a suppressi on .
/
node removeNode( node n , i nt k , void ( f r eeDat a ) ( void) )
{
}
//
/
Supprime l e noeud de cl e k de l AVL a , appl i que l a f onct i on
de des t r uct i on a l a donnee de cl e k , O( l og n) .
/
void avlRemove ( avl a , i nt k)
{
}
//
/
Pl ace dans l a l i s t e chai nee l t out es l e s donnees
du sousarbre de raci ne n dans l ordre cr oi s s ant .
/
void nodeToLi st ( node n , l i nke dLi s t l )
{
}
//
/
Retourne une l i s t e chai nee contenant t out es l e s donnees
de l AVL a di sposees dans l ordre croi ssant , O(n) .
/
l i nke dLi s t avl ToLi st ( avl a)
{
}
//
/
Det rui t t ous l e s noeuds du sousarbre de raci ne n,
appl i que l a f onct i on de des t r uct i on f r a t out es l e s
donnees du sousarbre .
/
void nodeDestroy ( node n , void ( f r ) ( void) )
{
}
//
49
/
Det rui t l AVL a , appl i que l a f onct i on de des t r uct i on a
t out es l e s donnees du sousarbre , O(n) .
/
void avl Dest r oy ( avl a)
{
}
//
//
/
Pour t e s t e r l es al gori t hmes
/
void de s t r oyI nt ( void i )
{
f r e e ( ( i nt ) i ) ;
}
i nt getIntKey( void i )
{
return ( ( i nt ) i ) ;
}
void doNothing ( )
{
}
i nt main ( )
{
i nt i ;
i nt d ;
l i nke dLi s t l ;
l i nk m;
avl a = avl Cr eat e ( getIntKey , de s t r oyI nt ) ;
for ( i = 0 ; i < 40 ; i ++)
{
d = ( i nt ) mal l oc ( si zeof ( i nt ) ) ;
d = i ;
avl I ns e r t ( a , d ) ;
}
avl Pri ntKeys ( a ) ;
avl Pr i nt Le ve l s ( a ) ;
for ( i = 0 ; i < 40 ; i +=5)
avlRemove ( a , i ) ;
avl Pri ntKeys ( a ) ;
avl Pr i nt Le ve l s ( a ) ;
l = avl ToLi st ( a ) ;
for (m = l i nke dLi s t Ge t Fi r s t ( l ) ; m != NULL ; m = m>next )
pr i nt f ( %d > , ( i nt ) (m>data ) ) ;
pr i nt f ( \n ) ;
l i nke dLi s t De s t r oy ( l , doNothing ) ;
avl Set Fr eeFunct i on( a , de s t r oyI nt ) ;
avl Dest r oy ( a ) ;
return 0;
}
50
Chapitre 8
Modelisation
8.1 Denition
Modeliser est une des competences les plus importantes en algorithmique. A partir dun probl`eme concret (in-
dustriel, logistique, economique, etc.), on eectue une modelisation en formalisant le probl`eme avec une terminologie
mathematique, et en reformulant la question de fa con precise. Meilleure est la modelisation, plus il est simple de
resoudre le probl`eme.
8.2 Exemple
Voici un exemple de probl`eme : comment placer 8 reines sur un echiquer de sorte quaucune ne puisse semparer
dune autre ? Si vous souhaitez realiser un programme qui resolve ce probl`eme, vous allez dabord devoir le modeliser
mathematiquement. Dans la plupart des probl`emes, on a
des donnees : les emplacement des reines
des contraintes : toutes les reines sont placees, il nexiste pas de couple de reines sur la meme ligne, la meme
colonne, ou la meme diagonale
une question : est-il possible de placer ces huit reines sans violer de contrainte ?
Il faut donc commencer par reechir `a une fa con de modeliser les emplacement des reines.
8.2.1 Donnees
Premi`ere modelisation
On pourrait, navement prendre une matrice M de dimensions 8 8, et placer 0 dans une case sil ne sy trouve pas
de reine, 1 sil sen trouve une.
Premi`ere modelisation
Ou bien considerer huit couples de donnees qui contiendraient les coordonnees de la case sur laquelle serait placee
chaque reine. Ainsi, la i-`eme reine occupe la case (l
i
, c
i
)
Premi`ere modelisation
Ou plus simplement, puisquil ny a quune reine par ligne, un vecteur de 8 valeurs nous donnerait la colonne sur
laquelle serait placee chaque reine. c
i
est donc la colonne sur laquelle on a place la reine de la ligne i.
Bref
Considerons comme crit`ere la place memoire occupee, il va de soi que ces solutions sont de qualite croissante. Nous
allons voir quelles le sont aussi quand il sagit de poser les contraintes.
51
8.2.2 Contraintes
La fa con dexprimer les contraintes depend de la fa con dont ont ete representees les donnees.
Premi`ere modelisation
toutes les reines sont placees :
8

i=1
8

j=1
m
ij
= 8
une reine par ligne : i {1, . . . , 8},
8

i=1
m
ij
= 1
une reine par colonne : j {1, . . . , 8},
8

j=1
m
ij
= 1
pas plus dune reine par diagonale : p {2, . . . , 16},

i+j=p
m
ij
1 et p {7, . . . , 7},

ij=p
m
ij
1.
complique, non?
Deuxi`eme modelisation
toutes les reines sont placees : rien `a faire
une reine par ligne : i {1, . . . , 8}, j {1, . . . , 8} tel que i = j, l
i
= l
j
une reine par colonne : i {1, . . . , 8}, j {1, . . . , 8} tel que i = j, c
i
= c
j
pas plus dune reine par diagonale : i {1, . . . , 8}, j {1, . . . , 8} tel que i = j, |c
i
c
j
| = |l
i
l
j
|
Cest plus simple, non?
Troisi`eme modelisation
toutes les reines sont placees : rien `a faire
une reine par ligne : rien `a faire
une reine par colonne : i {1, . . . , 8}, j {1, . . . , 8} tel que i = j, c
i
= c
j
pas plus dune reine par diagonale : i {1, . . . , 8}, j {1, . . . , 8} tel que u = j, |i j| = |c
i
c
j
|
Encore plus simple.
Bref
Vous remarquez que ces mod`eles sont aussi de qualite croissante si on prend comme crit`ere la simplicite de lex-
pression des contraintes.
8.2.3 Question
La question est `a chaque fois la meme : quelles valeurs donner aux variables pour ne violer aucune contrainte ?
Mais le nombre de jeux de valeurs `a donner aux variables nest pas le meme `a chaque fois.
1. 2
64
possibilites, ce qui est de loin superieur au nombre datomes dans lunivers...
2. (8
2
)
8
possibilites, cest dej` a mieux, ca fait ((2
3
)
2
)
8
= 2
48
combinaisons possibles.
3. 8
8
possibilites, `a savoir (2
3
)
8
= 2
24
combinaisons, ce qui represente seulement quelques millions de possibilites...
Parmi les modelisations proposees, la derni`ere est donc la meilleure sur tous les plans. Seul inconvenient pour le
moment, on ne voit pas comment resoudre ce probl`eme sans enumerer toutes les possibilites... Nous repondrons `a cette
question dans les cours suivants.
8.3 Sensibilisation `a la complexite
8.3.1 Le tour de la table
Vous vous attablez deux fois par jour avec votre petite famille de seulement 8 personnes pour manger. Il vous vient
lidee de changer de place `a chaque repas de sorte que lon ait jamais deux fois la meme conguration (i.e. toutes les
52
personnes `a la meme place). Combien de temps vous faudra-t-il pour vous attabler suivant toutes les congurations
possibles ?
8.3.2 De la terre `a la Lune
Vous disposez dune feuille de papier dun dixi`eme de millim`etre depaisseur. Vous decidez de la plier plusieurs
fois sur elle-meme (tant que cest possible). A votre avis, est-il possible de faire 10 pliages, o` u votre feuille aura-t-elle
la meme epaisseur que le Petit Robert ? Pourrez-vous eectuer 30 pliages, ou lepaisseur de votre feuille sera-t-elle
comparable `a la taille dune terrain de football ? Et en supposant que vous soyez capable de la plier 50 fois sur
elle-meme, `a combien de fois la distance de la terre `a la Lune lepaisseur de cette feuille sera-t-elle egale ?
8.3.3 En bref
Lorsque vous cherchez des solutions `a des probl`emes combinatoires, bannissez dentree de jeu toute methode basee
sur une exploration exhaustive de lensemble des solutions.
8.4 Terminologie
8.4.1 Diculte
Nous allons passer en revue dans la section suivante quelques probl`emes classiques doptimisation combinatoire.
Nous les classerons en deux categories
Les probl`emes faciles : cest-`a-dire ceux qui se resolvent en temps polynomial, autrement dit sans avoir `a
explorer lintegralite des solutions.
Les probl`emes diciles : cest-`a-dire ceux quon ne peut resoudre quen explorant toutes les solutions. On dit
que ces probl`emes sont NP-Complets.
La denition ci-dessus est tr`es shematique, tenez-vous en `a celle-ci pour le moment, un cours sera ulterieurement
consacre `a letude des probl`emes NP-Complets.
8.4.2 Rappels de theorie des graphes
La plupart des probl`emes exposes ci-apr`es sont des probl`emes de theorie des graphes. Un graphe G est un couple
(S, A) o` u S est lensemble des sommets (ou noeuds) et A lensemble des aretes (ou arcs). Nous ne verrons que des
exemples dans lesquels lensemble S est ni, sachant quil peut contenir nimporte quoi (des entiers, des reels, des
couples de matrices, ds sous-ensembles de IR, des graphes, etc.). Lensemble A par contre ne peut contenir que des
couples (si le graphe est oriente, des paires si le graphe nes pas oriente) delements de S. Par exemple, G = (S, A)
avec
S = {(1, 2), (2, 3), (1, 3), (4, 5), (5, 4)}
et
A = {((1, 2), (2, 3)), ((1, 2), (1, 3)), ((4, 5), (5, 4)), ((5, 4), (4, 5)), ((1, 3), (1, 3)), ((2, 3), (1, 2))}
est un graphe (oriente en locurrence). Si un graphe est oriente, on ne dit plus sommets mais noeuds, et on ne dit plus
aretes mais arcs.
Les graphes sont quelquefois values, cest-`a-dire quil existe une application de A dans un sous-ensemble de IR. Ils
sont quelquefois ponderes, cest-`a-dire quil existe une application de S dans un sous-ensemble de IR.
8.4.3 Denition dun probl`eme
La plupart des probl`emes suivants sont denis en deux temps :
des donnees
une question
Les questions permettent de classer les probl`emes en plusieurs categories :
les probl`emes de decision : questions de la forme existe-t-il..., la reponse est oui ou non.
les probl`emes de satisfaction de contraintes : questions de la forme trouver une solution veriant.... La
reponse doit juste satisfaire des contraintes.
53
les probl`emes doptimisation : questions sous la forme trouver ... minimal (ou maximal) tel que.... La reponse
doit satisfaire des contraintes et etre optimale.
8.4.4 Probl`emes doptimisation
Dans un probl`eme doptimisation, la valeur que lon cherche `a maximiser, ou `a minimiser, sappelle la fonction
objectif. Une solution dun probl`eme doptimisation est dite
realisable si elle ne viole aucune contrainte.
optimale si elle est la meilleure des solutions realisables.
Notez quil peut y avoir plusieurs solutions optimales. Tout comme il peut ne pas y avoir de solution realisable,
dans ce cas le probl`eme doptimisation na pas de solution.
8.5 Probl`emeth`eque
8.5.1 Arbre couvrant de poids minimal
Soit G = (S, A) un graphe non oriente muni dune valuation des aretes c, T = (S
T
, S
A
) est un arbre couvrant G si
T est un arbre
S
T
= S
T est connexe
Le poids de T est

aAT
c(a)
Le probl`eme de larbre couvrant de poids minimal est le suivant :
donnees : un graphe G, une valuation c
question : trouver larbre T de plus petit poids parmi les arbres couvrant G.
Ce probl`eme (doptimisation) est facile, les deux algorithmes les plus connus sont ceux de Primm et de Kruskall.
8.5.2 Ensemble stable maximal
Soit G = (S, A) un graphe non oriente muni dune ponderation p un sous-ensemble K de S est un ensemble stable
si
a = (e, e

) A, e K ou e

K
Le poids de cet ensemble stable est

sK
p(s)
Le probl`eme de lensemble stable maximal est deni comme suit :
donnees : un graphe G, une ponderation p
question : trouver le sous-ensemble K de poids maximal parmi les ensembles stables de G.
Ce probl`eme est NP-Complet dans le cas general, polynomial si le graphe est un arbre ou est biparti
8.5.3 Circuit eulerien
Etant donne un graphe G oriente ou non, un circuit eulerien dans G est un circuit passant par une et une seule
fois par chaque arete de G. Le probl`eme est le suivant :
donnees : un graphe G
question : trouver un circuit eulerien dans G.
Ce probl`eme est polynomial, il se resoud avec un algorithme inspire par les travaux dEuler sur les graphes.
54
8.5.4 Circuit hamiltonien
Soit G un graphe (oriente ou non), un circuit hamiltonien dans G est un circuit passant par une et une seule fois
par chaque sommet de G. Le probl`eme du circuit hamiltonien est le suivant :
donnees : un graphe G
question : trouver un circuit hamiltonien dans G.
Ce probl`eme est NP-Complet.
8.5.5 Voyageur de commerce
Soit G un graphe (oriente ou non) value par une fonction c, le poids dune chemin (ou dun circuit) K la somme,
pour toute arete a de K, des c(a).
donnees : un graphe G
question : trouver un circuit hamiltonien de poids minimal dans G.
Ce probl`eme est NP-Complet.
8.5.6 SAT
Soit une expression booleenne `a n variables sous forme clausale (conjonction de disjonctions), par exemple,
(x
1
x
3
x
2
) (x
2
) (x
1
x
3
) (x
3
) (x
1
x
2
x
3
x
4
)
Les clauses (contenant des disjonctions) sont notees
{C
1
, c
2
, . . . , c
k
}
Toute clause est formee de k
i
litteraux
C
i
= l
i
1
, l
i
2
, . . . , l
i
ki
chaque litteral l est soit une variable (l = x
j
), soit la negation dune variable (l =x
j
). Une aectation A des variables
est une application de {x
1
, . . . , x
n
} dans {true, false}.
Si A(x
j
) = true, alors l est satisfait si l = x
j
, non satisfait sinon
si A(x
j
) = false, alors l
j
est satisfait si l = x
j
, non satisfait si l = x
j
Une clause est satisfaite si au moins un des litteraux qui la forment est satisfait. Une expression sous forme clausale
est satisfaite si toutes les clauses sont satisfaites. Le probl`eme est le suivant :
donnees : n variables, k clauses de chacune k
i
litteraux, chacun correspondant `a une variable ou `a la negation
dune variable.
question : trouver une aectation qui satisfasse toutes les clauses (donc au moins un litteral par clause)
Ce probl`eme (de satisfaction de contraintes) est NP-Complet dans le cas general, et facile si les clauses contiennent au
plus 2 litteraux.. Remarquons que si la question avait ete existe-t-il une aectation qui satisfasse toutes les clauses ?,
ce probl`eme serait un probl`eme de decision.
8.5.7 Couverture
Soit G = (S, A) un graphe non oriente muni dune ponderation p un sous-ensemble K de S est une couverture si
a = (e, e

) A, e K ou e

K
Le poids de cette couverture est

sK
p(s)
Le probl`eme de la couverture minimale est deni comme suit :
donnees : un graphe G, une ponderation p
question : trouver le sous-ensemble K de poids minimal parmi les couvertures de G.
Ce probl`eme est NP-Complet dans le cas general, polynomial si le graphe est un arbre ou est biparti.
55
8.5.8 Coloration
Soit G = (S, A) un graphe non oriente, une k-coloration c de g est une application de S dans un ensemble E tel
que |E| = k veriant
(e, e

) A, c(e) = c(e

)
Le probl`eme de la k-coloration est deni comme suit :
donnees : un graphe G
question : trouver une k-coloration de G.
Ce probl`eme est NP-Complet.
Le nombre chromatique
G
dun graphe est la plus petite coloration de ce graphe. Autrement dit,

G
= min{k|G est k colorable}
donnees : un graphe G
question : trouver le nombre chromatique de G.
Ce probl`eme est aussi NP-Complet.
8.5.9 Plus court chemin
Soit g un graphe oriente (ou non) muni dune valuation de aretes c. Un chemin C de longueur p dans G est un
p-uplet (c
1
, . . . , c
p
) delements de A tel que si c
i
= (s
i
, t
i
), alors pour tout i {1, . . . , p1}, t
i
= s
i+1
. C est un chemin
de u S `a v S si s
1
= u et t
p
= v.
Le probl`eme du plus court chemin dans un graphe value se denit comme suit :
donnees : un graphe G value, deux sommets u et v
question : trouver le plus court chemin de u `a v dans G.
Ce probl`eme est polynomial, Les deux algorithmes les plus connus sont
Dijkstra : tr`es rapide, O(|S| +|A|) dans le pire des cas, mais ne fonctionne quavec les valuations positives, ne
necessite pas le parcours de tout le graphe.
Bellman : un peu moins rapide, il presente lavantage de fonctionner avec des valuations negatives, sauf si le
graphe contient un circuit absorbant (i.e. negatif).
8.5.10 Sac `a dos
Etant donne un ensemble A = {a
1
, . . . , a
n
}, des poids positifs{p
i
|i {1, . . . , n}}, des valeurs positives {v
i
|i
{1, . . . , n}}, et une constante positive K. Une solution realisable est un sous-ensemble I de {1, . . . , n} tel que

iI
p
i
K,
la valeur de la fonction objectif est

iI
v
i
. Le probl`eme du sac `a dos est le suivant :
donnees : un ensemble A muni de deux valuations {p
i
|i {1, . . . , n}} et {v
i
|i {1, . . . , n}}, et une constante
K > 0
question : trouver le sous ensemble B de A maximisant

iI
v
i
sous la contrainte

iI
p
i
K.
Ce probl`eme est NP-Complet.
8.6 Exercices
Exercice 1 - Digicode
Vous souhaitez craker un digicode, vous devez pour cela trouver un code de k chires, le digicode en comportant
n.
1. Combien de chires seront, dans le pire des cas, saisies sur le clavier si vous decidez denumerer tous les codes
les uns `a la suite des autres, et suivant un ordre lexicographique ?
2. Si vous decidez dentremeler les codes les uns dans les autres, donnez un minorant de la meilleure methode
envisageable.
56
3. Modelisez ce probl`eme comme un probl`eme de recherche dun circuit hamiltonnien dans un graphe oriente. La
resolution est-elle facile ?
4. Modelisez ce probl`eme comme un probl`eme de recherche dun circuit eulerien dans un graphe, le probl`eme est-il
facile ?
Exercice 2 - Rattrapages
Un ensemble E = {e
1
, . . . , e
n
} doivent passer des sessions de rattrapages dans les mati`eres M = {m
1
, . . . , m
k
}.
Vous disposez dun ensemble de couples C = (c
1
, . . . , c
j
) tel c
i
= (e, m) signie que letudiant e doit repasser la mati`ere
m. Nous souhaitons organiser les rattrapages en aectant chaque epreuve `a un jour. Plusieurs epreuves puissent se
derouler le meme jour tant quun meme candidat na pas deux ratrappages `a eectuer le meme jour. Nous souhaitons
minimiser le nombre de jours que dureront les rattrapages.
1. Comment modeliser le probl`eme de la fa con la plus simple possible ?
2. Est-il polynomial ?
Exercice 3 - Gardiens de prison
Une prison est contituee de couloirs qui sintersectent en de multiples points. Le directeur souhaiterait, avec un
minimum de gardiens, surveiller les couloirs. il faudrait pour cela, placer les gardiens aux intersections des couloirs de
sorte que chaque couloir soit visible par au moins un gardien. Comment modeliser ce probl`eme en theorie des graphes ?
Exercice 4 - le savant fou en voyage
Un chimiste souhaite transporter les produits A, B, C, D, E, dans des valises. Les couples de produits suivants ne
doivent en aucun cas etre transportes dans la meme valise :
A et C
A et D
C et D
A et B
B et D
A et E
E et C
Le but est de repartir les produits dans un minimum de valises.
1. Ramenez-vous `a un probl`eme classique de theorie des graphes. Dessinez le graphe.
2. Ce probl`eme est-il NP-Complet ?
3. Proposez une solution realisable `a trois valises pour ce probl`eme.
Exercice 5 - ensemble stable et k-coloration
Soit G = (S, A) un graphe, k une constante strictement positive. On sinteresse `a la k-colorabilite du graphe G (i.e.
peut-on colorier le graphe G avec k couleurs ?). Nous allons creer un graphe G

= (S

, A

) `a partir de G en procedant
de la fa con suivante :
A chaque sommet s de G, on associe k sommets de G

, notes {(s, 1), . . . , (s, k)}, tous relies entre eux par des
aretes.
Pour chaque arete {e, e

} de G, et chaque couleur j, on relie dans G

les sommets (e, j) et (e

, j). Notez bien que


comme les sommets sont des couples, les aretes sont des paires de couples.
Plus formellement,

= {(s, j)|s S, j {1, . . . , k}}


est un ensemble de couples (sommet de G/couleur).

= A
1
A
2
57
avec
A
1
= {{(s, j), (s, j

)}|s S, 1 j < j

k}
un ensemble daretes formant |S| sous-graphes complets de k sommets et
A
2
= {{(e, j), (e

, j)}|{e, e

} A, j {1, . . . , k}}
un ensemble daretes interconnectant ces sous-graphes.
Le but de cet exercice est de montrer quen trouvant un ensemble stable de |S| sommets dans G

, on trouve aussi
une k-coloration de G.
1. Soit G le graphe de lexercice precedent, on pose k = 3. Representez graphiquement G

.
2. Donnez une denition en fran cais (avec des mots) de ce quest un ensemble stable.
3. Ce probl`eme (existe-t-il un ensemble stable de |S| sommets dans G

?) est-il NP-Complet ?
4. Donnez un ensemble stable de 5 sommets dans ce graphe.
5. Utilisez cet ensemble stable pour determiner une 3-coloration de G.
6. Demontrez de fa con formelle et avec le plus de rigueur possible que, etant donne un graphe G arbitraire, un
nombre k > 0, G est k-colorable si et seulement sil existe un ensemble stable de |S| sommets dans G

.
Exercice 6 - Ordonnancement
En votre qualite de manager, vous vous retrouvez confronte au probl`eme suivant : vous avez un ensemble de t aches
`a eectuer, chacune delle ayant un temps dexecution connu `a lavance et une date de n souhaitee. De plus, il existe
pour chaque t ache une date avant laquelle il nest pas possible de commencer son execution. Votre equipe ne peut pas
travailler sur deux t aches dierentes en meme temps et il nest pas possible de fractionner ou dinterrompre lexecution
dune t ache. Si lexecution dune t ache nest pas achevee avant la date de n souhaitee, on dit de cette t ache quelle
est en retard. Votre objectif est de determiner un calendrier dexecution des t aches de sorte `a minimiser la somme des
retards. Voici les projets `a realiser en septembre :
numero nom execution au plus t ot duree deadline
1 changer la plomberie 1 1 6
2 debugger le projet A 2 3 4
3 nettoyer la voiture du PDG 1 1 6
4 installer le progiciel B 8 2 23
5 creer la base de donnee pour C 1 5 12
6 coder une interface graphique pour C 10 5 15
7 preparer le planning doctobre 17 2 19
Par exemple, linstalla-
tion du progiciel B prend 2 jours consecutifs, elle ne peut pas commencer avant le 8 septembre, et doit se terminer au
plus tard le 23 septembre. Il possible de commencer le 8 et de terminer le 9 tout comme il est possible de commencer
le 22 et de terminer le 23.
1. Donnez une solution realisable pour ce probl`eme. Vous presenterez la solution sous forme dun tableau, chaque
t ache occupera une ligne et celles-ci seront disposees dans lordre de leur execution. Vous utiliserez quatre colonnes
le nom de la t ache
la date de debut
le temps dexecution
la date de n dexecution
2. Formalisons le probl`eme.
Donnees : un nombre n de t aches, un ensemble de durees {d
1
, . . . , d
n
}, un ensemble de dates de debut
dexecution au plus t ot {r
1
, . . . , r
n
}, un ensemble de dates de n dexecution au plus tard {f
1
, . . . , f
n
}, une
constante M.
Question : Existe-t-il un ordre dexecution des t aches tel que la somme cumulee des retards nexc`ede pas M ?
Nous appelerons ce probl`eme SCHEDULING. Soient {s
1
, . . . , s
n
} les dates de debut dexecution de chacune des
t ache. Soient {t
1
, . . . , t
n
} les dates de n dexecution. Donnez une relation simple entre t
i
, s
i
et d
i
. Prenez bien
soin de verier que cette relation est veriee dans lexemple de la question precedente.
3. Lexecution de la t ache i ne peut pas commencer avant la date r
i
. Exprimez cette contrainte avec les notations
des questions precedentes.
58
4. Deux t aches dindices respectifs i et j ne peuvent pas se superposer, exprimez cette contrainte `a laide dune
proposition portant sur s
i
, s
j
, t
i
et t
j
.
5. Combien y a-t-il de contraintes de cette forme ? Vous justierez votre reponse en denombrant les couples (i, j)
tels que 1 i < j n.
6. Nous notons max(a, b) la plus grande des deux valeurs a et b. A quoi correspond la valeur max(0, t
i
f
i
) ?
7. Nous choisissons comme fonction objectif la somme cumulee des retards. Exprimez cette fonction objectif `a partir
des t
i
et des f
i
8. Exprimez la condition la somme cumulee des retards nexc`ede pas M avec les notations de la question
precedente
Exercice 7 - Sac-`a-dos
Nous souhaitons resoudre le probl`eme du sac ` a dos par enumeration exhaustive des solutions, cest `a dire comme des
boeufs. Nous representerons une solution s (realisable ou non) par la liste chanee des indices des objets selectionnes
dans s. Nous representerons une instance i par deux tableaux p (poids des objets) et v (valeurs des objets). Une
solution sera la liste chanee des indices des objets places dans le sac. Ecrivez les corps des sous-programmes suivants :
1. void* linkedListCopy(void* l). Copie les maillons de la liste chanee l, mais pas les valeurs pointees par les
maillons. Vous utiliserez linkedListMap.
2. Ecrivez le sous-programme void knapSackPrintSolution(linkedList* l), ache la liste des indices formant
la solution l, vous utiliserez linkedListApply.
3. Ecrivez un sous-programme linkedList* parties(linkedList* l), ce sous-programme prend en param`etre
un ensemble represente par une liste chanee et retourne une liste chanee dans laquelle chaque maillon est une
liste chanee contenant une partie de l. Vous utiliserez linkedListApply.
4. void knapSackPrintParties(linkedList* l), ache toutes les parties de l, vous utiliserez linkedListApply.
5. void knapSackDestroyParties(linkedList* l) detruit l et les listes chanees pointees par chaque maillon de
cette liste.
Nous representerons une instance du probl`eme sac `a dos avec une variable du type :
typedef struct
{
/
nombre t o t a l d ob j e t s
/
long nbItems ;
/
t ab l e au de nombreObj et s el ement s cont enant l e poi ds de
chaque el ement
/
long wei ght s ;
/
t ab l e au de nombreObj et s el ement s cont enant l a val eur de
chaque el ement
/
long val ue s ;
/
Poi ds maximum qu i l e s t p o s s i b l e de pl ac e r dans l e sac ` a dos .
/
long maxWeight ;
}knapSack ;
59
Ecrivez les corps des sous-programmes suivants :
1. knapSack* knapSackMake(long nbItems, long maxWeight), alloue la memoire pour contenir linstance ainsi
que les deux tableaux.
2. void knapSackSetItem(knapSack* k, long index, long value, long weight), xe les poids (weight) et
valeur (value) de lobjet dindice i de linstance k.
3. long knapSackValue(knapSack* instance, linkedList* solution), retourne la somme des valeurs des ob-
jets de instance dont les indices sont dans la liste solution. Vous utiliserez la fonction linkedListApply.
4. long knapSackWeight(knapSack* instance, linkedList* solution), retourne le poids de la solution solution
relative `a linstance instance. Vous procederez de la meme fa con que dans la question precedente.
5. int knapSackIsFeasible(knapSack* instance, linkedList* solution), retourne vrai si est seulement si la
solution solution relative `a linstance instance est realisable.
6. void knapSackPrintInstance(knapSack* k), ache la liste des poids des des valeurs de tous les objets de
linstance k. Par exemple,
(i = 0, v = 1, w = 1)
(i = 1, v = 2, w = 2)
(i = 2, v = 9, w = 7)
(i = 3, v = 8, w = 2)
(i = 4, v = 5, w = 7)
(i = 5, v = 6, w = 6)
(i = 6, v = 7, w = 7)
(i = 7, v = 4, w = 2)
(i = 8, v = 3, w = 7)
(i = 9, v = 10, w = 2)
(i = 10, v = 1, w = 1)
(i = 11, v = 2, w = 2)
(i = 12, v = 9, w = 7)
(i = 13, v = 8, w = 2)
(i = 14, v = 5, w = 7)
(i = 15, v = 6, w = 6)
(i = 16, v = 7, w = 7)
(i = 17, v = 4, w = 2)
(i = 18, v = 3, w = 7)
(i = 19, v = 10, w = 2)
(i = 20, v = 1, w = 1)
7. void knapSackDestroy(knapSack* k), vous avez vraiment besoin que je vous donne des indications ?
8. linkedList* knapSackListInit(long n), retourne une liste chanee contenant les elements {1, . . . , n}. Vous
limplementerez de fa con recursive.
9. linkedList* knapSackBruteForceSolve(knapSack* k) retourne la liste chanee contenant la liste des indices
des objets formant la solution optimale du probl`eme k.
10. Jusqu`a quelle valeur de n parvenez-vous `a resoudre le probl`eme ?
11. Montrez que le temps dexecution est proportionnel au nombre de maillons crees, toutes listes confondues.
12. Evaluez le nombre de maillons en fonction de n, donnez la complexite de la resolution de knapsack par enumeration
de toutes les solutions.
13. Est-ce que cela vous explique pourquoi lexecution est si longue ?
60
Chapitre 9
Programmation lineaire
9.1 Exemple
Nous disposons de 500 kilos de mati`ere premi`ere M
A
, et de 600 kilos de mati`ere premi`ere M
B
. Pour fabriquer un
exemplaire de produit P
1
il faut 10 kilos de M
A
et 20 kilos de M
B
, pour fabriquer un exemplaire de produit P
2
il faut
20 kilos de M
A
et 10 kilos de M
B
. La vente dun exemplaire de P
1
rapporte 10 euros, celle dune exemplaire de P
2
rapporte 12 euros. Soit x
1
le nombre de produits P
1
fabriques x
2
le nombre de produits P
2
fabriques. Comment xer
x
1
et x
2
pour maximiser les beneces ?
Ce probl`eme se modelise et se note de la fa con suivante :
_

_
max 10x
1
+ 12x
2
s.c. 10x
1
+ 20x
2
500
20x
1
+ 10x
2
600
x
1
, x
2
0
9.2 Algorithme du simplexe en bref
Le but de ce cours nest pas de vous apprendre comment on resoud les programmes lineaires, mais comment on
les modelise. Ces probl`emes se resolvent, en pratique, en temps polynomial. Un des algorithmes les plus connus est
lalgorithme du simplexe. Je nexpliquerai ici que le principe, pour plus de details, voir [5]. Les contraintes peuvent
etre representees par des demi-plans. Lensemble des solutions realisables est lintersection de ces demi-plans, cette
intersection forme un polygone convexe. Soit z un reel, lensemble des couples (x, y) tel que la fonction objectif prend
la valeur z est une droite d
z
.
En Augmentant la valeur de z, on deplace d
z
. On cherche donc la plus grande valeur de z telle quau moins
un point de d
z
se trouve dans lensemble des solutions realisables. Il se trouve qu`a loptimum, la droite d
z
passe par
un des sommets du polygone des solutions realisables. Lalgorithme du simplexe parcours les sommets de ce polygone
jusqu` a atteindre cet optimum. Cette methode se generalise facilement `a un nombre de variables et de contraintes
arbitraires.
9.3 Modeliser un programme lineaire
Un programme lineaire `a n variables et `a m contraintes est de la forme suivante :
_

_
max c
1
x
1
+ . . . + c
i
x
i
+ . . . + c
n
x
n
s.c. a
11
x
1
+ . . . + a
1i
x
i
+ . . . + a
1n
x
n
b
1
.
.
.
.
.
.
.
.
.
.
.
.
a
j1
x
1
+ . . . + a
ji
x
i
+ . . . + a
jn
x
n
b
j
.
.
.
.
.
.
.
.
.
.
.
.
a
m1
x
1
+ . . . + a
mi
x
i
+ . . . + a
mn
x
n
b
m
61
Soient x le vecteur `a n lignes et 1 colonne
_

_
x
1
.
.
.
x
n
_

_
c le vecteur `a n lignes et 1 colonne
_

_
c
1
.
.
.
c
n
_

_
Alors on exprime la valeur de la fonction objectif avec le produit scalaire c
t
x. Soit A la matrice `a m lignes et n
colonnes
_
_
_
_
_
_
_
_
a
11
. . . a
1i
. . . a
1n
.
.
.
.
.
.
.
.
.
a
j1
. . . a
ji
. . . a
jn
.
.
.
.
.
.
.
.
.
a
m1
. . . a
mi
. . . a
mn
_
_
_
_
_
_
_
_
et b le vecteur `a m lignes et 1 colonne
_

_
b
1
.
.
.
b
m
_

_
Alors les contraintes secrivent
Ax b
Finalement, un programme lineaire est de la forme
_
max c
t
x
s.c. Ax b
Exercice 1 - Probl`eme de transport
Une entreprise de fabrication de mort aux rat dispose de n points de fabrication, produisant p
i
(1 i n) tonnes
par jour. Il faut acheminer dans m points de vente les quantites d
j
(1 j m). On a bien s ur
n

i=1
p
i

m

j=1
d
j
Le co ut dacheminement de 1 tonne de mort au rat du point de fabrication i au point de vente j est donne par c(i, j).
Comment faire pour satisfaire la demande de chaque point de vente tout minimisant le co ut total dacheminement ?
Modelisez ce probl`eme par un programme lineaire.
Exercice 2 - Minimiser le nombre de transactions
m personnes partent en vacances et paient de fa con anarchique pendant leur sejour. A leur retour, ils font les
comptes et le charge des comptes dessine un graphe oriente G = (S, A) muni dune valuation c o` u
chaque element de S est une personne
chaque couple (i, j) A signie la personne i doit c(i, j) euros `a la personne j
Representez le graphe correspondant aux donnes suivantes :
1. A doit 147 euros `a C
62
2. B doit 57 euros `a A
3. E doit 228 euros `a B
4. B doit 129 euros `a D
5. D doit 78 euros `a A
6. C doit 45 euros `a B
7. B soit 187 euros `a E
On remarque que ce graphe contient des circuits, et que pour certains couples, de sommets, il existe plusieurs
chemins. Utiliser le graphe tel quil est pour planier les remboursements conduirait `a des remboursements redondants
(C donne `a B qui donne `a A qui donne `a C...). En reechissant, il remarque que peu importe qui rembourse qui, ce qui
compte, cest que chacun retrouve son argent. Pour simplier le probl`eme, il decompose donc S en deux sous-ensembles
S
+
(ceux `a qui on doit de largent quils nen doive) et S

(ceux qui doivent de largent plus quon leur en doit).


Chaque sommet s est etiquete par la valeur
|

t
+
(s)
c(s, t)

(s)
c(t, s)|
Quels sont les sommets et les etiquettes des sommets de ce nouveau graphe ? La question est de trouver comment
placer les aretes de la fa con la plus simple possible. Modelisez ce probl`eme comme un probl`eme de ot max. Nous
souhaitons maintenant minimiser le nombre de transaction. Est-ce possible avec un algorithme de ot maximum?
Nous verrons dans une autre section que ce probl`eme est NP-Complet.
Exercice 3 - Plaques dego ut
Une entreprise de fabrication de plaques dego uts dispose de n points de fabrication, produisant p
i
(1 i n)
plaques par jour. Il faut chaque jour acheminer dans m centres les quantites d
j
(1 j m). Toutes les distances sont
susament courtes pour que chaque trajet puisse etre fait par un seul camion dans une meme journee. La production
est faite telle que
n

i=1
p
i
=
m

j=1
d
j
Chaque camion `a une contenance K, le probl`eme est comment aecter chaque camion `a un centre de fabrication et
un centre de livraison pour utiliser un minimum de camions ? Montrez que ce probl`eme est le meme que le precedent.
Exercice 4 - Regression lineaire et ecart-absolu
Soit une serie statistique bivariee {(x
i
, y
i
)|i = 1, . . . , n}, une regression lineaire consiste en la recherche de la droite
passant au plus pr`es des points representes dans un rep`ere orthonorme `a deux dimensions.
Soit y = ax +b lequation de cette droite. Alors, on approxime y
i
avec la valeur ax
i
+b. Lecart absolu entre y
i
et
son approximation est |ax
i
+b y
i
|. Nous souhaitons minimiser la somme es ecarts absolus
n

i=1
|ax
i
+b y
i
|
Modelisez ce probl`eme comme un probl`eme de programmation lineaire.
9.4 GLPK
9.4.1 Quest-ce que cest ?
GLPK [6] est une librairie de resolution de programmes lineaires. Elle contient une implementation de lalgorithme
du simplexe. Il est possible de lancer GLPK en ligne de commande, ou bien dimporter la librairie dans un programme
C.
63
9.4.2 O` u le trouver ?
Utilisez urpmi ou apt-get.
9.4.3 La documentation
Le manuel de reference[7] est tr`es complet mais quelque peu dicile `a lire quand on nest pas habitue. Cette annexe
est aussi l`a pour vous vous aider `a le lire.
9.4.4 Les fonctions
Exemple
Nous allons illustrer le fonctionnement de GLPK en resolvant le probl`eme
_

_
max 10x
1
+ 12x
2
s.c. 10x
1
+ 20x
2
500
20x
1
+ 10x
2
600
x
1
, x
2
0
Le programme C ci-dessous modelise ce probl`eme et lenvoie dans glpk.
#include<s t di o . h>
#include gl pk . h
i nt main ( )
{
LPX l p = l px c r e a t e pr o b ( ) ;
double c o e f f s [ 4 +1 ] ;
i nt rows [ 4+1] , c o l s [ 4 +1 ] ;
l p x s e t o b j d i r ( l p , LPXMAX) ;
l px add r ows ( l p , 2 ) ;
l px s e t r ow bnds ( l p , 1 , LPX UP, 0 . 0 , 5 0 0 . 0 ) ;
l px s e t r ow bnds ( l p , 2 , LPX UP, 0 . 0 , 6 0 0 . 0 ) ;
l px a dd c o l s ( l p , 2 ) ;
l px s e t c o l bnds ( l p , 1 , LPX LO, 0 . 0 , 0 . 0 ) ;
l px s e t c o l bnds ( l p , 2 , LPX LO, 0 . 0 , 0 . 0 ) ;
l p x s e t o b j c o e f ( l p , 1 , 1 0 . ) ;
l p x s e t o b j c o e f ( l p , 2 , 1 2 . ) ;
c o e f f s [ 1 ] = 10 ; rows [ 1 ] = 1 ; c o l s [ 1 ] = 1 ;
c o e f f s [ 2 ] = 20 ; rows [ 2 ] = 1 ; c o l s [ 2 ] = 2 ;
c o e f f s [ 3 ] = 20 ; rows [ 3 ] = 2 ; c o l s [ 3 ] = 1 ;
c o e f f s [ 4 ] = 10 ; rows [ 4 ] = 2 ; c o l s [ 4 ] = 2 ;
l px l oad mat r i x ( l p , 4 , rows , c ol s , c o e f f s ) ;
l px s i mpl e x ( l p ) ;
pr i nt f ( val e ur de l a f o nc t i o n o b j e t i f : %l f \n , l px g e t o bj v a l ( l p ) ) ;
pr i nt f ( quant i t e de pr odui t s A : %l f \n , l px g e t c o l pr i m ( l p , 1 ) ) ;
pr i nt f ( quant i t e de pr odui t s B : %l f \n , l px g e t c o l pr i m ( l p , 2 ) ) ;
l px de l e t e pr o b ( l p ) ;
return 1 ;
}
Noubliez pas de compiler vos sources avec loption -lglpk (sinon, ca marche pas).
Importation
Avant toute chose, noubliez pas
#include gl pk . h
64
Creation, suppression
GLPK met `a votre disposition le type LPX, une variable de ce type est un programme lineaire. On cree un programme
lineaire avec la fonction lpx create prob(), on le detruit avec lpx delete prob(LPX*).
Nombre de variables et de contraintes
Les programmes lineaires sont usuellement representes par des tableaux :
_

_
max c
1
x
1
+ . . . + c
i
x
i
+ . . . + c
n
x
n
s.c. a
11
x
1
+ . . . + a
1i
x
i
+ . . . + a
1n
x
n
b
1
.
.
.
.
.
.
.
.
.
.
.
.
a
j1
x
1
+ . . . + a
ji
x
i
+ . . . + a
jn
x
n
b
j
.
.
.
.
.
.
.
.
.
.
.
.
a
m1
x
1
+ . . . + a
mi
x
i
+ . . . + a
mn
x
n
b
m
Vous remarquez que ce programme `a n variables et `a m contraintes est forme dun grand tableau, `a n+1 colonnes,
et `a m+ 1 lignes. Dans la terminologie de GLPK,
Une variable est une colonne (col)
Une contrainte est une ligne (row)
La fonction lpx add rows(LPX*, int) specie le nombre de contraintes, lpx add cols(LPX*, int) specie le
nombre de variables.
La fonction objectif
Soyez tr`es atentifs : les indices sous GLPK commen cent `a 1. La fonction lpx set obj coef(LPX*, int
numeroDeLigne, double coefficient) permet de preciser la valeur dun coecient de la fonction objectif. Par
exemple, pour aecter la valeur 3.0 `a c
2
dans le programme mylp, on utilise linstruction lpx set obj coef(mylp,
2, 3.0). Selon le contexte, on cherche `a minimiser ou `a maximiser la fonction objectif, on le precise avec la fonction
lpx set obj dir(LPX*, int direction). Il existe deux directions : LPX MIN et LPX MAX.
Le deuxi`eme membre de linegalite
Il nest sujet dans cette section que du membre de droite des inegalites formant les contraintes, nous verrons
dans une partie ulterieure comment denir le membre de gauche de chaque contrainte. Il existe plusieurs formes de
contraintes, par exemple,
a
j1
x
1
+. . . +a
ji
x
i
+. . . +a
jn
b
j
Cette forme se note LPX UP (upper). Une contrainte de la forme
a
j1
x
1
+. . . +a
ji
x
i
+. . . +a
jn
x
n
b
j
se note LPX LOW (lower). Pour dautres formes, reportez-vous `a la documentation. On specie la forme dune
contrainte avec la fonction lpx set row bnds(LPX*, int indiceLigne, int forme, double borneInf, double borneSup).
Par exemple, la forme de la contrainte
a
41
x
1
+. . . +a
4i
x
i
+. . . +a
4n
x
n
67
se specie avec linstruction lpx set row bnds(mylp, 4, LPX UP, 0.0, 67.0). La forme de la contrainte
a
41
x
1
+. . . +a
4i
x
i
+. . . +a
4n
x
n
67
se specie avec linstruction lpx set row bnds(mylp, 4, LPX LO, 67.0, 0.0). Notez que certains param`etres
sont ignores, le quatri`eme si la contrainte est de la forme LPX UP, le cinqui`eme si la contrainte est de la forme LPX LO.
65
Les domaines des variables
Il est possible dajouter des contraintes sur les valeurs des variables. Par exemple, les contraintes suivantes
x
1
, x
2
0
font partie du programme lineaire donne en exemple. La fonction lpx set col bnds(LPX*, int indiceColonne,
int forme, double borneInf, double borneSup). Par exemple, si x est dindice 4, et quon tient `a lempecher de
prendre des valeurs negatives, on le specie avec linstruction lpx set col bnds(mylp, 4, LPX LO, 0.0, 0.0).
Les coecients des contraintes
Les coecients des contraintes sont tous initialises `a 0. Si vous tenez `a ce que certains prennent des valeurs non
nulles, vous devez le specier avec la fonction lpx load matrix(LPX*, int nbCoeffs, int* lignesDesCoefficients,
int* colonnesDesCoefficients, double* coefficients);. Cette fontion prend en param`etre la taille des trois ta-
bleaux lignesDesCoefficients, colonnesDesCoefficients et coefficients. Le i-`eme element de coefficients est le
coecient de la contrainte dindice colonnesDesCoefficients[i] et de la ligne dindice lignesDesCoefficients[i]. Par
exemple, pour specier lunique contrainte du programme lineaire
_
_
_
max x
1
+ x
2
s.c. 5x
1
+ 4x
2
3
x
1
, x
2
0
on initialise les tableaux de la sorte
c o e f f i c i e n t s [ 1 ] = 5 ;
l i g ne s De s Co e f f i c i e nt s [ 1 ] = 1 ;
c o l o nne s De s Co e f f i c i e nt s [ 1 ] = 1
c o e f f i c i e n t s [ 2 ] = 4 ;
l i g ne s De s Co e f f i c i e nt s [ 2 ] = 1 ;
c o l o nne s De s Co e f f i c i e nt s [ 2 ] = 2
Ensuite, il ny a plus qu`a invoquer
l px l oad mat r i x ( mylp , 2 , l i g ne s De s Co e f f i c i e nt s ,
c o l o nne s De s Coe f f i c i e nt s , c o e f f i c i e n t s ) ;
Lalgorithme du simplexe
lpx simplex(LPX*) execute lalgorithme du simplexe sur le probl`eme passe en param`etre. La fonction double
lpx get obj value(LPX*) retourne la valeur de la fonction objectif `a loptimum. double lpx get col primm(LPX*,
int indiceVariable) retourne la valeur de la indiceV ariable-`eme variable `a loptimum.
Exercice 5 - Prise en main de GLPK
Utilisez GLPK pour resoudre le programme lineaire :
_

_
max 4x
1
+ 6x
2
+ 2x
3
s.c. 3x
1
+ 7x
2
+ x
3
12
3
5
x
1
+ 3x
2
+
14
5
x
3
3
9x
1
+
9
100
x
2
+ 5x
3
6
x
1
, x
2
, x
3
0
Exercice 6 - Le plus beau metier du monde
Un enseignant a donne k notes de controle continu `a ses n el`eves, et une note de partiel pour chaque el`eve. On
note c
j
i
la note obtenue par le i-`eme el`eve au j-`eme controle continu, et p
i
la note de partiel du i-`eme el`eve. Il souhaite
determiner le jeu de coecients qui maximise la moyenne generale de la classe.
66
1. Comment resoudre ce probl`eme ? Utilisez GLPK pour resoudre linstance
double no t e s Pa r t i e l [ N] = {10 , 13 , 2 , 4 . 5 , 9 , 12 , 16 , 8 , 5 , 12};
double notesCC1 [ N] = {11 , 16 , 11 , 8 , 10 , 11 , 11 , 6 , 4 , 13};
double notesCC2 [ N] = { 9 , 18 , 7 , 8 , 11 , 3 , 13 , 10 , 7 , 19};
2. Que remarquez-vous ?
3. Le responsable pedagogique est en total desaccord, il consid`ere que la note de partiel doit avoir un coecient
au moins egal `a 0.5 et que deux notes de controle continu doivent avoir des coecients au moins egaux `a 0.1.
Comment tenir compte de ces contraintes ?
4. En raison dun petit nombre de notes tr`es elevees `a certains examens, la moyenne generale de la classe est bonne
malgre le fait que beaucoup del`eves ont une moyenne tr`es basse. Lenseignant decide donc de changer de crit`ere
et de maximiser la moyenne la plus basse. Comment proceder ?
5. Veriez la solution de la question precedente en calculant les moyennes de tous les el`eves avec les coecients
donnes par GLPK (ne le calculez pas `a la main, programmez-le...).
67
Chapitre 10
Theorie de la complexite
Certains probl`emes combinatoires sont dits NP-Complets, cela signie quil nest possible de les resoudre quen
passant par une recherche exhaustive dans lensemble des solutions, ce qui est concr`etement irrealisable. Le but de ce
cours est de vous montrer comment reconnatre quun probl`eme est NP-Complets, et comment le prouver.
Le chapitre de [2] sur la NP-Completude fournit un expose clair de la theorie de la complexite, mais utilisant des
concepts de calculabilite que je nutilise pas dans ce cours. La lecture de ce chapitre ne pourra cependant que vous
etre beneque. Louvrage [8] est la bible de la theorie de la complexite. Bien quil ne soit disponible quen anglais et
relativement dicile `a se procurer, la theorie y est expliquee de fa con claire, detaillee, et sans exc`es de formalisme.
10.1 Terminologie et rappels
10.1.1 Probl`emes de decision
Nous nous restreindrons aux probl`emes de decision dans le reste du cours. Un probl`eme de decision est specie
par
Des donnees
Une question
Par exemple,
Donnees : un graphe G, une constante k strictement positive
Question : G est-il k-colorable ?
10.1.2 Instances
Une instance dun probl`eme sobtient en precisant les valeurs des donnees. Par exemple,
Donnees : un graphe G complet dordre 10, k = 9
Question : G est-il k-colorable ?
On resout un probl`eme de decision et decidant, pour toute instance I, si cette instance est `a reponse oui ou `a
reponse non. On dit plus generalement quun algorithme qui resout un probl`eme de decision decide ce probl`eme, et
toutes les instances de ce probl`eme.
10.1.3 Algorithme polynomial
Un algorithme est polynomial si sa complexite est de lordre de O(n
k
) o` u n est la taille du probl`eme, et k une
constante independante de linstance consideree.
10.2 Les classes P et NP
La theorie de la complexite est basee sur une classication des dierents probl`emes. Deux classes sont importantes
`a connatre : P et NP.
68
10.2.1 La classe P
Un probl`eme appartient `a la classe de probl`emes P sil existe un algorithme polynomial permettant de le resoudre.
Par exemple, le plus court chemin, larbre couvrant dans un graphe, etc.
10.2.2 La classe NP
Etant donne un probl`eme de decision, ce probl`eme est dans NP sil est possible de verier une solution en temps
polynomial. Considerons par exemple le probl`eme suivant :
Donnees : un graphe G
Question : existe-t-il un cycle hamiltonien dans G?
Supposons que ce graphe contienne 100 sommets, et quun de vos camarade vous dise : cette instance est `a reponse
oui. Vous lui demanderez certainement : dans quel ordre parcourir les sommets pour former un cycle hamiltonien ?
Notez bien que malgre le fait que resoudre le probl`eme soit infaisable en pratique, verier quun chemin est eectivement
un chemin hamiltonien est tr`es aise. Un cycle permettant de verier en temps polynomial quune telle instance est une
instance `a reponse oui sappelle un certicat.
Plus generalement, etant donne une instance I dun probl`eme , un certicat c est une donnee permettant de
verier en temps polynomial que I est une instance de `a reponse oui.
10.2.3 Relations dinclusion
Tout probl`eme de P est aussi un probl`eme de NP. Ce qui secrit aussi
Theor`eme 10.2.1 P NP
Soit I une instance dun probl`eme appartenant `a P, alors il existe un algorithme polynomial permettant de
decider . De ce fait, si I est `a reponse oui, meme un certicat vide permet de le verier en temps polynomial.
La question suivante empeche la plupart des chercheurs en informatique de dormir : Est-ce que P = NP ? On sait
dej` a que P NP, pour repondre `a la question, il faudrait montrer :
NP P, autrement dit, tout probl`eme de NP peut etre resolu en temps polynomial.
NP \ P = , autrement dit, il existe des probl`emes de NP qui ne peuvent etre resolus en temps polynomial.
Notez que le probl`eme du cycle hamiltonien appartient `a NP.
Si P = NP, alors il existe un algorithme polynomial permettant de le decider.
Si P = NP, alors il convient de se demander si ce probl`eme nest pas dans NP \ P, le cas echeant il nexiste
aucun algorithme polynomial permettant de le decider.
Etant donne le nombre de probl`emes de NP pour lesquels on ne trouve aucun algorithme polynomial, il est fort
probable que P = NP. Notez bien que ceci nest quune conjecture, elle nest pas demontree `a ce jour.
10.3 Reductions polynomiales
Soit un probl`eme de NP pour lequel vous ne parvenez pas `a trouver dalgorithme polynomial, vous nous pouvez
pas dire que ce probl`eme nest pas dans P, car vous ne savez pas si NP \ P est vide ou non. Il va donc falloir proceder
autrement. Nous allons introduire la notion de diculte dun probl`eme, ainsi quun moyen de comparer des probl`emes.
10.3.1 Denition
Nous allons etablir une relation dordre sur les probl`emes, nous la noterons

ce qui signie est moins dicile que

. est denie comme suit


Denition 10.3.1

sil existe une fonction f de complexite polynomiale qui ` a toute instance I de associe
une instance I

de

telle que I est ` a reponse oui si et seulement si I

est ` a reponse oui.


69
10.3.2 Exemple
Montrons que le probl`eme HC (cycle hamiltonien) est moins dicile que TSP (voyageur de commerce). Pour cela,
construisons une fonction f prenant en param`etre une instance du probl`eme HC, et creant une instance I du probl`eme
TSP. Il est tr`es important de determiner f de sorte que I soit `a reponse oui si et seulement si f(I) est `a reponse
oui. Rappelons la denition de HC dans un graphe non oriente :
Donnees : un graphe G non oriente
Question : existe-t-il un cycle hamiltonien dans G?
Ainsi que la denition de TSP,
Donnees : un graphe G

non oriente muni dune valuation c, une constante K


Question : existe-t-il dans un G un cycle hamiltonien de longueur inferieure ou egale `a K?
Nous denissons f de la sorte, f prend en param`etre les donnees de HC, `a savoir le graphe G = (S, A), on denit
linstance f(I) de la sorte
G

= (S, A

), A

contient toutes les paires de sommets quil est possible de former avec les sommets de G.
Autrement dit, G

est un graphe complet.


c(e) = 1 si e A, c(e) = 2 si e A. Autrement dit, les aretes de A

ont la valeur 1 si elle se trouvaient dans A,


et toutes les aretes qui ont ete ajoutees pour obtenir un graphe complet ont la valeur 2.
K = |S|.
Il est maintenant necessaire de montrer que I est une instance `a reponse oui si et seulement si f(I) est une instance
`a reponse oui.
Soit I une instance de HC `a reponse oui. Alors il existe un cycle hamiltonien dans G. La longueur de ce cycle
dans G est |S|, `a savoir le nombre de sommets. La longueur de ce cycle est aussi |S| dans G

, car les aretes


empruntees dans G

etaient toutes de valuation 1.


Soit I une instance de HC telle que f(I) est `a reponse oui. Comme f(I) est `a reponse oui, alors il existe un
cycle hamiltonien de longueur K = |S|. Comme ce cycle passe par |S| aretes, et que toutes les aretes de G

sont
de valuation 1 ou 2, alors ce cycle nemprunte que des aretes de valuation 1. Comme les aretes de valuation 1 de
G

sont aussi des aretes de G, alors il existe un cycle hamiltonien dans G.


10.3.3 Application
Propriete 10.3.1 Si

et

P, alors P.
Soit I une instance de , comme

, alors il existe f polynomiale telle que I est `a reponse oui si et seulement si


f(I) est `a reponse oui. Comme

P, alors

est decide par un algorithme polynomial. En appliquant cet algorithme


`a f(I), on decide I. Lalgorithme quon obtient est donc
Determiner f(I) (polynomial)
Decider f(I) (polynomial)
Comme les deux algorithmes consideres sont polynomiaux, alors I est decide en temps polynomial. Donc P.
Il est important de retenir que

implique que lexistence dun algorithme polynomial decidant

implique
lexistence dun algorithme polynomial decidant .
10.4 Les probl`emes NP-complets
10.4.1 Courte meditation
Si vous vous trouvez face `a un probl`eme que vous ne parvenez pas `a decider `a laide dun algorithme polynomial,
il vous sut de montrer, par exemple, que TSP pour ne pas vous faire mepriser par vos superieurs. Supposons
quil existe un algorithme polynomial decidant , alors vous en deduiriez immediatement un algorithme decidant le
probl`eme TSP, qui tient tout le monde en echec... Vous montrerez de ce fait non pas que le probl`eme na pas de
solution, mais que ni vous, ni personne dautre (encore moins vos superieurs...), nest capable, pour le moment, de
trouver un algorithme polynomial pour le decider.
10.4.2 3-SAT
La question que nous sommes amenes `a nous poser maintenant est : existe-t-il un probl`eme de NP au moins aussi
dicile que tous les probl`emes de NP ? La reponse est oui.
70
Theor`eme 10.4.1 (Cook) Pour tout NP, 3 SAT
Le probl`eme SAT est deni dans la probl`emeth`eque. 3 SAT correspond au cas particulier dans lequel toutes les
clauses contiennent 3 litteraux. 3 SAT est plus dicile que tous les probl`emes de NP, cela signie que sil etait
possible de decider 3 SAT en temps polynomial, il serait alors possible de decider nimporte quel probl`eme de NP
en temps polynomial.
10.4.3 Consequences deprimantes
Propriete 10.4.1 Si

et

, alors

.
Soit I une instance de , comme

, alors il existe f polynomiale telle que I est `a reponse oui si et seulement


si f(I) est `a reponse oui. Comme

, alors il existe g polynomiale telle que f(I) est `a reponse oui si et seulement
si (g f)(I) est `a reponse oui. Donc la reduction (g f) est polynomiale et I est `a reponse oui si et seulement si
(g f)(I) est `a reponse oui.
Denition 10.4.1 est NP-Complet si pour tout probl`eme

NP, on a


Autrement dit, est NP-Complet sil est plus dicile que nimporte quel probl`eme de NP.
Propriete 10.4.2 Si 3 SAT , alors est NP-Complet.
Pour tout

NP,

3 SAT et 3 SAT , donc

. Alors pour tout

NP,

, donc est
NP-Complet.
Propriete 10.4.3 Si est NP-Complet, et

, alors

est NP-Complet.
Si est NP-Complet, alors pour tout probl`eme

NP,

. Comme de plus

, alors pour tout


probl`eme

NP,

. Donc

est NP-Complet.
Si vous voulez montrer quun probl`eme est NP-Complet, il sut de montrer quil est plus dicile quun probl`eme
dej` a connu comme etant NP-Complet.
10.4.4 Un espoir vain
Propriete 10.4.4 Si et

sont NP-Complets, et quil est possible de decider en temps polynomial, alors on peut
decider

en temps polynomial.
Comme

appartient `a NP, alors

3 SAT, et comme est NP-Complet, alors 3 SAT . Donc

.
Si P, alors

P.
Cette propriete est tr`es importante, elle signie que si on parvenait `a decider un seul probl`eme NP-Complet en
temps polynomial, alors on pourrait tous les decider en temps polynomial et on aurait P = NP.
Exercice 1 - 3-SAT/CLIQUE
3-SAT est deni de la fa con suivante :
Donnees : Un ensemble {C
j
|j = 1, . . . , p} de clauses, un ensemble {x
i
|i = 1, . . . , n} de variables. Chaque clause
C
j
contient 3 litteraux {l
1
j
, l
2
j
, l
3
j
} pouvant etre de la forme x
i
ou x
i
, ce que lon notera avec une egalite pour
simplier les notations.
Question : Existe-t-il une valuation des variables satisfaisant au moins un litteral de chaque clause ?
Une clique est un sous-graphe complet. La taille dune clique est le nombre de sommets quelle contient. On denit
le probl`eme CLIQUE de la fa con suivante :
Donnees : Une graphe G non oriente, une constante K > 0
Question : Existe-t-il dans G une clique de taille K?
Nous considerons la reduction suivante :
K = p
A chaque clause C
i
, on associe trois sommets s
1
j
, s
2
j
et s
3
j
.
Il existe une arete entre deux sommets s
i
j
et s
i

j
si
71
j = j

si l
j
i
= x, alors l
i

j
= x
3-SAT est connu pour etre NP-Complet, montrez que CLIQUE est NP-Complet.
Exercice 2 - K-COLORATION/ENSEMBLE STABLE
Soit G = (S, A) un graphe, k une constante strictement positive. On sinteresse `a la k-colorabilite du graphe G (i.e.
peut-on colorier le graphe G avec k couleurs ?). Nous allons creer un graphe G

= (S

, A

) `a partir de G en procedant
de la fa con suivante :
A chaque sommet s de G, on associe k sommets de G

, notes {(s, 1), . . . , (s, k)}, tous relies entre eux par des
aretes.
Pour chaque arete {e, e

} de G, et chaque couleur j, on relie dans G

les sommets (e, j) et (e

, j). Notez bien que


comme les sommets sont des couples, les aretes sont des paires de couples.
Plus formellement,

= {(s, j)|s S, j {1, . . . , k}}


est un ensemble de couples (sommet de G/couleur).

= A
1
A
2
avec
A
1
= {{(s, j), (s, j

)}|s S, 1 j < j

k}
un ensemble daretes formant |S| sous-graphes complets de k sommets et
A
2
= {{(e, j), (e

, j)}|{e, e

} A, j {1, . . . , k}}
un ensemble daretes reliant ces sous-graphes.
Demontrez de fa con formelle et avec le plus de rigueur possible que, etant donne un graphe G arbitraire, un nombre
k > 0, G est k-colorable si et seulement sil existe un ensemble stable de |S| sommets dans G

.
Exercice 3 - CLIQUE/ENSEMBLE STABLE
Montrez que ENSEMBLE STABLE est NP-Complet, vous tiendrez compte du fait que CLIQUE est NP-Complet.
Exercice 4 - ENSEMBLE STABLE/COUVERTURE
Montrez que COUVERTURE est NP-Complet, vous tiendrez compte du fait que ENSEMBLE STABLE est NP-
Complet.
Exercice 5 - 3-SAT/SUBSET SUM
Le probl`eme SUBSET SUM, est deni comme suit :
Donnees : un ensemble A = {p
i
|i {1, . . . , n}} de n valeurs, une constante K.
Question : existe-t-il un sous-ensemble I de {1, . . . , n} tel que

iI
p
i
= K?
On peut montrer par une reduction de 3SAT que SUBSETSUM est NP-Complet. Eectuons la transformation
suivante :
A chaque variable x
j
, on associe deux valeurs v
j
et v

j
dont la representation decimale comporte p +n chires.
Les p premiers chires representent les clauses. Le i-`eme chire ( {1, . . . , p}) de v
j
prend la valeur 1 si x
j
apparat dans C
i
, 0 sinon. Le i-`eme chire ( {1, . . . , p}) de v

j
prend la valeur 1 si x apparat dans C
i
, 0
sinon.
Les n derniers chires representent lindice de la variable x
i
, le p +j-`eme chire de v
j
et de v

j
prend la valeur
1, les n 1 autres chires prennent la valeur 0.
A chaque clause C
i
, on associe 2 valeurs x
i
et x

i
de n+p chires dont le i-`eme chire vaut 1 et tous les autres 0.
On prend comme nombre K la valeur dont les p premiers chires valent 3 et les n derniers 1.
Utilisez la reduction polynomiale ci-dessus pour montrer que SUBSET SUM est NP-Complet.
72
Exercice 6 - PARTITION/SUBSET SUM
Le probl`eme PARTITION est deni comme suit :
Donnees : un ensemble A = {p
i
|i {1, . . . , n}} de n valeurs, tel que

n
i=1
p
i
est pair.
Question : existe-t-il un sous-ensemble I de {1, . . . , n} tel que

iI
p
i
=
iI
p
i
Montrez que SUBSET SUM est NP-Complet, utilisez le fait que PARTITION est NP-Complet.
Exercice 7 - PARTITION/SAC A DOS
Montrez, par reduction du probl`eme PARTITION, que SAC A DOS est NP-Complet.
Exercice 8 - Ordonnancement
1. Montrez que SCHEDULING NP.
2. Etant donne le probl`eme PARTITION :
Donnees : Un ensemble de m valeurs {v
1
, . . . , v
m
}.
Question : Existe-t-il un sous-ensemble I de {1, . . . , m} tel que

iI
v
i
=

iI
v
i
Autrement dit, est-il possible de partitionner lensemble {v
1
, . . . , v
m
} en deux sous-ensembles dont la somme des
valeurs est egale ? Linstance de PARTITION suivante, m = 7, (v
1
, . . . , v
7
) = (1, 2, 3, 4, 5, 6, 7) est-elle `a reponse
oui ? Vous demontrerez la justesse de votre reponse.
3. Nous savons que PARTITION est NP-Complet. Nous allons montrer `a laide dune reduction polynomiale f, que
PARTITION SCHEDULING. Nous construisons une fonction f qui `a toute instance de PARTITION associe
une instance de SCHEDULING denie comme suit :
n = m+ 1
pour tout i {1, . . . , m}, d
i
= v
i
, r
i
= 1, f
i
=

n
j=1
v
j
+ 1
d
n
= 1, r
n
=
1
2

n
j=1
v
j
+ 1, f
n
=
1
2

n
j=1
v
j
+ 1
M = 0
Determiner limage de linstance (1, 2, 3, 4, 5, 6, 7) par la fonction f. Vous presenterez votre solution sous forme
dun tableau, vous preciserez les valeurs de toutes les donnees du probl`eme.
4. Limage de cette instance est-elle `a reponse oui ? Vous demontrerez la justesse de votre reponse en donnant
les valeurs de debut dexecution si cest le cas, ou bien une preuve dimpossibilite dans le cas contraire.
5. Montrez, sans exc`es de formalisme, que f est polynomiale.
6. Montrer que toute instance de PARTITION `a reponse oui a une image par f `a reponse oui.
7. Montrer que toute instance de PARTITION dont limage est ` a reponse oui est `a reponse oui.
8. SCHEDULING est-il NP-Complet ? Justiez votre reponse.
73
Chapitre 11
Introduction la cryptographie
11.1 Denitions
Chirer une information revient `a la transformer de sorte quelle ne puisse etre intelligible que par la personne `a
qui elle est destinee. La cryptologie est un terme generique regroupant deux disciplines :
La cryptographie, qui est letude des methodes de chirement et de dechirement.
La cryptanalyse, qui est lart de casser des messages chires. Autrement dit, la cryptanalyse est letude des
techniques qui permettent `a une personne non autorisee de decrypter (ce mot semploie uniquement dans ce
contexte) des messages chires.
La cryptographie permet aussi de signer et dauthentier des documents. En signant un document, on permet au
destinaire de verier la provenance du document, et lauthentication permet de verier que ce document na pas ete
altere.
Vous prendrez garde `a ne pas confondre chirement et codage. Coder revient `a remplacer chaque symbole (ou
suite de symboles) par un(e) autre. Cela peut servir en cryptographie, mais la reciproque est fausse.
Un chire est la donnee dun algorithme de chirement (et/ou de signature) et de lalgorithme de dechirement
(et/ou de verication et dauthentication). On utilise aussi le mot protocole, ou encore algorithme.
Nous appellerons tiers non autorise toute personne `a qui le message chire nest pas destine et qui pourrait,
pour des raisons qui lui appartiennent, etre tentee de le lire.
Un canal non securise est un moyen de transmission de linformation dont la s urete nest pas garantie, cest-`a-dire
sur lequel il est aise pour un tiers non autorises dintercepter les messages. Les protocole de chirement trouve tout
leur interet lorsque lon doit faire transiter par un canal non securise des informations condentielles.
Un message, avant le chirement est appele message clair ou encore message en clair. Une fois chire, on
lappelle message chire. Lorsquil a ete dechire (a priori par son destinataire), on lappelle message dechire.
11.2 La steganographie
La steganographie est lart de dissimuler des messages, par exemple en utilisant les bits de poids faible dune
image au format bmp [9], ou encore en pla cant des informations dans le slack [10]. La steganographie nest pas considere
comme de la cryptographie, car le message doit pouvoir tomber entre les mains dun tiers non autorisee
sans que celui-ci puisse le lire. Ce crit`ere nest evidemment pas satisfait par la steganographie, bien que celle-ci
ait eu son heure de gloire pendant lantiquite.
11.3 Les chires symetriques sans cle
Un chire symetrique sans cle se compose dune fonction f qui a tout message clair M associe un message f(M).
Le message se dechire avec une fonction f
1
. Par exemple, le chire de Cesar,qui consiste `a remplacer toute lettre
par celle qui se trouve trois positions plus loin dans lalphabet. Cette methode resistera aux attaques un certain temps,
mais une fois la fonction f decouverte, il est trivial de determiner f
1
, et toute la methode est `a jeter `a la poubelle. Un
74
deuxi`eme crit`ere devant etre satisfait est que meme si des personnes non autorisees connaissent lalgorithme
chirement, elle ne doivent pas etre capable de dechirer un message chire.
Exercice 1 - Chirement par transposition
Chirer un message par transposition revient appliquer un algorithme de permutation des lettres.
1. Est-il aise de cryptanalyser un message chire de la sorte ?
2. Considerez-vous quil sagit dun moyen de chirement s ur ?
Exercice 2 - La barri`ere de la langue
Pendant la deuxi`eme guerre mondiale, les americains ont utilise pour communiquer par radio la langue des indiens
Navajos, tr`es complexe et ne ressemblant `a aucune autre pour communiquer rapidement et s urement sans que les
japonais ne puisse comprendre les conversations. Quen pensez-vous ?
11.4 Les chires symetriques `a cle
On cherche une methode de chirement telle que meme si le secret de lalgorithme nest pas susament bien tenu,
cela naura pas de consequences sur sa abilite. Un algorithme symetrique `a cle est une fonction f qui `a tout message
clair M et `a toute cle K associe un message chire C = f(M, K). On dechire le message en utilisant la meme cle (ou
une cle facile `a trouver `a partir de la premi`ere), f
1
(C, K) nous donne le message dechire. Cela signie que meme
en connaissant f, un tiers non autorise ne pourra pas dechirer C sans K. Si K est decouverte, il sut de changer de
cle, et il sera alors possible dutiliser le meme algorithme.
11.4.1 Le chire de Vigen`ere
La methode de Vigen`ere est la plus connue.
Un message M est compose de nombres representant des rangs de lettres dans lalphabet
Une cle K est composee de n nombres k
1
k
2
. . . k
n
.
On decoupe M en blocs de n nombres m
1
m
2
. . . m
n
A chaque bloc, on associe un bloc chire c
1
c
2
. . . c
n
avec c
i
= (m
i
+k
i
)mod26
Si n = 10, alors il existe 26
10
possibilites, ce qui permet de bannir dentre de jeu toutes les methodes basees
sur une enumeration de toutes les cles. Soit p le nombre de lettres chirees avec la cle K que vous avez `a votre
disposition, memes si ces lettres proviennent de messages dierents. Si le ratio
p
n
, est eleve, alors vous pouvez tenter
de cryptanalyser les messages avec des methodes statistiques [11].
11.4.2 Enigma
Enigma est une machine `a chirer utilisee par larmee allemande pendant la deuxi`eme guerre mondiale. Elle se
presentait comme une machine `a ecrire, mais ecrivait dautres lettres que celles qui etaient saisies. Un syst`eme de rotors
qui pivotaient `a chaque pression de touche changeait la cle au fur et `a mesure que lon avan cait dans lecriture du
message. Cela ressemblait `a un code de Vigen`ere dont la cle est aussi longue que le message, et comme les allemands
changeaient de cle chaque semaine, cela rendait irrealiste toute cryptanalyse basee sur une analyse des frequences. La
cle utilisee etait une disposition des rotors et une position initiale, ce qui faisait que meme si une machine enigma
(lalgorithme) tombait entre les mains dun ennemi de larmee allemande, celui-ci ne pouvait dechirer les messages
sans connatre la disposition des rotors (la cle). Enigma a donne beaucoup de l `a retordre aux allies, et etait considere
comme un moyen de chirement tr`es ecace.
11.5 Les algorithmes asymetriques
Mais quelque soit la abilite theorique dalgorithme symetrique `a cle, un gros probl`eme pratique se pose : que faire
si les cles tombent entre les mains dun tiers non autorise ?
75
11.5.1 Un peu dhistoire[1]
Les allemands etaient obliges de faire circuler les cles en centaines dexemplaires dans toute leurope, en garantir
la securite etait une t ache tr`es dicile. Et ce qui devait arriver arriva : des anglais sempar`erent de cles denigma sans
que les allemands le sachent. Comme ils disposaient de copies denigma depuis longtemps dej` a et que les allemands
ne se savaient pas ecoutes, ils purent tranquillement dechirer tous les messages allemands. Nombreux sont ceux qui
consid`erent que cela a ete decisif pour la victoire des allies.
11.5.2 Le principe
Mettre des cles en circulation et garantir leur securite est considere aujourdhui comme un t ache impossible.
Comment echanger des cles sans prendre le risque quun message soit decrype par un tiers non autorise ? Lidee de la
reponse est dutiliser deux cles : K
e
pour chirer et K
d
pour dechirer. Le destinataire du message est la seule personne
`a detenir K
d
, elle diuse K
e
librement. Un message M est chire avec une fonction f en un message C = f(M, K
e
).
Son destinataire dechire le message avec une fonction g telle que M = g(C, K
d
). Les deux fonctions f, g, et la cle
K
e
doivent pouvoir etre publiees et tomber entre les mains dun tiers non autorise sans quil puisse dechirer M.
Autrement dit, il doit etre dicile de trouver K
d
`a partir de f, g, K
e
et M.
On peut se representer ce type de protocole de la fa con suivante. Alice veut envoyer un message `a Bob. Bob lui
envoie une bote et un cadenas ouvert. Alice place le message dans la bote et verrouille le cadenas. Maintenant, seul
le detenteur de la cle du cadenas peut ouvrir la bote. Sil sagit de Bob, lui seul pourra recuperer le message, meme
Alice ne pourra pas le faire. Le principe le la cryptographie asymetrique est le meme :
K
e
est la cle publique et permet `a toute personne de chirer un message.
Seule la cle privee K
d
permet le dechirement du message.
Exercice 3 - SSH
Les chires `a cle publique sont tr`es gourmands en calculs, ils rendent inenvisageable le transfert de volumes importants
de donnees. Par contre les protocoles symetriques sont tr`es rapides en pratique. Comment conjuguer les deux pour
communiquer de fa con rapide et securisee `a travers un canal non securise.
76
Chapitre 12
GnuPG
12.1 Presentation
Gnu Privacy Guard[12] est un logiciel de chirement asymetrique et de gestion de cles. Lalgorithme utilise pour
signer et chirer est El Gamal, qui est dune abilite comparable `a celle dRSA.
Il sinstalle tr`es simplement avec urpmi. Il existe sous forme de plugin pour Thunderbird, et est donc muni dune
interface graphique. Nous lutiliserons dans ce cours en ligne de commande, rassurez-vous il y en a tr`es peu `a apprendre.
GNU Privacy Guard est, comme son nom lindique, sous licence GNU, vous pouvez donc en faire lusage que vous
voulez - y compris commercial - sans risquer de vous retrouver un jour au tribunal.
12.2 Utilisation
12.2.1 Generation dune cle privee
Avant toute utilisation du GPG, vous devez creer une cle privee. GPG vous la generera et la conservera en lieu
s ur... Pour generer votre cle privee, saisissez la commande :
gpg --gen-key
Plusieurs informations vous seront demandees, y compris un mot de passe pour deverouiller la cle privee, il est
imperatif que ce mot de passe soit robuste, sinon un tiers non autorise ayant un acc`es physique `a votre machine aurait
acc`es `a votre cle privee. Cette cle est stockee dans un repertoire de votre home, elle sera utilise `a chaque dechirement
et `a chaque signature.
12.2.2 Exportation de la cle publique
Si vous souhaitez recevoir des messages chires,vous devez donner votre cle publique `a vos correspondants. Pour
exporter votre cle publique dans un chier, saisissez la commande
gpg --export --armor --output nomdufichier
Loption --armor encode la cle dans un format achable et pouvant etre envoye par mail. Vous pouvez donner ce
cher `a qui vous voulez et meme le mettre sur votre page web, cette cle permet seulement de chirer des chiers, seule
votre cle privee permettra leur dechirement.
12.2.3 Importation
Si vous souhaitez envoyer des chiers chiree ` a un correspondant, vous aurez besoin de sa cle publique. Il lui sut
de vous lenvoyer dune fa con similaire `a celle dont vous lui aurez fourni votre cle publique. Une fois sa cle publique
entre vos mains, il ne vous reste plus qu`a saisir
77
gpg --import --armor nomdufichier
12.2.4 Liste des cles
La liste des cles publiques en votre possession sobtient en saisissant
gpg --list-keys
12.2.5 Chirement
Une fois que vous detenez la cle publique dun de vos correspondants, vous avez la possibilite de chirer des chiers
que lui seul pourra dechirer.
gpg --encrypt --recipient destinataire --output fichierChiffr e fichier`aChiffrer
destinataire est une sous-chaine permettant didentier la cle publique du destinataire du message chire,
fichierChiffr e est le nom du chier genere par cette commande, fichier`aChiffrer est, comme son nom lindique,
le nom du chier `a chirer.
12.2.6 Dechirement
Vous pouvez dechirer un chier chire avec votre cle publique en utilisant la commande
gpg --decrypt --output fichierD echiffr e fichierChiffr e
12.2.7 Signature
Les messages sont automatiquement signes avec votre cle privee lors du chirement. La signature est veriee lors
du dechirement, `a condition bien s ur, que le destinataire ait en sa possession la cle publique de lemetteur.
12.2.8 Bref
Ces notes netaient quun survol de GnuPG, pour plus dinformations, ou en vue dune utilisation professionnelle,
se referer `a [13].
Exercice 1 - Creation des cles
1. Installez GPG avec urpmi si vous etes sous linux, et debrouillez-vous si vous etes sous windaube.
2. Creez un couple de cles.
Exercice 2 - Echange de cles
1. Trouvez un binome
2. Exportez vos cles publiques et echangez-les par mail.
3. Documentez-vous sur loption fingerprint, expliquez quelle utilisation vous pourriez bien en faire.
Exercice 3 - Echange de messages
1. Placez dans des chiers texte des messages arbitraires
2. Chirez-les et echangez-les.
3. Dechirez les messages.
78
Exercice 4 - Elargissement de la toile de conance
Je designerai dorenavant votre binome par la lettre B.
1. Trouvez un trinome C (B devra aussi trouver un trinome D).
2. Recuperez la cle publique P
C
de C, vous prendrez soin de verier son authenticite avec son fingerprint
3. Chirez la cle publique P
B
de B et envoyez-la `a C.
4. C devra dechirer P
B
et envoyer sa cle publique chiree `a B.
5. B devra dechirer la cle publique de C et envoyer un message chire de conrmation `a vous et `a C.
79
Chapitre 13
GMP
13.1 Presentation
GMP[14] est un package darithmetique multi-precision, cest `a dire permettant de representer des entiers, des
rationnels et des ottants avec une precision arbitraire, et non pas celle preconisee par les normes de representation
des entiers et des ottants. Les algorithmes de cryptographie manipulent des nombres de plusieurs dizaines, voire
centaines de chires, ce qui necessite lutilisation dune telle biblioth`eque.
Vous pouvez linstaller tr`es simplement avec urpmi ou apt-get. Comme ce package est sous licence GNU, vous
pouvez en faire lutilisation que vous voulez. La documentation est disponible en anglais et vous donne la liste detaillee
des fonctions. Le but de ce document est juste de vous faire comprendre le fonctionnement du package en quelques
minutes.
13.2 Quelques points delicats
Le point le plus complexe est la gestion de la memoire, vous devez, en manipulant les fonctions de GMP.h, etre
tr`es attentifs aux valeurs que vous passez en param`etre.
13.2.1 Compilation
Nouliez pas dimporter gmp.h et dajouter loption de compilation -lgmp. Sinon ca marche pas.
13.2.2 Initialisation
Le type mpz t vous est fourni avec la librairie, meez-vous de labsence detoile, il y a necessairement des pointeurs
derri`ere ce type. Des fonctions prexees par mpz init vous permettent dinitialiser ces variables. Noubliez jamais
linitialisation, elle correspond `a lallocation dynamique, elle noubliez jamais la destruction, qui elle correspond `a la
liberation de la memoire.
mpz t i ; // de c l ar at i on
mpz i ni t ( i ) ; // al l oc at i o n
Les instructions ci-dessus declarent un entier multiprecision i et eectuent lallocation dynamique. La fonction
mpz init initialise i `a 0. Ne pas confondre initialisation et aectation. Un fois la variable initialisee, vous pouvez
lui aecter toutes les valeurs que vous voulez. Par contre ninitialisez pas une variable dej` a initialisee, vous devez
prealablement la detruire. On detruit un entier multiprecision (bref, on lib`ere la memoire) avec la fonction mpz clear.
mpz t i ; // de c l ar at i on
mpz i ni t ( i ) ; // al l oc at i o n
mpz s et ui ( i , 5000) ; // a f f e c t a t i o n
/
Ut i l i s a t i o n de i
80
/
mpz cl ear ( i ) ; // l i b e r a t i o n de l a memoire
13.2.3 Les fonctions
Vous remarquerez dans la documentation que presque toutes les fonctions de manipulation dentiers multiprecision
retounent void. Il est conseille avec ce type de variable de ne pas utiliser les valeurs de retour, mais dajouter un
param`etre pour y placer le resultat. Par exemple, pour multiplier un entier multiprecision par un long, on proc`ede de
la sorte :
// de c l ar at i ons
mpz t r e s ul t a t ;
mpz t operandeGauche ;
long operandeDroi te ;
EMPTY
// a l l o c a t i o n s
mpz i ni t ( r e s ul t a t ) ;
mpz i ni t ( operandeGauche ) ;
EMPTY
// a f f e c t a t i o n s
mpz s et ui ( operandeGauche , 1000) ;
operandeDroi te = 100;
EMPTY
// c al c u l
mpz mul si ( r e s ul t a t , operandeGauche , operandeDroi te ) ;
Les instructions ci-dessus eectue le calcul resultat = operandeGauche operandeDroite, soit resultat = 1000
100. Vous remarquez le resultat de la multiplication est le premier param`etre, et non pas la valeur de retour.
13.2.4 Achage
Pour acher ou ecrire dans un chier la valeur dun entier multiprecision, on utilise la fonction mpz out str (FILE
*stream, int base, mpz t op ). Si stream est egal `a NULL, la valeur est ecrite dans stdout.
mpz t val e ur ;
mpz i ni t ( val e ur ) ;
mpz s et ui ( val eur , 1 7 ) ;
mpz out s t r (NULL, 10 , val e ur ) ;
mpz cl ear ( val e ur ) ;
Les instructions ci-dessus achent 17.
13.2.5 Exemple
Voici un petit exemple avec quelques calculs sur des entiers multi-precision.
#include<gmp. h>
#include<s t di o . h>
/
Pl ace l a f a c t o r i e l l e de n dans r es . r es doi t e t r e i n i t i a l i s e
/
void f a c t o r i e l l e ( long n , mpz t r e s )
{
mpz t temp ;
i f ( n == 0)
81
{
mpz s et ui ( res , 1 ) ;
}
el se
{
mpz i ni t ( temp ) ;
f a c t o r i e l l e ( n1, temp ) ;
mpz mul si ( res , temp , n ) ;
mpz cl ear ( temp ) ;
}
}
/
Pl ace bn dans r es . r es doi t e t r e i n i t i a l i s e
/
void pui s s anc e ( long b , long n , mpz t r e s )
{
mpz t temp ;
i f ( n == 0)
{
mpz s et ui ( res , 1 ) ;
}
el se
{
mpz i ni t ( temp ) ;
pui s s anc e ( b , n1, temp ) ;
mpz mul ui ( res , temp , b ) ;
mpz cl ear ( temp ) ;
}
}
/
Af f i che l e s 100 premi eres pui s s ances de 10.
/
i nt main ( )
{
mpz t i ;
long i nd ;
mpz i ni t ( i ) ;
for ( i nd = 0 ; i nd <= 100 ; i nd++)
{
pui s s anc e ( 10 , i nd , i ) ;
mpz out s t r (NULL, 10 , i ) ;
pr i nt f ( \n ) ;
}
mpz cl ear ( i ) ;
return 0 ;
}
Et voici, pour vous eviter de vous prendre la tete, le makele.
al l : testGMP. c
gcc g lgmp testGMP. c
82
run : al l
. / a . out
13.2.6 Pour terminer
Etant donne le nombre de sous-programmes disponibles dans GMP, il serait inutile de les copier/coller ici. Je vous
laisse consulter la documentation [15]. Bon courage.
Exercice 1 - Prise en main
Ecrivez un programme qui ache la table de multiplication de 10
20
Exercice 2 - Fonction puissance
Reprennez la fonction puissance dans lannexe sur GMP et modiez-l`a en utilisant le fait que si n est pair alors,
b
n
= (b
2
)
n
2
Modiez la fonction puissance de sorte quelle prenne des entiers multiprecision en param`etre.
Exercice 3 - La fonction dAckermann
La fonction dAckermann , est denie comme suit :
(0, n) = n + 1
(m, 0) = (m1, 1)
(m, n) = (m1, (m, n 1))
Utilisez GMP pour calculer le plus de valeurs possibles de la suite dAckermann.
83
Chapitre 14
Arithmetique
Les bases mathematiques permettant la comprehension des algorithmes asymetriques sont exposees dans ce cours.
Vous trouverez un expose plus detaille dans [2]. Notez aussi que ce cours se recoupe avec le programme de spe maths
de terminale S.
Sauf mention explicite du contraire, tous les nombres consideres ici sont des entiers relatifs, cest-`a-dire des nombres
entiers pouvant etre positifs, negatifs ou nuls.
14.1 Divisibilite
Denition 14.1.1 a divise b, sil existe k tel que ak = b
a divise b se note a|b. On dit alors que a est un diviseur de b, et que b est un multiple de a.
Exercice 1
Prouvez, en utilisant la denition de la divisibilite, que
3|21
(3)|6
Exercice 2
Prouvez les proprietes suivantes :
1. Si a|b et b|a, alors |a| = |b|
2. Si a|b et b|c, alors a|c
3. Si a|b et a|c, alors a|(b +c)
4. Si a|b et a|c, alors a|bc
5. Si a|b, alors a
k
|b
k
pour tout entier naturel k.
14.2 Division euclidienne
Denition 14.2.1 Soient a un nombre relatif et b un entier strictement positif, on eectue la division a par b en
determinant q et r tels que a = qb +r, avec 0 r < q. q est le quotient, r le reste.
Exercice 3
Eectuez les divisions suivantes :
12 par 5
11 par 2
13 par 13
2 par 4
84
(6) par 2
0 par 3
(5) par 2
14.3 PGCD
Denition 14.3.1 Le plus grand commun diviseur de a et b, note pgcd(a, b) est le plus grand nombre qui divise ` a la
fois a et b.
Exercice 4
Completez le tableau suivant :
a b pgcd(a, b)
6 3
3 6
17 13
2
9
2
6
0 4
7 7
14.4 Nombres premiers
Denition 14.4.1 Un nombre p 2 est premier sil na que par 1 et p comme diviseurs positifs.
Par convention, 1 nest pas premier.
Exercice 5
Les nombres suivants sont-ils premiers ?
4
7
23
1
Exercice 6
Prouvez quil existe une innite de nombres premiers.
14.5 Nombres premiers entre eux
Denition 14.5.1 a et b sont premiers entre eux si pgcd(a, b) = 1
Autrement dit, a et b sont premiers entre eux sils nont aucun autre diviseur commun que 1.
Exercice 7
Les couples de nombres suivants sont-ils premiers entre eux ?
3 et 5
20 et 32
23 et 41
18 et 27
0 et 4
7 et 7
Existe-t-il des nombres premiers avec eux-memes ?
85
Exercice 8
Prouvez que deux nombres premiers distincts sont premiers entre eux.
Exercice 9
Soient a et b deux entiers relatifs, p = pgcd(a, b), a

=
a
p
et b

=
b
p
. Prouvez que a

et b

sont premiers entre eux.


14.6 Decomposition en produit de facteurs premiers
Propriete 14.6.1 Tout nombre entier positif x peut secrire comme un produit de nombres premiers. Cest-` a-dire
sous la forme
x = p
e1
1
p
e2
2
. . . p
ei
i
. . . p
en
n
o` u pour tout i {1, . . . , n}, p
i
est le i-`eme nombre premier et e
i
un nombre positif ou nul.
Tout nombre est deni de fa con unique par la suite (e
1
, e
2
, . . . , e
n
, 0, 0, . . .). Par exemple, quel nombre est deni
par la suite (1, 3, 0, 1, 2, 0, 0, . . .) ?
Exercice 10
Decomposez chacun de ces nombres en produit de facteurs premiers.
21
286
51
1344
Exercice 11
Donnez les nombres correspondant aux decompositions en facteurs premiers suivantes.
(0, 0, 1, 1, 0, . . . , 0, . . .)
(1, 1, 2, 0, . . . , 0, . . .)
(1, 0, 2, 0, 1, 0, . . . , 0, . . .)
(0, 0, 1, 0, . . . , 0, . . .)
(0, . . . , 0, . . .)
14.6.1 Application `a la divisibilite
Propriete 14.6.2 Soient
x = p
e1
1
p
e2
2
. . . p
ei
i
. . . p
en
n
et
y = p
f1
1
p
f2
2
. . . p
fi
i
. . . p
fn
n
x|y si et seulement si pour tout i, e
i
f
i
Exercice 12
Donnez la liste des diviseurs du nombre correspondant `a la decomposition en facteurs premiers suivante :
(1, 0, 1, 0, 1, 0, . . . , 0, . . .)
Exercice 13
Soient x = p
e1
1
p
e2
2
. . . p
ei
i
. . . p
en
n
et y = p
f1
1
p
f2
2
. . . p
fi
i
. . . p
fn
n
. Donnez la decomposition en facteurs premiers de xy.
86
14.6.2 Application au calcul du PGCD
Propriete 14.6.3 Soient
a = p
e1
1
p
e2
2
. . . p
ei
i
. . . p
en
n
et
b = p
f1
1
p
f2
2
. . . p
fi
i
. . . p
fn
n
alors
pgcd(a, b) = p
min(e1,f1)
1
p
min(e2,f2)
2
. . . p
min(ei,fi)
i
. . . p
min(en,fn)
n
Exercice 14
Calculez les PGCDs des couples de nombres dont les decompositions en facteurs premiers sont donnees :
(0, 0, 2, 1, 0, . . . , 0, . . .) et (0, 0, 1, 2, 0, . . . , 0, . . .)
(1, 1, 1, 0, . . . , 0, . . .) et (0, 2, 2, 2, 0, . . . , 0, . . .)
(1, 0, 1, 0, . . . , 0, . . .) et (0, 1, 0, 1, 0, . . . , 0, . . .)
(2, 2, 1, 1, 0, . . . , 0, . . .) et (0, 0, 1, 1, 0, . . . , 0, . . .)
Exercice 15
Soient x = p
e1
1
p
e2
2
. . . p
ei
i
. . . p
en
n
et y = p
f1
1
p
f2
2
. . . p
fi
i
. . . p
fn
n
. Determiner une condition necessaire et susante sur les
suites e et f permettant de savoir si x et y sont premiers entre eux.
14.7 Theor`eme de Bezout
Theor`eme 14.7.1 Pour tous a, b relatifs, il existe u et v relatifs tels que
au +bv = pgcd(a, b)
Theor`eme 14.7.2 a et b sont premiers entre eux si et seulement sil existe u et v relatifs tels que
au +bv = 1
14.7.1 Theor`eme de Gauss
Theor`eme 14.7.3 Si a et b sont premiers entre eux, et a|bc, alors a|c
14.8 Algorithme dEuclide
14.8.1 Algorithme dEuclide pour le PGCD
Propriete 14.8.1 Pour tous a et b relatifs,
pgcd(a, 0) = a
pgcd(a, b) = pgcd(b, a mod b)
Exercice 16
Appliquez lalgorithme dEuclide aux couples de nombres suivants :
3 et 6
4 et 0
161 et 184
21 et 34
87
Exercice 17
On admet que le pgcd(a, b) est la plus petite combinaison lineaire strictement positive de a et b.
1. Montrer que pgcd(a, b)|pgcd(b, a mod b)
2. Montrer que pgcd(b, a mod b)|pgcd(a, b)
3. Montrer que lalgorithme dEuclide se termine.
4. Soit F
n
la suite denie par
F
0
= 0
F
1
= 1
F
n
= F
n1
+F
n2
, si n 2
On appelle F
n
le n-i`eme nombre de Fibonacci. Montrez par recurrence que
F
n
=
1

5
(
n
+
n
)
avec
=
1 +

5
2
; =
1

5
2
;
F est-elle croissante ?
5. Prouvez que pout tout n 2,
F
n
mod F
n1
= F
n2
6. Prouvez par recurrence que
pgcd(F
n
, F
n1
) = 1
7. Prouvez par recurrence que le calcul de
pgcd(F
n
, F
n1
)
necessite n appels recursifs.
8. Prouvez par recurrence que si F
n
k et F
n1
k

, alors
pgcd(k, k

)
se calcule avec un nombre dappels recursifs inferieur ou egal `a n.
9. Prouvez que si k > k

, alors pgcd(k, k

) sexecute en O(log

(k))
10. Montrez que lhypoth`ese k > k

netait pas restrictive.


14.8.2 Algorithme dEuclide etendu
Il possible denrichir lalgorithme dEuclide an quil calcule les coecients u et b de la relation de Bezout.

Etant
donnes deux nombres a et b,
Si b = 0, alors pgcd(a, b) = a, et on a 1.a + 0.b = pgcd(a, b)
Par recurrence, appliquons la meme methode au couple (b, a mod b), alors on a u et v tels que
u.b +v.(a mod b) = pgcd(b, a mod b)
Soit
a
b
le quotient de la division de a par b, alors
a mod b = a
a
b
b
Donc
u.b +v.(a
a
b
b) = pgcd(b, a mod b)
Ce qui se reecrit
v.a + (u v
a
b
)b = pgcd(b, a mod b)
88
Comme, de plus,
pgcd(a, b) = pgcd(b, a mod b)
alors
v.a + (u v
a
b
)b = pgcd(a, b)
Donc, en posant u

= v et v

= u v
a
b
, on a bien
u

.a +v

.b = pgcd(a, b)
Exercice 18
Appliquez lalgorithme dEuclide etendu aux couples de nombres suivants. Lesquels sont premiers entre eux ?
3 et 6
4 et 0
161 et 184
21 et 34
Exercice 19
Ecrivez en C lalgorithme dEuclide etendu (passez u et v en param`etre par reference) sans GMP.
Exercice 20
Prouvez le theor`eme de Gauss
14.8.3 Morceaux choisis
Exercice 21 - Divisbilite
Prouvez que si a|b alors soit |a| |b|, soit b = 0.
Exercice 22 - Unicite de la division
Demontrer que le couple (q, r) resultant de la division de a et b est unique.
Exercice 23 - Divisibilite par 10
Combien y a-t-il de 0 `a la n de (1000!) ?
Exercice 24 - Combien y a-t-il de nombres premiers ?
1. Soit u
n
= p
1
p
2
. . . p
n
1 le produit des n > 1 plus petits nombres premiers auquel on a retranche 1, p
i
un des n
plus petits nombres premiers. Eectuez une division eulidienne de u
n
par p
i
.
2. Prouvez que u
n
nest divisible par aucun des n plus petits nombres premiers.
3. En deduire quil existe une innite de nombres premiers.
14.8.4 Applications avec GMP
Dans tous les exercices qui suivent, vous naurez droit quau type mpz t.
Exercice 25 - Algorithme dEuclide etendu
Programmez lalgorithme dEuclide etendu en achant une trace dexecution montrant les etapes du calcul de u
et v.
89
Exercice 26 - Experimentation avec la suite de Fibonacci
Ecrivez une fonction retournant le n-`eme nombre de Fibonacci en utilisant la relation de recurrence donnee dans
la section algorithme dEuclide. Que remarquez-vous lorsque lon calcule des valeurs de la suite de Fibonacci avec
de grandes valeurs de n (control-C pour interrompre lexecution dun programme :-) ? On consid`ere, pour remedier `a
ce petit probl`eme la fonction denie comme suit
(a, b, 0) = b
(a, b, n) = (a +b, a, n 1)
Prouvez par recurrence sur n que F
n+k
= (F
k+1
, F
k
, n), puis que F
n
= (1, 0, n). Utilisez cette relation pour modier
la fonction calculant le n-`eme nombre de Fibonacci. Tester lalgorithme dEuclide etendu avec des couples (F
n
, F
n1
)
(prenez de grandes valeurs de n).
90
Chapitre 15
Arithmetique modulaire
Les protocoles de chirement sont bases sur des operations dans des espaces quotient, detailles dans la derni`ere
partie de ce cours. Les denitions sont simpliees au minimum necessaire pour comprendre ce cours, et donc moins
precises que ce que vous pourriez trouver dans des ouvrages specialises.
La premi`ere section, sur les congruences, expose des points du programme de spe maths de terminale S, rediges
toutefois de fa con plus technique. Les deux sections suivantes abordent des elements du programme de premi`ere annee
de fac, ou de maths sup, seuls les points essentiels `a la comprehension de la derni`ere section du cours sont exposees,
jai pris la liberte de simplier quelques denitions. La derni`ere section expose des methodes utilisees directement en
cryptographie asymetrique, elles sont aussi enseignees en premi`ere annee de fac.
15.1 Congruences
Denition 15.1.1
a b (mod n)
si
n|(a b)
On dit alors que a est congru ` a b modulo n.
Autrement dit, a est b congru `a b modulo n si et seulement si a et b ont le meme reste de la division par n. Plus
formellement,
Propriete 15.1.1 a b (mod n) si et seulement si a mod n = b mod n.
En eet, si n|(a b), alors il existe k tel que kn = a b. Divisons a et b par n, il existe q, q

, r et r

tels que
a = qn +r et b = q

n + r

, avec 0 r < n et 0 r

< n. Donc kn = a b equivaut `a


kn = qn +r (q

n +r

)
ssi
kn = (q q

)n + (r r

)
ssi
n(k +q

q) = (r r

)
Donc
n|(r r

)
Or, |rr

| < n, donc n ne peut diviser (rr

) que si rr

= 0. On a donc r = r

, comme r = a mod n et r

= b mod n,
alors a mod n = b mod n.
Reciproquement, supposons a mod n = b mod n. Divisons a et b par n, il existe q, q

et r tels que a = qn + r
et b = q

n +r, avec 0 r < n. Donc


a b = qn +r (q

n +r)
91
ssi
a b = qn q

n
ssi
a b = (q q

)n
Donc, n|(a b).
Propriete 15.1.2 Si a b (mod n) et a

(mod n), alors


1. a +a

b +b

(mod n)
2. aa

bb

(mod n)
3. a
k
b
k
(mod n)
Exercice 1
Pour chacune de ces proprietes,
donnez un exemple numerique
donnez une preuve
Exercice 2
Calculez les valeurs suivantes :
73
3
mod 10; 4.7 mod 9; 14 + 71 mod 83; 4
4
mod 12;
3.9 7.8 mod 11; 247
349
mod 7; 2
1247
mod 17;
34
57
1 mod 11; 9518
42
4 mod 5
3
2n+1
+ 5
2n+1
mod 4; 6
n
+ 13
n+1
mod 7
15.2 Rappels dalg`ebre
15.2.1 Monodes
Denition 15.2.1 Un monode (E, +, 0) est un ensemble E muni dune addition + et dun element neutre 0 pour
cette addition.
Un element neutre 0 est tel que e E, e + 0 = 0 +e = e.
Par exemple, lensemble des entiers naturels, note N (ou (N, +, 0)), est un monode. En eet,
il est toujours possible dadditionner deux entiers naturels
et 0 est un element neutre pour laddition.
Lensemble (B, , 1) des booleens, muni du produit est aussi un monode. Il est en eet toujours possible de multiplier
deux booleens, et on a 0.1 = 0, 1.1 = 1, donc 1 (vrai) est un element neutre pour le produit booleen.
15.2.2 Groupes
Denition 15.2.2 (G, +, 0) est un groupe si
(G, +, 0) est un monode
pour tout element x de G, il existe un element x appele oppose de x, tel que
x + (x) = 0
Autrement dit, un groupe est un monode dans lequel il existe une soustraction. On remarque que N nest pas un
groupe mais que lensemble des entiers relatifs Z (ou (Z, +, 0)) est bien un groupe. En eet,
il est toujours possible dadditionner deux entiers relatifs
0 est bien un element neutre pour laddition.
pour tout x Z, x existe, ce qui nest pas le cas dans N.
92
15.2.3 Anneaux
Denition 15.2.3 (A, +, , 0, 1) est un anneau si
(A, +, 0) est un groupe
on peut toujours multiplier deux elements de A
il existe un element neutre 1 pour la multiplication
Par exemple, lensemble des entiers relatifs est un anneau, il sut de prendre 1 comme element neutre pour la
multiplication. Lensemble des matrices carrees est un anneau.
15.2.4 Corps
Denition 15.2.4 (C, +, , 0, 1) est un corps si
(G, +, , 0, 1) est un anneau
pour tout element x de C, sauf 0, il existe un element x
1
appele inverse de x, tel que
x (x
1
) = 1
Autrement dit, C est un corps sil est muni dune division. Par exemple, lensemble des entiers relatifs nest pas un
corps, mais lensemble des rationnels en est un. Lensemble des matrices inversibles est un corps.
Exercice 3
On consid`ere lensemble (F, +, , f
0
, f
1
) des fonctions lineaires (f(x) = ax + b) muni de laddition ((f + g)(x) =
f(x) +g(x)) et de la composition ((f g)(x) = f(g(x))).
Est-ce que (F, +, , f
0
, f
1
) est un monode ?
un groupe ?
un anneau?
un corps ?
existe-t-il un sous-ensemble de F formant un corps ?
Exercice 4
On consid`ere lensemble (P, +, , f
0
, f
1
) des polynomes `a coecients reels
P(x) =
n

i=1
a
i
x
i
+a
0
muni de laddition et de la composition
Est-ce que (P, +, , f
0
, f
1
) est un monode ?
un groupe ?
un anneau?
un corps ?
existe-t-il un sous-ensemble de P formant un corps ?
15.2.5 Relations dequivalence
Denition 15.2.5 Une relation sur E est une relation dequivalence si
1. est reexive, cest ` a dire e E, e e
2. est symetrique, cest ` a dire e, e

E, e e

e
3. est transitive, cest ` a dire e, e

, e

, e e

et e

e e

Par exemple, la relation = sur les reels est une relation dequivalence. Il se trouve que la relation sur les entiers
relatifs est une relation dequivalence, preuve en exercice.
93
Exercice 5
Etant donne un entier relatif non nul n. Pour tous a, b entiers relatifs, on pose a b si a b (mod n). Prouver
que est une relation dequivalence.
15.3 Espaces quotients
15.3.1 Classes dequivalence
Une relation dequivalence permet de repartir tous les elements dun ensemble dans des ensembles appeles classes
dequivalence. Deux elements a et b sont dans la meme classe si a b. Par exemple, si n = 5, on peut repartir tous
les relatifs dans 5 classes dequivalence selon le reste de leur division par 5. Par exemple,
c = {. . . , 13, 8, 3, 2, 7, 12, 17, . . .}
est une classe dequivalence, tous ses elements sont, deux `a deux, distants dun multiple de 5. Pour designer une classe
dequivalence, on utilise un element de cette classe, appele representant. En prenant 2 comme representant, on note
alors [2]
5
la classe des equivalents `a 2 modulo 5. On aurait pu aussi utiliser un autre element de c comme representant,
mais ce nest pas usuel, on prend en general un representant compris entre 0 et n 1.
Denition 15.3.1 Soit n > 0, et k {0, . . . , n 1}, alors on note [k]
n
= {e|e k}.
15.3.2 Z/nZ
Supposons quen calculant c = a + b mod n, on substitue `a a et `a b des elements de meme classe dequivalence,
alors le resultat est-il de la meme classe que c ? Verions : rempla cons a par a

[a]
n
et b par b

[b]
n
. Comme a a

et b b

, alors il existe k et k

tels que a

= a +kn et b

= b +k

n. Calculons
c

= a

+b

= a +kn +b +k

n
= a +b + (k +k

)n
= c + (k +k

)n
Donc c c

et c

[c]
n
. On deduit quil est possible detendre laddition modulaire aux classes dequivalences. Au lieu
dadditionner un element de [a]
n
`a un element de [b]
n
, nous additionnerons directement ces deux classes dequivalence.
Comme on remarque la meme chose en calculant c = ab mod n (en exercice), nous pouvons denir les calculs modulo
n sur lensemble densembles
{[0]
n
, . . . , [n 1]
n
}
Denition 15.3.2 Soit n > 0, alors on note Z/nZ lespace quotient {[k]
n
|0 k n 1}
Lorsquil ny a pas dambigute, on se permet denlever les crochets et de noter k au lieu de [k]
n
.
Exercice 6
Montrez quen substituant `a a et `a b des elements de meme classe dequivalence dans c = ab mod n, on obtient un
element de meme classe dequivalence que c.
Structure danneau
Propriete 15.3.1 Pour tout n > 0, Z/nZ est un monode.
Preuve en exercice.
Propriete 15.3.2 Pour tout n > 0, Z/nZ est un groupe.
Preuve en exercice.
Propriete 15.3.3 Pour tout n > 0, Z/nZ est un anneau.
Preuve en exercice.
94
15.4 Inverses modulaires
Supposons quil existe une fonction de chirement f denie comme suit, f(k) = k 7 mod 9. Calculons f(3)
3 7 29 0 (mod 9). Existe-t-il une fonction f

(k) = k p mod 9, inverse de f, telle que (f f

)(k) = k, en
particulier, existe-t-il p tel que 0 p mod 9 = 3 ?
On a multiplie [3]
9
par [7]
9
pour obtenir [0]
9
, peut-on revenir `a [3]
9
, cest-`a-dire multiplier [0]
9
par linverse, note
[7]
1
9
de [7]
9
? Plus generalement, cela revient `a se demander si Z/nZ est un corps. Cest-`a-dire, est-ce que la division
existe dans Z/nZ. Voici la reponse :
Theor`eme 15.4.1 Z/nZ est corps si et seulement si n est premier.
Supposons que Z/nZ est un corps, etant donne [k]
n
(k = 0), [k]
n
admet un inverse. Il existe donc une classe [k

]
n
telle que k.k

1 (mod n). Par denition, n|(k.k

1), et il existe tel que


n = k.k

1
ce qui secrit aussi comme une relation de Bezout,
k.k

n = 1
Or, k

et nexistent que si k et n sont premiers entre eux. Comme Z/nZ est un corps, alors pour tout k {1, . . . , n1},
k est premier avec n, donc aucun deux (sauf 1) ne peut diviser n, donc n est premier. La reciproque est basee sur le
meme principe.
15.4.1 Elements inversibles et fonction dEuler
On deduit de la preuve precedente que k est inversible dans Z/nZ si et seulement si k est premier avec n. Donc si
n nest pas premier, tous ses elements ne sont pas inversibles.
Denition 15.4.1 Pour tout n > 0, (n) est le nombre delements inversibles de Z/nZ.
Prenons par exemple Z/10Z, les elements inversibles de Z/10Z sont
{1, 3, 7, 9}
Notons quil sagit des elements premiers avec 10. Donc (10) = 4.
Exercice 7
Z/11Z est-il un corps ?
Quels sont les elements inversibles de Z/11Z et leurs inverses ?
Quelle est la valeur de (11) ?
Exercice 8
Z/14Z est-il un corps ?
Quels sont les elements inversibles de Z/14Z et leurs inverses ?
Quelle est la valeur de (14) ?
Notons que si n est premier, tous ses elements, sauf 0 sont inversibles, nous admettrons donc que
Propriete 15.4.1 Si n est premier, alors (n) = n 1.
Nous aurons besoin du resultat suivant pour RSA, admis sans preuve,
Propriete 15.4.2 Si p et q sont premiers, alors (pq) = (p 1)(q 1).
Par exemple, dans Z/35Z, il y a (5 1)(7 1) elements inversibles, donc (35) = 24.
95
15.4.2 Pratique de linversion
Comment, etant donne n > 0, et k Z/nZ, trouver linverse de k ? Si n est premier, le petit theor`eme de fermat
nous le donne :
Theor`eme 15.4.2 Si n est premier, alors pout tout k non congru ` a 0 modulo n,
k
n1
1 (mod n)
.
Par exemple, si n = 5 et k = 3, alors 3
4
81 1 (mod 5), donc 3
n2
3
3
27 2 (mod 5) est linverse
modulo 5 de 3. En eet, 3.2 1 (mod 5).
Si on connait (n) alors le theor`eme dAlembert-Gauss nous permet de trouver linverse de k,
Theor`eme 15.4.3 Pour tous n 2, k inversible dans Z/nZ,
k
(n)
1 (mod n)
.
Par exemple, si n = 10, et k = 3, alors (10) = (2.5) = 1.4 = 4, on a bien
3
4
9
2
81
1 (mod 10)
Si n = 21 et k = 4, alors (21) = (3.7) = 2.6 = 12, et on a bien
4
12
16
6
256
3
4
3
64
1 (mod 10)
Linverse modulo pq (p et q premiers) de k (inversible dans Z/pqZ) est donc k
(n)1
.
Exercice 9 - Espaces quotient et GMP
Ecrire avec GMP un sous-programme faisant le rapport complet dun espace quotient de la forme Z/nZ :
Z/nZ est-il un corps ?
Quels sont les elements inversibles de Z/nZ et leurs inverses ?
Quelle est la valeur de (n) ?
96
Chapitre 16
RSA
16.0.3 Principe
Le chirement se fait `a laide de la cle publique, le dechirement `a laide de la cle privee. [2]
Chirement
La cle publique est un couple (C, N) o` u
N = PQ est le produit de deux nombres premiers P et Q
C est un nombre premier avec (P 1)(Q1).
On chire un message M en calculant
M

M
C
(mod N)
Si par exemple on a P = 3, Q = 11, alors N = PQ = 33 et (P 1)(Q 1) = 2 10 = 20. Si par exemple on prend
C = 7, on remarque que 7 est bien premier avec 20, la cle publique est (7, 33). On chire le message M = 13 en
calculant M

M
C
13
7
7 (mod 33).
Dechirement
Notez quil nest pas trivial de retrouver M `a partir de M

et de (C, PQ). La cle privee est un couple (C

, N) tel que
pour tout message M,
(M
C
)
C

M (mod N)
Alors on dechire M

en calculant
M (M

)
C

(mod N)
Ici on a C

= 3. On constate que M 7
3
13 (mod 33). La question que lon est invite `a se poser est : comment on
trouve C

?
16.0.4 Resistance aux attaques
Dapr`es le theor`eme dEuler, pour tout M premier avec N,
M
(N)
1 (mod N)
Plus generalement, pour tout k entier relatif,
M
k(N)
1 (mod N)
Ce qui secrit aussi
M
k(N)
M M (mod N)
97
et de ce fait
M
k(N)+1
M (mod N)
Comme
M
CC

M (mod N)
il convient de determiner C

tel que
CC

= k(N) + 1
ce qui secrit plus simplement comme une relation de Bezout
CC

k(N) = 1
Notez que la connaissance de (N) est indispensable si on souhaite trouver C

. Etant donne N = PQ le produit de


nombres premiers P et Q, on a (N) = (P 1)(Q 1). Donc pour connatre (N), il est necessaire de connatre la
decomposition de N en produit de facteurs premiers. Donc, retrouver C

`a partir de C oblige le cryptanalyste `a passer


par une factorisation de N, probl`eme connu pour etre dicile.
98
Annexe A
Corriges des programmes
A.1 Fonctions recursives
#include<s t di o . h>
#include<s t d l i b . h>
i nt addi t i on ( i nt a , i nt b)
{
pr i nt f ( (%d , %d)\n , a , b ) ;
i f ( a == 0)
return b ;
i f ( a > 0)
return 1 + addi t i on ( a 1 , b ) ;
return addi t i on ( a + 1 , b) 1;
}
i nt s ous t r ac t i on ( i nt a , i nt b)
{
pr i nt f ( (%d , %d)\n , a , b ) ;
i f ( b == 0)
return a ;
i f ( b > 0)
return s ous t r ac t i on ( a , b 1) 1;
return s ous t r ac t i on ( a , b + 1) + 1;
}
i nt mul t i pl i c at i on ( i nt a , i nt b)
{
pr i nt f ( (%d , %d)\n , a , b ) ;
i f ( a == 0)
return 0;
i f ( a > 0)
return b + mul t i pl i c at i on ( a 1 , b ) ;
return mul t i pl i c at i on ( a + 1 , b) b ;
}
i nt di vi s i o n ( i nt a , i nt b)
{
pr i nt f ( (%d , %d)\n , a , b ) ;
i f ( a < 0)
return di vi s i on (a , b ) ;
i f ( b < 0)
return di vi s i on ( a , b ) ;
i f ( a < b)
return 0;
return 1 + d i vi s i o n ( a b , b ) ;
}
i nt pui ssance ( i nt a , i nt b)
{
pr i nt f ( (%d , %d)\n , a , b ) ;
i f ( b == 0)
return 1;
return a pui ssance ( a , b 1 ) ;
}
99
A.2 Fonctions recursives terminales
#include<s t di o . h>
#include<s t d l i b . h>
long f a c t o r i e l l e R ( long n , long acc )
{
pr i nt f ( (%l d , %l d )\n , n , acc ) ;
i f ( n == 0)
return acc ;
return f a c t o r i e l l e R (n1, acc n ) ;
}
long f a c t o r i e l l e ( long n)
{
return f a c t o r i e l l e R (n , 1) ;
}
i nt main ( )
{
long a = 4;
pr i nt f ( %l d ! = %l d \n , a , f a c t o r i e l l e ( a ) ) ;
getch ( ) ;
return 0;
}
100
A.3 Iterateurs et applications
#include<s t di o . h>
//
typedef struct
{
unsigned long f i r s t ;
unsigned long second ;
} coupl e ;
//
typedef struct
{
unsigned long 11 , 12 , 21 , 22 ;
} quadrupl et ;
//
coupl e applyF( coupl e ( f ) ( coupl e ) , i nt n , coupl e x)
{
i f ( n == 0)
return x ;
return f ( applyF( f , n 1 , x ) ) ;
}
//
coupl e applyFT( coupl e ( f ) ( coupl e ) , i nt n , coupl e x)
{
i f ( n == 0)
return x ;
return applyF( f , n1, f ( x ) ) ;
}
//
unsigned long mul t i pl i e ( unsigned long a , unsigned long b)
{
coupl e x = {0 , a };
coupl e f ( coupl e x)
{
coupl e y = {x . f i r s t + x . second , x . second };
return y ;
}
return applyFT( f , b , x ) . f i r s t ;
}
//
unsigned long f a c t o r i e l l e ( unsigned long n)
{
coupl e x = {n , 1};
coupl e f ( coupl e x)
{
coupl e y = {x . f i r s t 1 , x . f i r s t x . second };
return y ;
}
return applyFT( f , n , x ) . second ;
}
//
unsigned long pui ssance ( unsigned long b , unsigned long n)
{
coupl e x = {1 , b};
coupl e f ( coupl e x)
{
coupl e y = {x . f i r s t x . second , x . second };
return y ;
}
return applyFT( f , n , x ) . f i r s t ;
}
//
unsigned long f as t Pui s s anc e ( unsigned long b , unsigned long n)
{
i f ( n == 0)
101
return 1;
i f ( n % 2)
return b f as t Pui s s anc e ( bb , n/2) ;
return f as t Pui s s anc e ( bb , n /2) ;
}
//
unsigned long applyFD( i nt ( de l t a ) ( i nt k ) ,
unsigned long ( f ) ( coupl e ) , i nt n , unsigned long x)
{
coupl e y ;
i f ( n == 0)
return x ;
y . f i r s t = n ;
y . second = applyFD( del t a , f , de l t a ( n) , x ) ;
return f ( y ) ;
}
//
unsigned long sl owPui ssanceIT ( unsigned long b , unsigned long n)
{
unsigned long f ( coupl e x)
{
return x . secondb ;
}
i nt de l t a ( i nt x)
{
return x 1;
}
return applyFD( del t a , f , n , 1) ;
}
//
unsigned long f a c t o r i e l l e I T ( unsigned long n)
{
unsigned long f ( coupl e x)
{
return x . f i r s t x . second ;
}
i nt de l t a ( i nt x)
{
return x 1;
}
return applyFD( del t a , f , n , 1) ;
}
//
unsigned long f as t Pui s s ance I T( unsigned long b , unsigned long n)
{
unsigned long f ( coupl e x)
{
i f ( x . f i r s t % 2)
return bx . secondx . second ;
return x . secondx . second ;
}
i nt de l t a ( i nt x)
{
return x /2;
}
return applyFD( del t a , f , n , 1) ;
}
//
quadrupl et f i boMat ( )
{
quadrupl et q = {1 , 1 , 1 , 0};
return q ;
}
//
quadrupl et i d e nt i t e ( )
{
quadrupl et q = {1 , 0 , 0 , 1};
return q ;
}
102
//
quadrupl et multMat ( quadrupl et x , quadrupl et y)
{
quadrupl et xy ;
xy . 11 = x . 11 y . 11 + x . 12 y . 21 ;
xy . 21 = x . 21 y . 11 + x . 22 y . 21 ;
xy . 12 = x . 11 y . 12 + x . 12 y . 22 ;
xy . 22 = x . 21 y . 12 + x . 22 y . 22 ;
return xy ;
}
//
quadrupl et applyFDQ( unsigned long ( de l t a ) ( unsigned long ) ,
quadrupl et ( f ) ( unsigned long , quadrupl et ) ,
unsigned long n , quadrupl et x)
{
i f ( n == 0)
return x ;
return f ( n , applyFDQ( del t a , f , de l t a ( n) , x ) ) ;
}
//
quadrupl et matPow( quadrupl et x , unsigned long n)
{
quadrupl et f ( unsigned long m, quadrupl et q)
{
quadrupl et qPrime = multMat ( q , q ) ;
i f (m % 2)
return multMat ( x , qPrime ) ;
return qPrime ;
}
unsigned long de l t a ( unsigned long x)
{
return x /2;
}
return applyFDQ( del t a , f , n , i de nt i t e ( ) ) ;
}
//
coupl e multMatVec ( quadrupl et x , coupl e y)
{
coupl e xy ;
xy . f i r s t = x . 11 y . f i r s t + x . 12 y . second ;
xy . second = x . 21 y . f i r s t + x . 22 y . second ;
return xy ;
}
//
unsigned long f as t Fi bonac c i I T( unsigned long l )
{
quadrupl et q = f i boMat ( ) ;
coupl e c = {1 , 0};
c = multMatVec (matPow( q , l ) , c ) ;
return c . second ;
}
//
i nt main ( )
{
i nt i ;
for ( i = 0 ; i <= 45 ; i ++)
{
pr i nt f ( F %d = %l d\n , i , f as t Fi bonac c i I T( i ) ) ;
}
return 0;
}
103
A.4 Tours de Hano
#include<s t di o . h>
#include<mal l oc . h>
#include<s t d l i b . h>
/
On pl acera dans l a premiere case de chaque t abl eau l e nombre de di sques
pl aces sur l e s ocl e .
/
i nt max2( i nt i , i nt j )
{
return ( i > j ) ? i : j ;
}
i nt max3( i nt i , i nt j , i nt k)
{
return max2( max2( i , j ) , k ) ;
}
void a f f i c h e S o c l e s ( i nt s )
{
i nt max = max3( s , ( s + 1) , ( s + 2 ) ) ;
i nt i ;
for ( i = max ; i > 0 ; i )
{
i f ( s >= i )
pr i nt f ( %3d , ( s + i ) ) ;
el se
pr i nt f ( ) ;
i f ( ( s + 1) >= i )
pr i nt f ( %3d , ( ( s +1) + i ) ) ;
el se
pr i nt f ( ) ;
i f ( ( s + 2) >= i )
pr i nt f ( %3d , ( ( s +2) + i ) ) ;
pr i nt f ( \n ) ;
}
pr i nt f ( \n ) ;
}
void depl aceDi sque( i nt socl eSour ce , i nt s oc l e De s t i nat i on )
{
( s oc l e De s t i nat i on + s oc l e De s t i nat i on + 1) =
( s oc l e Sour c e + s oc l e Sour c e ) ;
( s oc l e De s t i nat i on)++;
( s oc l e Sour c e);
}
void depl aceDi sques ( i nt n , i nt s , i nt sFrom , i nt sVia , i nt sTo )
{
i f ( n > 0)
{
depl aceDi sques ( n1, s , sFrom , sTo , sVi a ) ;
depl aceDi sque ( ( s + sFrom) , ( s + sTo ) ) ;
a f f i c h e S o c l e s ( s ) ;
depl aceDi sques ( n1, s , sVia , sFrom , sTo ) ;
}
}
i nt c r e e Soc l e ( i nt nbDi sques )
{
i nt s = mal l oc ( ( nbDi sques + 1) si zeof ( i nt ) ) ;
i f ( s == NULL)
e xi t ( 0 ) ;
s = 0;
return s ;
}
void i ni t S o c l e ( i nt s , i nt nbDi sques )
{
i nt i ;
for ( i = 1 ; i <= nbDi sques ; i ++)
( s + i ) = nbDi sques i + 1;
s = nbDi sques ;
}
void c r e e Soc l e s ( i nt s , i nt nbDi sques )
{
104
s = c r e e Soc l e ( nbDi sques ) ;
( s + 1) = c r e e Soc l e ( nbDi sques ) ;
( s + 2) = c r e e Soc l e ( nbDi sques ) ;
i n i t So c l e ( s , nbDi sques ) ;
}
i nt main ( )
{
i nt s [ 3 ] ;
i nt nbDi sques = 3;
c r e e Soc l e s ( s , nbDi sques ) ;
a f f i c h e S o c l e s ( s ) ;
depl aceDi sques ( nbDi sques , s , 0 , 1 , 2) ;
f r e e ( s ) ;
f r e e ( ( s + 1 ) ) ;
f r e e ( ( s + 2 ) ) ;
return 1;
}
105
A.5 Suite de Fibonacci
#include<s t di o . h>
#define N 45
unsigned long f i bo ( unsigned long l )
{
i f ( l == 0)
return 0;
i f ( l == 1)
return 1;
return f i bo ( l 1) + f i bo ( l 2 ) ;
}
void phi ( unsigned long l 1 , unsigned long l 2 )
{
unsigned long temp ;
temp = l 1 ;
l 1 += l 2 ;
l 2 = temp ;
}
void applyF( void ( f ) ( unsigned long , unsigned long ) ,
i nt n , unsigned long l 1 , unsigned long l 2 )
{
i f ( n > 0)
{
f ( l 1 , l 2 ) ;
applyF( f , n1, l 1 , l 2 ) ;
}
}
unsigned long f as t Fi bo ( unsigned long l )
{
unsigned long l 1 = 1 , l 2 = 0;
applyF( phi , l , &l 1 , &l 2 ) ;
return l 2 ;
}
i nt main ( )
{
unsigned long l ;
for ( l = 0 ; l <= N ; l ++)
pr i nt f ( %l u = %l u\n , l , f i bo ( l ) ) ;
for ( l = 0 ; l <= N ; l ++)
pr i nt f ( %l u = %l u\n , l , f as t Fi bo ( l ) ) ;
return 0;
}
106
A.6 Pgcd
#include<s t di o . h>
unsigned long pgcd( unsigned long a , unsigned long b)
{
i f ( b == 0)
return a ;
return pgcd( b , a % b ) ;
}
unsigned long f i bonac c i ( unsigned long l )
{
unsigned long moinsUn , moinsDeux;
i f ( l == 0 | | l == 1)
return l ;
moinsUn = 1;
moinsDeux = 0;
while ( l > 1)
{
moinsUn = moinsDeux;
moinsDeux = moinsUn ;
moinsUn = moinsDeux;
moinsUn += moinsDeux;
l ;
}
return moinsUn ;
}
i nt main ( )
{
unsigned long f 1 , f 2 , i ;
f 2 = f i bonac c i ( 0 ) ;
for ( i = 0 ; i <= 40 ; i ++)
{
f 1 = f 2 ;
f 2 = f i bo na c c i ( i +1);
pr i nt f ( pgcd(%l u , %l u ) = %l u\n , f 1 , f 2 , pgcd( f 1 , f 2 ) ) ;
}
return 0;
}
107
A.7 Pavage avec des L
#include<s t di o . h>
#include<s t d l i b . h>
#include<mal l oc . h>
typedef struct
{
i nt l i gne ;
i nt col onne ;
}coordonnees ;
typedef struct
{
char tab ;
i nt n ;
coordonnees c as e I nt e r di t e ;
} g r i l l e ;
i nt pui s s ( i nt b , i nt n)
{
i f ( n == 0)
return 1;
return b pui s s ( b , n1);
}
void erreurMemoi re ( )
{
pr i nt f ( Pas de memoire\n ) ;
e xi t ( 1 ) ;
}
char r et our neAdr esseCase( g r i l l e g , coordonnees c )
{
i nt mi l i e u ;
i f ( g . n == 0)
return g . tab ;
mi l i e u = pui s s ( 2 , g . n 1 ) ;
i f ( c . l i g ne >= mi l i e u )
{
g . tab += 2 mi l i e u mi l i e u ;
c . l i gne=mi l i e u ;
}
i f ( c . col onne >= mi l i e u )
{
g . tab += mi l i e u mi l i e u ;
c . col onne=mi l i e u ;
}
g . n = 1;
return r et our neAdr esseCase( g , c ) ;
}
char retourneVal eurCase ( g r i l l e g , coordonnees c )
{
return r et our neAdresseCase( g , c ) ;
}
void af f e c t e Val e ur Cas e ( g r i l l e g , coordonnees c , char val eur )
{
r et our neAdresseCase( g , c ) = val eur ;
}
g r i l l e g r i l l e Cr e e ( i nt n , i nt l i gne I nt e r di t e , i nt c ol onne I nt e r di t e ,
char val eur s , char val e ur I nt e r di t e )
{
g r i l l e g ;
i nt l ar ge ur = pui s s ( 2 , n ) ;
coordonnees c ;
g . tab = ( char ) mal l oc ( l ar ge ur l ar ge ur ) ;
i f ( g . tab == NULL)
erreurMemoi re ( ) ;
g . n = n ;
g . c a s e I nt e r di t e . l i gne = l i g n e I n t e r di t e ;
g . c a s e I nt e r di t e . col onne = c ol onne I nt e r di t e ;
for ( c . l i g ne = 0 ; c . l i g ne < l ar ge ur ; c . l i gne++)
for ( c . col onne = 0 ; c . col onne < l ar ge ur ; c . col onne++)
af f e c t e Val e ur Cas e ( g , c , val e ur s ) ;
af f e c t e Val e ur Cas e ( g , g . c as e I nt e r di t e , va l e ur I nt e r di t e ) ;
return g ;
}
108
void g r i l l e Af f i c h e ( g r i l l e g)
{
i nt l ar ge ur = pui s s ( 2 , g . n ) ;
coordonnees c ;
for ( c . l i g ne = 0 ; c . l i g ne < l ar ge ur ; c . l i gne++)
{
for ( c . col onne = 0 ; c . col onne < l ar ge ur ; c . col onne++)
pr i nt f ( %c , retourneVal eurCase ( g , c ) ) ;
pr i nt f ( \n ) ;
}
}
void gr i l l e Pavage ( g r i l l e g , char c )
{
i nt l ar ge ur ;
char val e ur I nt e r di t e ;
i nt nbPi eces ;
g r i l l e hd , hg , bd , bg ;
i f ( g . n != 0)
{
l ar ge ur = pui s s ( 2 , g . n1);
hg . tab = g . tab ;
hd . tab = hg . tab + l ar ge ur l ar ge ur ;
bg . tab = hd . tab + l ar ge ur l ar ge ur ;
bd . tab = bg . tab + l ar ge ur l ar ge ur ;
hg . n = g . n 1;
hd . n = g . n 1;
bg . n = g . n 1;
bd . n = g . n 1;
hg . c as e I nt e r di t e . l i g ne = l ar ge ur 1;
hg . c as e I nt e r di t e . col onne = l ar ge ur 1;
hd . c as e I nt e r di t e . l i g ne = l ar ge ur 1;
hd . c as e I nt e r di t e . col onne = 0 ;
bg . c as e I nt e r di t e . l i g ne = 0 ;
bg . c as e I nt e r di t e . col onne = l ar ge ur 1;
bd . c as e I nt e r di t e . l i g ne = 0 ;
bd . c as e I nt e r di t e . col onne = 0 ;
i f ( g . c a s e I nt e r di t e . l i g ne < l ar ge ur )
i f ( g . c as e I nt e r di t e . col onne < l ar ge ur )
hg . c as e I nt e r di t e = g . c a s e I nt e r di t e ;
el se
{
hd . c as e I nt e r di t e . l i gne = g . c as e I nt e r di t e . l i gne ;
hd . c as e I nt e r di t e . col onne = g . c a s e I nt e r di t e . col onne l ar ge ur ;
}
el se
i f ( g . c as e I nt e r di t e . col onne < l ar ge ur )
{
bg . c as e I nt e r di t e . l i gne = g . c as e I nt e r di t e . l i gne l ar ge ur ;
bg . c as e I nt e r di t e . col onne = g . c a s e I nt e r di t e . col onne l ar ge ur ;
}
el se
{
bd . c as e I nt e r di t e . l i gne = g . c as e I nt e r di t e . l i gne l ar ge ur ;
bd . c as e I nt e r di t e . col onne = g . c a s e I nt e r di t e . col onne l ar ge ur ;
}
val e ur I nt e r di t e = retourneVal eurCase ( g , g . c as e I nt e r d i t e ) ;
af f e c t e Val e ur Cas e ( hd , hd . c as e I nt e r di t e , c + 1 ) ;
af f e c t e Val e ur Cas e ( hg , hg . c as e I nt e r di t e , c + 1 ) ;
af f e c t e Val e ur Cas e ( bg , bg . c as e I nt e r di t e , c + 1 ) ;
af f e c t e Val e ur Cas e ( bd , bd . c as e I nt e r di t e , c + 1 ) ;
af f e c t e Val e ur Cas e ( g , g . c as e I nt e r di t e , val e ur I nt e r di t e ) ;
gr i l l e Pavage ( hd , c +1);
nbPi eces = ( l ar ge ur l ar ge ur 1) /3;
gr i l l e Pavage ( hg , c+nbPi eces + 1 ) ;
gr i l l e Pavage ( bg , c+2nbPi eces + 1) ;
gr i l l e Pavage ( bd , c+3nbPi eces + 1) ;
}
}
void g r i l l e De t r u i t ( g r i l l e g)
{
f r e e ( g . tab ) ;
}
i nt main ( )
{
g r i l l e g = g r i l l e Cr e e ( 4 , 5 , 12 , 1, ! ) ;
gr i l l e Pavage ( g , ! ) ;
g r i l l e Af f i c h e ( g ) ;
109
g r i l l e De t r u i t ( g ) ;
return 0;
}
110
A.8 Complexes
#include<s t di o . h>
#include<s t d l i b . h>
#include<mal l oc . h>
#include<math . h>
#include compl exe . h
#include l i nke dLi s t . h
//
/
Retourne l a par t i e r e e l l e
/
double reComplexe ( compl exe c )
{
return c . r e ;
}
//
/
Retourne l a par t i e i magi nai re
/
double imComplexe( compl exe c )
{
return c . im;
}
//
/
Retourne l e module
/
double modComplexe ( compl exe c )
{
return c . mod;
}
//
/
Retourne l argument
/
double argComplexe ( compl exe c )
{
return c . arg ;
}
//
/
Af f i che c sous forme exponent i el l e
/
void printExpComplexe ( compl exe c )
{
pr i nt f ( %.10 l f e (%. 10 l f i ) , c . mod, c . arg ) ;
}
//
/
Af f i che l a f f i x e de c
/
void pri ntAf f Compl exe( compl exe c )
{
pr i nt f ( (%. 10 l f + %.10 l f i ) , c . re , c . im) ;
}
//
/
Cree un complexe a par t i r de son a f f i x e
/
111
compl exe makeAffComplexe ( double re , double im)
{
compl exe c = {re , im, s qr t ( r e r e + imim) , 0. 0 };
i f ( c . mod != 0. 0)
{
c . arg = acos ( c . r e /c . mod) ( ( c . im >= 0 )? 1 : 1) ;
}
return c ;
}
//
/
Cree un complexe a par t i r de sa forme exponent i el l e
/
compl exe makeExpComplexe( double mod, double arg )
{
compl exe c = {0. 0 , 0. 0 , mod, arg };
c . arg += M PI ;
long l = c . arg /( 2. M PI ) ;
c . arg = l 2. M PI ;
c . arg = M PI ;
i f (mod != 0. 0)
{
c . r e = c . mod cos ( c . arg ) ;
c . im = c . mod s i n ( c . arg ) ;
}
return c ;
}
//
pComplexe copyComplexe ( compl exe c )
{
pComplexe p = ( pComplexe) mal l oc ( si zeof ( compl exe ) ) ;
i f ( p == NULL)
e xi t ( 0 ) ;
p>r e = c . r e ;
p>im = c . im;
p>mod = c . mod;
p>arg = c . arg ;
return p ;
}
//
/
Retourne l e conjugue de c
/
compl exe conj ugueComplexe( compl exe c )
{
return makeAffComplexe ( c . re , c . im) ;
}
//
/
Sous t r ai t c1 et c2
/
compl exe subComplexe ( compl exe c1 , compl exe c2 )
{
return makeAffComplexe ( c1 . r e c2 . re , c1 . im c2 . im) ;
}
//
/
Additionne c1 et c2
/
compl exe addComplexe( compl exe c1 , compl exe c2 )
{
return makeAffComplexe ( c1 . r e + c2 . re , c1 . im + c2 . im) ;
}
//
/
112
Mul t i pl i e c1 et c2
/
compl exe multComplexe ( compl exe c1 , compl exe c2 )
{
return makeAffComplexe ( c1 . r e c2 . r e c1 . im c2 . im,
c1 . r e c2 . im + c1 . im c2 . r e ) ;
}
//
/
Mul t i pl i e c par l e r e el d
/
compl exe multReelComplexe ( double d , compl exe c )
{
return makeExpComplexe( d c . mod, c . arg ) ;
}
//
/
Di vi se c2 par c1
/
compl exe divComplexe ( compl exe c1 , compl exe c2 )
{
return makeExpComplexe( c1 . mod / c2 . mod, c1 . arg c2 . arg ) ;
}
//
/
El eve c a l a pui ssane n
/
compl exe pui ssCompl exe ( compl exe c , unsigned long n)
{
return makeExpComplexe( pow( c . mod, n) , nc . arg ) ;
}
113
A.9 Listes chanees
#include l i nke dLi s t . h
#include<s t di o . h>
#include<s t d l i b . h>
#include<mal l oc . h>
//
void e r r or ( )
{
pr i nt f ( e r r or ) ;
e xi t ( 0 ) ;
}
//
i nt l i nke dLi s t Ge t Si z e ( l i nke dLi s t l )
{
return l >s i z e ;
}
//
l i nke dLi s t l i nke dLi s t Cr e at e ( )
{
l i nke dLi s t l ;
l = ( l i nke dLi s t ) mal l oc ( si zeof ( l i nke dLi s t ) ) ;
i f ( l == NULL)
e r r or ( ) ;
l >f i r s t = NULL;
l >l a s t = NULL;
l >s i z e = 0;
return l ;
}
//
l i nk l i nke dLi s t Cr e at e Li nk( void x)
{
l i nk l k = ( l i nk ) mal l oc ( si zeof ( l i nk ) ) ;
i f ( l k == NULL) e r r or ( ) ;
l k>data = x ;
l k>next = NULL;
return l k ;
}
//
void l i nkedLi stAppendLi nk ( l i nke dLi s t l , l i nk l k )
{
i f ( l >l a s t == NULL)
{
l >f i r s t = l k ;
l >l a s t = l >f i r s t ;
}
el se
{
l >l as t >next = l k ;
l >l a s t = l k ;
}
l k>next = NULL;
l >s i z e ++;
}
//
void l i nkedLi stAppend ( l i nke dLi s t l , void x)
{
l i nk l k = l i nke dLi s t Cr e at e Li nk( x ) ;
l i nkedLi stAppendLi nk ( l , l k ) ;
}
//
void l i nkedLi st PushLi nk ( l i nke dLi s t l , l i nk l k )
114
{
i f ( l >f i r s t == NULL)
{
l >f i r s t = l k ;
l >l a s t = l >f i r s t ;
}
el se
{
l k>next = l >f i r s t ;
l >f i r s t = l k ;
}
l >s i z e ++;
}
//
void l i nkedLi st Push ( l i nke dLi s t l , void x)
{
l i nk l k = l i nke dLi s t Cr e at e Li nk( x ) ;
l i nkedLi st PushLi nk ( l , l k ) ;
}
//
l i nk l i nke dLi s t Ge t Fi r s t ( l i nke dLi s t l )
{
return l >f i r s t ;
}
//
l i nk l i nke dLi s t Unl i nkFi r s t ( l i nke dLi s t l )
{
l i nk f = l i nke dLi s t Ge t Fi r s t ( l ) ;
i f ( f != NULL)
{
l >f i r s t = l >f i r s t >next ;
i f ( l >l a s t == f )
l >l a s t = NULL;
l >s i z e ;
}
return f ;
}
//
void l i nkedLi st Concat ( l i nke dLi s t begi n , l i nke dLi s t end)
{
i f ( begi n>s i z e != 0)
begi n>l as t >next = end>f i r s t ;
el se
begi n>f i r s t = end>f i r s t ;
i f ( end>s i z e != 0)
begi n>l a s t = end>l a s t ;
end>f i r s t = NULL;
end>l a s t = NULL;
begi n>s i z e += end>s i z e ;
end>s i z e = 0;
}
//
l i nke dLi s t l i nkedLi stMap ( l i nke dLi s t l , void ( f ) ( void) )
{
l i nke dLi s t l Bi s = l i nke dLi s t Cr e at e ( ) ;
l i nk l k = l i nke dLi s t Ge t Fi r s t ( l ) ;
while ( l k !=NULL)
{
l i nkedLi stAppend ( l Bi s , f ( l k>data ) ) ;
l k = l k>next ;
}
return l Bi s ;
}
//
void l i nkedLi st Appl y ( l i nke dLi s t l , void ( f ) ( void) )
{
115
l i nk l k = l i nke dLi s t Ge t Fi r s t ( l ) ;
while ( l k !=NULL)
{
f ( l k>data ) ;
l k = l k>next ;
}
}
//
void l i nkDe s t r oy( l i nk l , void ( f r ) ( void) )
{
i f ( l != NULL)
{
l i nkDe s t r oy( l >next , f r ) ;
f r ( l >data ) ;
f r e e ( l ) ;
}
}
//
void l i nke dLi s t De s t r oy ( l i nke dLi s t l , void ( f r ) ( void) )
{
l i nkDe s t r oy( l >f i r s t , f r ) ;
f r e e ( l ) ;
}
//
/
voi d des t r oyI nt ( voi d i )
{
f r ee (( i nt ) i ) ;
}
voi d pr i nt I nt ( voi d i )
{
pr i nt f (%d > , (( i nt ) i ) ) ;
}
voi d copyInt ( voi d i )
{
voi d v = mal l oc ( s i z e of ( i nt ) ) ;
i f ( v == NULL)
error ( ) ;
(( i nt ) v ) = (( i nt ) i ) ;
ret urn v ;
}
i nt main()
{
i nt i = 1;
i nt k ;
l i nk e dLi s t l = l i nkedLi s t Cr eat e ( ) ;
l i nk e dLi s t l Bi s ;
f or ( i = 0 ; i < 100 ; i ++)
{
k = ( i nt ) mal l oc ( s i z e of ( i nt ) ) ;
k = i ;
l i nkedLi st Append ( l , k ) ;
}
// l i nkedLi st Appl y ( l , pr i nt I nt ) ;
l Bi s = l i nkedLi st Map( l , copyInt ) ;
// l i nkedLi st Appl y ( l Bi s , pr i nt I nt ) ;
l i nkedLi st Concat ( l , l Bi s ) ;
l i nkedLi st Appl y ( l , pr i nt I nt ) ;
l i nkedLi st Des t r oy ( l , des t r oyI nt ) ;
l i nkedLi st Des t r oy ( l Bi s , des t r oyI nt ) ;
ret urn 1;
}
/
116
A.10 Tri fusion
#include<s t di o . h>
#include<s t d l i b . h>
#include<mal l oc . h>
#include l i nke dLi s t . h
void s p l i t ( l i nke dLi s t source , l i nke dLi s t dest1 , l i nke dLi s t dest 2 )
{
l i nk l = l i nke dLi s t Unl i nkFi r s t ( sour ce ) ;
i f ( l != NULL)
{
l i nkedLi stAppendLi nk ( dest1 , l ) ;
s p l i t ( source , dest2 , dest 1 ) ;
}
}
void merge ( l i nke dLi s t source1 , l i nke dLi s t source2 , l i nke dLi s t dest ,
i nt ( i nf ) ( void , void) )
{
l i nk l 1 , l 2 ;
l 1 = l i nke dLi s t Ge t Fi r s t ( sour ce1 ) ;
l 2 = l i nke dLi s t Ge t Fi r s t ( sour ce2 ) ;
i f ( l 1 != NULL | | l 2 != NULL)
{
i f ( l 2 == NULL | |
( l 1 != NULL && i n f ( l 1>data , l 2>data ) )
)
{
l i nke dLi s t Unl i nkFi r s t ( sour ce1 ) ;
l i nkedLi stAppendLi nk ( dest , l 1 ) ;
}
el se
{
l i nke dLi s t Unl i nkFi r s t ( sour ce2 ) ;
l i nkedLi stAppendLi nk ( dest , l 2 ) ;
}
merge ( source1 , source2 , dest , i n f ) ;
}
}
void doNothing ( void v)
{
}
void t r i Fus i on ( l i nke dLi s t l , i nt ( i n f ) ( void , void) )
{
l i nke dLi s t l 1 , l 2 ;
i f ( l i nke dLi s t Ge t Si z e ( l ) > 1)
{
l 1 = l i nke dLi s t Cr e at e ( ) ;
l 2 = l i nke dLi s t Cr e at e ( ) ;
s p l i t ( l , l 1 , l 2 ) ;
t r i Fus i on ( l 1 , i nf ) ;
t r i Fus i on ( l 2 , i nf ) ;
merge ( l 1 , l 2 , l , i n f ) ;
l i nke dLi s t De s t r oy ( l 1 , doNothing ) ;
l i nke dLi s t De s t r oy ( l 2 , doNothing ) ;
}
}
//
i nt e s t I nf ( void i , void j )
{
return ( ( i nt ) i <= ( i nt ) j ) ? 1 : 0;
}
void de s t r oyI nt ( void i )
{
f r e e ( ( i nt ) i ) ;
}
i nt main ( )
{
i nt i = 1;
i nt k ;
l i nke dLi s t l = l i nke dLi s t Cr e at e ( ) ;
l i nk l k ;
for ( i = 100 ; i > 0 ; i )
{
117
k = ( i nt ) mal l oc ( si zeof ( i nt ) ) ;
k = i ;
l i nkedLi stAppend ( l , k ) ;
}
l k = l i nke dLi s t Ge t Fi r s t ( l ) ;
while ( l k !=NULL)
{
pr i nt f ( %d , ( ( i nt ) ( l k>data ) ) ) ;
l k = l k>next ;
}
pr i nt f ( \n ) ;
t r i Fus i on ( l , e s t I nf ) ;
l k = l i nke dLi s t Ge t Fi r s t ( l ) ;
while ( l k !=NULL)
{
pr i nt f ( %d , ( ( i nt ) ( l k>data ) ) ) ;
l k = l k>next ;
}
pr i nt f ( \n ) ;
l i nke dLi s t De s t r oy ( l , de s t r oyI nt ) ;
return 0;
}
118
A.11 Tri par insertion
#include<s t di o . h>
#include<s t d l i b . h>
#include<mal l oc . h>
#include l i nke dLi s t . h
l i nk i ns e r t ( l i nk l i s t , l i nk item , i nt ( e s t I n f ) ( void , void) )
{
i f ( l i s t == NULL)
{
item>next = NULL;
return i tem ;
}
i f ( e s t I n f ( item>data , l i s t >data ) )
{
item>next = l i s t ;
return i tem ;
}
l i s t >next = i n s e r t ( l i s t >next , item , e s t I n f ) ;
return l i s t ;
}
l i nk t r i I n s e r t i o n ( l i nk l i s t , i nt ( e s t I n f ) ( void , void) )
{
i f ( l i s t == NULL)
return NULL;
return i ns e r t ( t r i I n s e r t i o n ( l i s t >next , e s t I nf ) , l i s t , e s t I nf ) ;
}
void l i nke dLi s t Sor t ( l i nke dLi s t l , i nt ( e s t I nf ) ( void , void) )
{
l >f i r s t = t r i I n s e r t i o n ( l >f i r s t , e s t I nf ) ;
void s e t Las t ( l i nk l l )
{
i f ( l l == NULL)
l >l a s t = NULL;
el se
i f ( l l >next == NULL)
l >l a s t = l l ;
el se
s e t Las t ( l l >next ) ;
}
s e t Las t ( l >f i r s t ) ;
}
i nt e s t I nf ( void i , void j )
{
return ( ( i nt ) i <= ( i nt ) j ) ? 1 : 0;
}
void de s t r oyI nt ( void i )
{
f r e e ( ( i nt ) i ) ;
}
i nt main ( )
{
i nt i = 1;
i nt k ;
l i nke dLi s t l = l i nke dLi s t Cr e at e ( ) ;
for ( i = 100 ; i > 0 ; i )
{
k = ( i nt ) mal l oc ( si zeof ( i nt ) ) ;
k = i ;
l i nkedLi stAppend ( l , k ) ;
}
void pr i nt I nt ( void i )
{
pr i nt f ( %d , ( ( i nt ) i ) ) ;
}
l i nkedLi st Appl y ( l , pr i nt I nt ) ;
pr i nt f ( \n ) ;
l i nke dLi s t Sor t ( l , e s t I n f ) ;
l i nkedLi st Appl y ( l , pr i nt I nt ) ;
pr i nt f ( \n ) ;
l i nke dLi s t De s t r oy ( l , de s t r oyI nt ) ;
return 0;
}
119
A.12 Transformee de Fourier
#include<s t di o . h>
#include<s t d l i b . h>
#include<mal l oc . h>
#include<math . h>
#include compl exe . h
#include f o u r i e r . h
#include l i nke dLi s t . h
//
/
Retourne l e s raci nes neme de c , O(n)
/
l i nke dLi s t raci nesCompl exe ( compl exe c , unsigned long n)
{
l i nke dLi s t l = l i nke dLi s t Cr e at e ( ) ;
pComplexe p ;
unsigned long i ;
for ( i = 0 ; i < n ; i ++)
{
p = ( pComplexe) mal l oc ( si zeof ( compl exe ) ) ;
i f ( p == NULL)
e xi t ( 1 ) ;
p = makeExpComplexe(pow( c . mod, 1. /n) , ( c . arg/n) + ( i )2M PI/n ) ;
l i nkedLi stAppend ( l , p ) ;
}
return l ;
}
//
/
Retourne l e s raci nes neme de 1 , O(n)
/
l i nke dLi s t uni teRaci nesCompl exe( unsigned long n)
{
return raci nesCompl exe ( makeAffComplexe ( 1. 0 , 0. 0) , n ) ;
}
//
/
Donne l image de x par polynome . Les c o e f f i c i e nt s du polynome sont
ranges par ordre de degre cr oi s s ant . O(n) .
/
compl exe horner ( l i nk polynome , compl exe x)
{
i f ( polynome == NULL)
return makeAffComplexe ( 0. 0 , 0 . 0 ) ;
return addComplexe( ( pComplexe) polynome>data ,
multComplexe ( x ,
horner ( polynome>next ,
x ) ) ) ;
}
//
/
Det rui t complexe poi nt e par p .
/
void deal l ocateCompl exe ( void p)
{
f r e e ( ( pComplexe) p ) ;
}
//
/
Retourne l a t ransf ormee di s c r e t e de Fourier du vect eur l ,
versi on i t e r a t i v e en O(n2)
/
l i nke dLi s t t r ans f or me e Four i e r I t ( l i nke dLi s t polynome )
{
l i nke dLi s t FT = l i nke dLi s t Cr e at e ( ) ;
120
l i nke dLi s t W n = uni teRaci nesCompl exe( l i nke dLi s t Ge t Si z e ( polynome ) ) ;
void eval uat e ( void w)
{
pComplexe p = ( pComplexe) mal l oc ( si zeof ( compl exe ) ) ;
i f ( p == NULL)
e xi t ( 0 ) ;
p = horner ( l i nke dLi s t Ge t Fi r s t ( polynome ) ,
( pComplexe)w) ;
return p ;
}
FT = l i nkedLi stMap (W n, eval uat e ) ;
l i nke dLi s t De s t r oy (W n, deal l ocateCompl exe ) ;
return FT;
}
//
/
Ne f a i t ri en . . .
/
void doNothing ( void w)
{
}
//
/
Retourne l a t ransf ormee di s c r e t e de Fourier du vect eur l ,
versi on r ecur s i ve en O(n. l og n)
/
l i nke dLi s t FFT( l i nke dLi s t polynome )
{
// creat i on des l i s t e s
l i nke dLi s t FT = l i nke dLi s t Cr e at e ( ) ; // r e s ul t a t
l i nke dLi s t odd = l i nke dLi s t Cr e at e ( ) ; // c o e f f i c i e nt s d i ndi ce pai r
l i nke dLi s t even = l i nke dLi s t Cr e at e ( ) ; // c o e f f i c i e nt s d i ndi ce impair
l i nke dLi s t a 0 = l i nke dLi s t Cr e at e ( ) ; // TF de odd
l i nke dLi s t a 1 = l i nke dLi s t Cr e at e ( ) ; // TF de even
l i nk l ; // pour parcouri r FT
compl exe w = makeAffComplexe ( 1. 0 , 0 . 0 ) ;
compl exe c = makeExpComplexe( 1. 0 , 2M PI/ l i nke dLi s t Ge t Si z e ( polynome ) ) ;
i nt i sEven = 1;
// cas de base
i f ( l i nke dLi s t Ge t Si z e ( polynome ) == 1)
{
l i nkedLi stAppend (FT,
copyComplexe ( ( pComplexe)
( l i nke dLi s t Ge t Fi r s t ( polynome)>data ) ) ) ;
return FT;
}
// aut res cas
void s p l i t ( void c o e f f )
{
i f ( i sEven )
l i nkedLi stAppend ( even , c o e f f ) ;
el se
l i nkedLi stAppend ( odd , c o e f f ) ;
i sEven = ! i sEven ;
}
// separat i on de polynome
l i nkedLi st Appl y ( polynome , s p l i t ) ;
// appel s r e cur s i f s
a 0 = FFT( even ) ;
a 1 = FFT( odd ) ;
void evenVal ues( void v)
{
l i nkedLi stAppend (FT, copyComplexe ( ( pComplexe) v ) ) ;
}
// aj out dans FT des val eurs de a [ 0]
l i nkedLi st Appl y ( a 0 , evenVal ues ) ;
l i nkedLi st Appl y ( a 0 , evenVal ues ) ;
l = l i nke dLi s t Ge t Fi r s t (FT) ;
void oddVal ues ( void v)
{
pComplexe f t = ( pComplexe) ( l >data ) ;
f t = addComplexe( f t , multComplexe (w, ( pComplexe) v ) ) ;
w = multComplexe ( c , w) ;
l = l >next ;
}
121
// aj out dans FT des w np a [ 1] p
l i nkedLi st Appl y ( a 1 , oddVal ues ) ;
l i nkedLi st Appl y ( a 1 , oddVal ues ) ;
// l i b e r at i on de l a memoire
l i nke dLi s t De s t r oy ( odd , doNothing ) ;
l i nke dLi s t De s t r oy ( even , doNothing ) ;
l i nke dLi s t De s t r oy ( a 0 , deal l ocateCompl exe ) ;
l i nke dLi s t De s t r oy ( a 1 , deal l ocateCompl exe ) ;
return FT;
}
//
/
Retourne l a t ransf ormee di s c r e t e de Fourier du vect eur l ,
versi on r ecur s i ve en O(n. l og n)
/
l i nke dLi s t i nverseFFT( l i nke dLi s t polynome )
{
l i nke dLi s t FT = l i nke dLi s t Cr e at e ( ) ;
l i nke dLi s t odd = l i nke dLi s t Cr e at e ( ) ;
l i nke dLi s t even = l i nke dLi s t Cr e at e ( ) ;
l i nke dLi s t a 0 = l i nke dLi s t Cr e at e ( ) ;
l i nke dLi s t a 1 = l i nke dLi s t Cr e at e ( ) ;
l i nk l ;
compl exe w = makeAffComplexe ( 1. 0 , 0 . 0 ) ;
compl exe c = makeExpComplexe( 1. 0 , 2.M PI/ l i nke dLi s t Ge t Si z e ( polynome ) ) ;
i nt i sEven = 1;
i f ( l i nke dLi s t Ge t Si z e ( polynome ) == 1)
{
l i nkedLi stAppend (FT,
copyComplexe ( ( pComplexe)
( l i nke dLi s t Ge t Fi r s t ( polynome)>data ) ) ) ;
return FT;
}
void s p l i t ( void c o e f f )
{
i f ( i sEven )
l i nkedLi stAppend ( even , c o e f f ) ;
el se
l i nkedLi stAppend ( odd , c o e f f ) ;
i sEven = ! i sEven ;
}
l i nkedLi st Appl y ( polynome , s p l i t ) ;
a 0 = i nverseFFT( even ) ;
a 1 = i nverseFFT( odd ) ;
void evenVal ues( void v)
{
l i nkedLi stAppend (FT, copyComplexe ( ( pComplexe) v ) ) ;
}
l i nkedLi st Appl y ( a 0 , evenVal ues ) ;
l i nkedLi st Appl y ( a 0 , evenVal ues ) ;
l = l i nke dLi s t Ge t Fi r s t (FT) ;
void oddVal ues ( void v)
{
pComplexe f t = ( pComplexe) ( l >data ) ;
compl exe val ue = multComplexe (w, ( pComplexe) v ) ;
val ue = multReelComplexe ( 1 . / 2 . , addComplexe( f t , val ue ) ) ;
f t = val ue ;
w = multComplexe ( c , w) ;
l = l >next ;
}
l i nkedLi st Appl y ( a 1 , oddVal ues ) ;
l i nkedLi st Appl y ( a 1 , oddVal ues ) ;
void doNothing ( void w){}
l i nke dLi s t De s t r oy ( odd , doNothing ) ;
l i nke dLi s t De s t r oy ( even , doNothing ) ;
void deal l ocateCompl exe ( void p)
{
f r e e ( ( pComplexe) p ) ;
}
l i nke dLi s t De s t r oy ( a 0 , deal l ocateCompl exe ) ;
l i nke dLi s t De s t r oy ( a 1 , deal l ocateCompl exe ) ;
return FT;
}
//
/
Retourne l a t ransf ormee di s c r e t e de Fourier i nverse
122
du vect eur l , versi on i t e r a t i v e en O(n2)
/
l i nke dLi s t t r ans f or me e I nve r s e Four i e r I t ( l i nke dLi s t polynome )
{
l i nke dLi s t FT = l i nke dLi s t Cr e at e ( ) ;
i nt n = l i nke dLi s t Ge t Si z e ( polynome ) ;
l i nke dLi s t W n = uni teRaci nesCompl exe( n ) ;
void conj ugue ( void w)
{
( pComplexe)w = conj ugueCompl exe( ( pComplexe)w) ;
}
l i nkedLi st Appl y (W n, conj ugue ) ;
void eval uat e ( void w)
{
pComplexe p = ( pComplexe) mal l oc ( si zeof ( compl exe ) ) ;
i f ( p == NULL)
e xi t ( 0 ) ;
p = horner ( l i nke dLi s t Ge t Fi r s t ( polynome ) ,
( pComplexe)w) ;
return p ;
}
FT = l i nkedLi stMap (W n, eval uat e ) ;
void di v i s e ( void w)
{
( pComplexe)w = multReelComplexe ( 1. /n , ( pComplexe)w) ;
}
l i nkedLi st Appl y (FT, d i vi s e ) ;
void deal l ocateCompl exe ( void p)
{
f r e e ( ( pComplexe) p ) ;
}
l i nke dLi s t De s t r oy (W n, deal l ocateCompl exe ) ;
return FT;
}
//
l i nke dLi s t s i mpl e Li s t ( i nt n)
{
i f ( n == 0)
return l i nke dLi s t Cr e at e ( ) ;
l i nke dLi s t l = s i mpl e Li s t ( n 1) ;
l i nkedLi stAppend ( l , copyComplexe ( makeAffComplexe ( n , 0 . 0 ) ) ) ;
return l ;
}
//
/
i nt main()
{
i nt k = 512;
voi d printC ( voi d v)
{
printAffCompl exe ((( pComplexe) v ) ) ;
pr i nt f (\n) ;
}
pr i nt f ( l i s t e \n) ;
l i nkedLi st Appl y ( si mpl eLi st ( k ) ,
printC ) ;
pr i nt f (FFT de l i s t e \n) ;
l i nkedLi st Appl y (FFT( si mpl eLi st ( k )) ,
printC ) ;
pr i nt f (FFT1 o FFT de l i s t e \n) ;
l i nkedLi st Appl y ( inverseFFT (FFT( si mpl eLi st ( k ) ) ) ,
printC ) ;
ret urn 0;
}
/
123
A.13 Polynomes
#include<s t di o . h>
#include<s t d l i b . h>
#include<mal l oc . h>
#include<math . h>
#include polynomes . h
//
/
Retourne un polynome vi de .
/
l i nke dLi s t makePolynome ( )
{
return l i nke dLi s t Cr e at e ( ) ;
}
//
/
Al l oue dynamiquement un emplacement pour une var i abl e de t ype
doubl e , y af f e c t e d et ret ourne c e t t e adresse .
/
double makeDouble( double d)
{
double p = ( double) mal l oc ( si zeof ( double ) ) ;
i f ( p == NULL)
e xi t ( 0 ) ;
p = ( double) d ;
return p ;
}
//
/
Al l oue dynamiquement un emplacement pour une var i abl e de t ype
doubl e , y af f e c t e d et ret ourne c e t t e adresse .
/
void makeDoubleWithVoid( void v)
{
return makeDouble( ( double) v ) ;
}
//
/
Desal l oue une var i abl e de t ype doubl e .
/
void destroyDoubl e ( void v)
{
f r e e ( ( double) v ) ;
}
//
/
Retourne une copi e de l , copi e aussi l e s c o e f f i c i e nt s .
/
l i nke dLi s t copyPolynome ( l i nke dLi s t l )
{
return l i nkedLi stMap ( l , makeDoubleWithVoid) ;
}
//
/
Det rui t l e polynome l et ses c oe f f i c i e nt s .
/
void destroyPol ynome ( l i nke dLi s t l )
{
l i nke dLi s t De s t r oy ( l , destroyDoubl e ) ;
}
//
124
/
Af f i che l e monome c oe f f xdegre proprement , f i r s t Pr i nt ed
es t vrai s i et seul ement s i ce monome es t l e premier af f i c he
dans l e polynome .
/
i nt printMonome( double c oe f f , i nt degre , i nt f i r s t Pr i nt e d )
{
i f ( c o e f f != 0. 0)
{
i f ( f i r s t Pr i nt e d && c o e f f > 0. 0)
pr i nt f ( + ) ;
i f ( c oe f f <0. 0)
pr i nt f ( ) ;
pr i nt f ( %4.2 l f , ( c oe f f >0)? c o e f f :c o e f f ) ;
i f ( degre > 0)
pr i nt f ( x ) ;
i f ( degre > 1)
pr i nt f ( ) ;
i f ( degre > 1)
pr i nt f ( %d , degre ) ;
return 1;
}
return 0;
}
//
/
Af f i che polynome l e pl us proprement pos s i b l e .
/
void pri ntPol ynome ( l i nke dLi s t polynome )
{
i nt degre = 0 , f i r s t Pr i nt e d = 0;
void f ( void c o e f f )
{
i f ( printMonome ( ( double) c oe f f , degre , f i r s t Pr i nt e d ) )
f i r s t Pr i n t e d = 1;
degre++;
}
l i nkedLi st Appl y ( polynome , f ) ;
pr i nt f ( \n ) ;
}
//
/
Supprime l e s O non s i g n i f i c a t i f s

A l a f i n du polyn

Ame .
/
void ski pZerosPol ynome( l i nke dLi s t l )
{
}
//
/
Retourne l e degre de l .
/
i nt degreePol ynome( l i nke dLi s t l )
{
i nt n ;
ski pZerosPol ynome( l ) ;
n = l i nke dLi s t Ge t Si z e ( l ) ;
i f ( n != 1)
return n ;
return ( ( double) l i nke dLi s t Ge t Fi r s t ( l )>data != 0) 1;
}
//
/
Ajoute un monome de c o e f f i c i e nt c oe f f a l a f i n du polynome , f ai s ant
ai ns i crout re son degre de 1.
/
void appendCoeffPolynome ( l i nke dLi s t polynome , double c o e f f )
{
125
double p = mal l oc ( si zeof ( double ) ) ;
i f ( p == NULL)
e xi t ( 0 ) ;
p = c o e f f ;
l i nkedLi stAppend ( polynome , p ) ;
}
//
/
Cree et ret ourne l e polynome de degre n1 dont l e s
c o e f f i c i e n t s sont passes dans l e t abl eau d .
/
l i nke dLi s t makeArrayPolynome( double d , i nt n)
{
l i nke dLi s t l = makePolynome ( ) ;
i nt i ;
for ( i = 0 ; i < n ; i ++)
appendCoeffPolynome ( l , ( d + i ) ) ;
return l ;
}
//
/
Retourne l e polynome nul .
/
l i nke dLi s t zeroPol ynome ( )
{
l i nke dLi s t l = makePolynome ( ) ;
appendCoeffPolynome ( l , 0 . 0 ) ;
return l ;
}
//
/
Retourne l e polynome uni t e .
/
l i nke dLi s t uni tPol ynome ( )
{
l i nke dLi s t l = makePolynome ( ) ;
appendCoeffPolynome ( l , 1 . 0 ) ;
return l ;
}
//
/
Retourne l e polynome
0 + X + 2X2 + 3X3 + . . . + iX i + . . . + nXn
/
l i nke dLi s t si mpl eLi stPol ynome ( i nt n)
{
l i nke dLi s t l ;
i f ( n == 0)
return zeroPol ynome ( ) ;
l = si mpl eLi stPol ynome ( n 1 ) ;
appendCoeffPolynome ( l , n ) ;
return l ;
}
//
/
Ajoute l a const ant e d au polynome l .
/
void addRealPolynome( l i nke dLi s t l , double d)
{
l i nk l nk = l i nke dLi s t Ge t Fi r s t ( l ) ;
i f ( l nk != NULL)
( double) l nk>data += d ;
el se
appendCoeffPolynome ( l , d ) ;
}
126
//
/
Mul t i pl i e l e polynome l par l e r e el d .
/
void multRealPolynome( l i nke dLi s t l , double d)
{
void mul ti pl yDoubl e ( void v)
{
( double) v = d ;
}
l i nkedLi st Appl y ( l , mul ti pl yDoubl e ) ;
}
//
/
Mul t i pl i e l e polynome l par Xn
/
void multXNPolynome ( l i nke dLi s t l , i nt n)
{
i f ( n > 0)
{
l i nkedLi st Push ( l , makeDouble ( 0 . 0 ) ) ;
multXNPolynome ( l , n 1) ;
}
}
//
/
Mul t i pl i e l e polynome l par c oe f f Xexp
/
void multMonomePolynome ( l i nke dLi s t l , double c oe f f , i nt exp)
{
multRealPolynome( l , c o e f f ) ;
multXNPolynome ( l , exp ) ;
}
//
/
Additionne deux

A deux t ous l e s mai l l ons des deux l i s t e s l a
et l b . Concatene l e r e s ul t at a l a l i s t e r e s ul t .
/
void addMai l l ons ( l i nk l a , l i nk l b , l i nke dLi s t r e s ul t )
{
i f ( l a != NULL && l b != NULL)
{
appendCoeffPolynome ( r e s ul t , ( double) l a>data
+ ( double) l b>data ) ;
addMai l l ons ( l a>next , l b>next , r e s ul t ) ;
}
el se
{
i f ( l a != NULL)
{
appendCoeffPolynome ( r e s ul t , ( double) l a>data ) ;
addMai l l ons ( l a>next , NULL, r e s ul t ) ;
}
i f ( l b != NULL)
{
appendCoeffPolynome ( r e s ul t , ( double) l b>data ) ;
addMai l l ons (NULL, l b>next , r e s ul t ) ;
}
}
}
//
/
Addi t i one l es deux polynomes a et b , ret ourne c e t t e somme.
/
l i nke dLi s t addPolynome( l i nke dLi s t a , l i nke dLi s t b)
{
l i nke dLi s t r e s ul t = makePolynome ( ) ;
127
addMai l l ons ( l i nke dLi s t Ge t Fi r s t ( a ) ,
l i nke dLi s t Ge t Fi r s t ( b) ,
r e s ul t ) ;
return r e s u l t ;
}
//
/
Mul t i pl i e a et b avec l a recurrence
( a 0 + a 1X + . . . + a nXn)Q(X)
= a 0 Q(X) + X ( a 1 + a 2 X. . . + a n X(n1)) Q(X)
/
l i nke dLi s t slowMultPolynome( l i nke dLi s t a , l i nke dLi s t b)
{
l i nke dLi s t temp1 = NULL;
l i nke dLi s t r e s = zeroPol ynome ( ) ;
i nt n = 0;
void auxFuncti on ( void v)
{
l i nke dLi s t temp2 = copyPolynome ( b ) ;
multMonomePolynome ( temp2 , ( double) v , n ) ;
temp1 = addPolynome( res , temp2 ) ;
destroyPol ynome ( r e s ) ;
destroyPol ynome ( temp2 ) ;
r e s = temp1 ;
n++;
}
l i nkedLi st Appl y ( a , auxFuncti on ) ;
return r e s ;
}
//
/
Fonction au x i l i a i r e pour l e sousprogramme ci dessous .
/
void mul tMai l l ons ( l i nk l a , l i nk l b , l i nke dLi s t r e s ul t )
{
pComplexe p ;
i f ( l a != NULL)
{
p = copyComplexe (
multComplexe (
( pComplexe) l a>data ,
( pComplexe) l b>data ) ) ;
l i nkedLi stAppend ( r e s ul t , p ) ;
mul tMai l l ons ( l a>next , l b>next , r e s ul t ) ;
}
}
//
/
Mul t i pl i e ent re eux t ous l e s c oe f f i c i e nt s ( compl exes ) des monomes de
meme degre , par exemple :
(1 + 2X + 4X2) et (3 + X 2X2) donnent
(1 3) + (2 1)X + (4 2)X2
a et b sont necessai rement de meme degre .
/
l i nke dLi s t multMonomesPolynome( l i nke dLi s t a , l i nke dLi s t b)
{
l i nke dLi s t l = makePolynome ( ) ;
mul tMai l l ons ( l i nke dLi s t Ge t Fi r s t ( a ) ,
l i nke dLi s t Ge t Fi r s t ( b) ,
l ) ;
return l ;
}
//
/
Convert i t un doubl e en poi nt eur sur complexe .
/
void complexOfDouble ( void v)
{
return copyComplexe ( makeAffComplexe ( ( double) v , 0 . 0 ) ) ;
128
}
//
/
Convert i t un complexe en doubl e , supprime
l a par t i e i magi nai re .
/
void doubleOfComplexe ( void v)
{
return makeDouble( reComplexe ( ( pComplexe) v ) ) ;
}
//
/
Det rui t un nombre complexe .
/
void destroyCompl exe ( void v)
{
f r e e ( ( pComplexe) v ) ;
}
//
/
Retourne l a premier pui sance de 2 superi eure ou egal a x .
/
i nt puiss2UpperThan ( i nt x)
{
i nt k = 2;
while ( k < x)
k = 2;
return k ;
}
//
/
Ajoute des zeros non s i g n i f i c a t i f s a l a f i n de l de s or t e
que sa t a i l l e devienne k .
/
void r e s i z e Li s t ( l i nke dLi s t l , i nt k)
{
while ( l i nke dLi s t Ge t Si z e ( l ) < k)
l i nkedLi stAppend ( l ,
copyComplexe ( makeAffComplexe ( 0. 0 , 0 . 0 ) ) ) ;
}
//
/
Modifie l e s t a i l l e s des deux l i s t e s de s or t e
qu on pui sse l eur appl i quer une FFT
/
void c a l i br a t e Li s t s ( l i nke dLi s t l 1 , l i nke dLi s t l 2 )
{
i nt k ;
i nt l engt h = l i nke dLi s t Ge t Si z e ( l 1 ) +
l i nke dLi s t Ge t Si z e ( l 2 ) 1;
k = puiss2UpperThan ( l engt h ) ;
r e s i z e Li s t ( l 1 , k ) ;
r e s i z e Li s t ( l 2 , k ) ;
}
//
/
Mul t i pl e a et b en passant par une t ransf ormee de f our i er .
/
l i nke dLi s t multPolynome ( l i nke dLi s t a , l i nke dLi s t b)
{
l i nke dLi s t ca , cb , f f t a , f f t b , prodab , resComplexe , r e s ;
ca = l i nkedLi stMap ( a , complexOfDouble ) ;
cb = l i nkedLi stMap ( a , complexOfDouble ) ;
129
c a l i b r a t e Li s t s ( ca , cb ) ;
f f t a = FFT( ca ) ;
f f t b = FFT( cb ) ;
prodab = multMonomesPolynome( f f t a , f f t b ) ;
resCompl exe = i nverseFFT( prodab ) ;
r e s = l i nkedLi stMap ( resComplexe , doubleOfComplexe ) ;
l i nke dLi s t De s t r oy ( ca , destroyCompl exe ) ;
l i nke dLi s t De s t r oy ( cb , destroyCompl exe ) ;
l i nke dLi s t De s t r oy ( f f t a , destroyCompl exe ) ;
l i nke dLi s t De s t r oy ( f f t b , destroyCompl exe ) ;
l i nke dLi s t De s t r oy ( prodab , destroyCompl exe ) ;
l i nke dLi s t De s t r oy ( resComplexe , destroyCompl exe ) ;
return r e s ;
}
//
/
Eval ue l e polynome l en x avec l a methode de Horner .
/
double hornerLi nk ( l i nk l nk , double x)
{
i f ( l nk == NULL)
return 0 . 0 ;
return ( double) l nk>data +
xhornerLi nk ( l nk>next , x ) ;
}
//
/
Eval ue l e polynome l en x avec l a methode de Horner .
/
double eval uatePol ynome ( l i nke dLi s t l , double x)
{
return hornerLi nk ( l i nke dLi s t Ge t Fi r s t ( l ) , x ) ;
}
//
i nt main ( )
{
l i nke dLi s t l = si mpl eLi stPol ynome ( 10000) ;
//makeArrayPolynome(d , 5) ;
l i nke dLi s t m, n , p ;
pr i nt f ( mul t i pl i c at i on \n ) ;
m = slowMultPolynome( l , l ) ;
pr i nt f ( done\n ) ;
//printPolynome (m) ;
pr i nt f ( mul t i pl i c at i on \n ) ;
n = multPolynome ( l , l ) ;
pr i nt f ( done\n ) ;
//printPolynome (m) ;
multRealPolynome( n , 1);
p = addPolynome(m, n ) ;
pr i nt f ( t e s t : %l f \n , eval uatePol ynome ( p , 1 . 0 ) ) ;
destroyPol ynome ( l ) ;
destroyPol ynome (m ) ;
destroyPol ynome ( n ) ;
return 0;
}
130
A.14 Tas binomiaux
Voici une implementation des tas binomiaux, jai commence par ecrire quelques fonctions de gestion de listes chanees,
et jai cree deux classes pour representer respectivement les arbres binomiaux et les tas binomiaux.
/
Implements a very si mpl e l i nked l i s t , each l i nk poi nt s t o item
of t ype T and ref erences t he next l i nk . O(1) operat i ons are
g e t t i ng t he f i r s t l i nk s data or t he second s l i nk ref erence ,
or de l e t i ng t he f i r s t el ement . Each f unct i ons modifying t he
l i nk i ng ret urns a poi nt er t o t he f i r s t l i nk of t he l i s t .
/
public cl ass Li nkedLi st <T>
{
/ /
private T data ;
/ /
private Li nkedLi st <T> next ;
/ /
/
Creates a one el ement l i s t .
/
public Li nkedLi st (T data )
{
thi s . data = data ;
}
/ /
/
Creates a one l i nk l i s t and appends t he second
paramter t o t h i s l i s t .
/
public Li nkedLi st (T data , Li nkedLi st <T> next )
{
thi s ( data ) ;
thi s . next = next ;
}
/ /
/
Modi f i es t he data .
/
public void setData (T data )
{
thi s . data = data ;
}
/ /
/
Appends a l i s t t o t he f i r s t l i nk of t he current
l i s t .
/
public void setNext ( Li nkedLi st <T> next )
{
thi s . next = next ;
}
/ /
/
Ret ri ves t he data of t he f i r s t l i nk .
/
public T getData ( )
{
return data ;
}
131
/ /
/
Returns t he second item of t he l i s t , doesn t change
t he l i nk i ng
/
public Li nkedLi st <T> getNext ( )
{
return next ;
}
/ /
/
Del et e from t h i s l i s t t he l i nk which t he adress i s l ,
ret urns t he l i s t whi t hout l .
/
public Li nkedLi st <T> de l e t e Li nk( Li nkedLi st <T> l )
{
i f ( thi s == l )
return getNext ( ) ;
setNext ( getNext ( ) . de l e t e Li nk( l ) ) ;
return thi s ;
}
/ /
/
Returns a St ri ng represent at i on of t he l i s t .
/
public St r i ng t oSt r i ng ( )
{
return > + data +
( ( next != nul l ) ? next . t oSt r i ng ( ) : X ) ;
}
/ /
private stati c <K> Li nkedLi st <K> r ever seAcc ( Li nkedLi st <K> l i nk ,
Li nkedLi st <K> acc )
{
i f ( l i nk == nul l )
return acc ;
Li nkedLi st <K> next = l i nk . getNext ( ) ;
l i nk . setNext ( acc ) ;
return r ever seAcc ( next , l i nk ) ;
}
/ /
/
Adds t he l i nk l i n f r ont of t hi s l i s t , ret urns
t he l i s t t hus creat ed .
/
public Li nkedLi st <T> addFront ( Li nkedLi st <T> l )
{
l . setNext ( thi s ) ;
return l ;
}
/ /
/
Adds t he item o i n f r ont of t hi s l i s t , ret urns
t he new l i s t .
/
public Li nkedLi st <T> addFront (T o )
{
return addFront (new Li nkedLi st <T>(o ) ) ;
}
/ /
/
Reverse t he order of t he items of t he l i s t . Returns t he
132
new l i s t .
/
public Li nkedLi st <T> r e ve r s e ( )
{
return r ever seAcc ( this , nul l ) ;
}
}
cl ass Bi nomi al Tree<T extends Comparable<T>>
implements Comparable<Bi nomi al Tree<T>>
{
/ /
private i nt or der ;
/ /
private T data ;
/ /
private Li nkedLi st <Bi nomi al Tree<T>> sons ;
/ /
public Bi nomi al Tree (T data )
{
thi s . data = data ;
or der = 0;
sons = nul l ;
}
/ /
public Bi nomi al Tree<T> f us i on ( Bi nomi al Tree<T> ot her )
{
i f ( getData ( ) . compareTo ( ot her . getData ( ) ) > 0)
return ot her . f us i on ( thi s ) ;
i f ( or der != ot her . getOrder ( ) )
System . out . pr i nt l n ( I nval i d arguments ) ;
sons = ( sons == nul l ) ?
new Li nkedLi st <Bi nomi al Tree<T>>(ot her ) :
sons . addFront ( ot her ) ;
or der++;
return thi s ;
}
/ /
public i nt getOrder ( )
{
return or der ;
}
/ /
public T getData ( )
{
return data ;
}
/ /
public BinomialHeap<T> ext r act Sons ( )
{
return new BinomialHeap<T>(( sons == nul l ) ?
nul l :
sons . r e ve r s e ( )
) ;
}
/ /
public i nt compareTo ( Bi nomi al Tree<T> ot her )
{
i f ( or der < ot her . getOrder ( ) )
return 1;
i f ( or der == ot her . getOrder ( ) )
133
return 0;
return 1;
}
}
/
Implements a pr i or i t y queue which al l ows t he f ol l owi ng operat i ons ,
each one i n a i n O( l og n) time .
i ns er t i ng an item
g e t t i ng t he minimum key item
de l e t i ng t he minimum key item
merging two queues
I t has been implemented by al exandremesl e . com f or j ava 1. 5
/
public cl ass BinomialHeap<T extends Comparable<T>>
{
/ /
private Li nkedLi st <Bi nomi al Tree<T>> bi nomi al Tr ees ;
/ /
/
Creates an empty queue .
/
public BinomialHeap ( )
{
bi nomi al Tr ees = nul l ;
}
/ /
/
Creates a one item queue .
/
public BinomialHeap (T data )
{
bi nomi al Tr ees = new Li nkedLi st <Bi nomi al Tree<T>>
(new Bi nomi al Tree<T>(data ) ) ;
}
/ /
BinomialHeap ( Li nkedLi st <Bi nomi al Tree<T>> l )
{
bi nomi al Tr ees = l ;
}
/ /
/
Returns t rus i f and onl y i f t he queue doesn t cont ai n
any item .
/
public boolean isEmpty( )
{
return bi nomi al Tr ees == nul l ;
}
/ /
private stati c <K extends Comparable<K>> Li nkedLi st <Bi nomi al Tree<K>>
f i ndMi nLi nk ( Li nkedLi st <Bi nomi al Tree<K>> l i nk ,
Li nkedLi st <Bi nomi al Tree<K>> acc )
{
i f ( l i nk == nul l )
return acc ;
K l i nkData = l i nk . getData ( ) . getData ( ) ;
K accData = acc . getData ( ) . getData ( ) ;
i f ( l i nkData . compareTo ( accData ) < 1)
return f i ndMi nLi nk ( l i nk . getNext ( ) , l i nk ) ;
return f i ndMi nLi nk ( l i nk . getNext ( ) , acc ) ;
}
/ /
134
/
Returns t he item wich has t he minimum key .
/
public T getMin ( )
{
Li nkedLi st <Bi nomi al Tree<T>> minNode = f i ndMi nLi nk ( bi nomi al Trees ,
bi nomi al Tr ees ) ;
i f ( minNode == nul l )
return nul l ;
return minNode . getData ( ) . getData ( ) ;
}
/ /
/
Del et es t he minimum key item .
/
public void del eteMi n ( )
{
Li nkedLi st <Bi nomi al Tree<T>> minLink =
f i ndMi nLi nk ( bi nomi al Trees , bi nomi al Tr ees ) ;
bi nomi al Tr ees = bi nomi al Tr ees . de l e t e Li nk( minLink ) ;
BinomialHeap<T> sons = minLink . getData ( ) . ext r act Sons ( ) ;
f us i on ( sons ) ;
}
/ /
/
Del et es t he minimum key item .
/
public void i ns e r t (T c )
{
f us i on (new BinomialHeap<T>(c ) ) ;
}
/ /
/
Adds t o t he current queue a l l t he item of t he queue b .
Use i t onl y i f b doesn t have t o used again .
/
public void f us i on ( BinomialHeap<T> b)
{
bi nomi al Tr ees =
cl ean ( merge ( bi nomi al Trees , b . bi nomi al Tr ees ) ) ;
}
/ /
private stati c <K extends Comparable<K>> Li nkedLi st <Bi nomi al Tree<K>>
merge ( Li nkedLi st <Bi nomi al Tree<K>> l 1 ,
Li nkedLi st <Bi nomi al Tree<K>> l 2 )
{
i f ( l 1 == nul l )
return l 2 ;
i f ( l 2 == nul l )
return l 1 ;
i f ( l 1 . getData ( ) . compareTo ( l 2 . getData ( ) ) <= 0)
{
l 1 . setNext ( merge ( l 1 . getNext ( ) , l 2 ) ) ;
return l 1 ;
}
el se
return merge ( l 2 , l 1 ) ;
}
/ /
private stati c <K extends Comparable<K>> Li nkedLi st <Bi nomi al Tree<K>>
cl ean ( Li nkedLi st <Bi nomi al Tree<K>> l )
{
i f ( l == nul l )
return nul l ;
i f ( l . getNext ( ) == nul l )
return l ;
135
Bi nomi al Tree<K> f i r s t = l . getData ( ) ;
Bi nomi al Tree<K> second = l . getNext ( ) . getData ( ) ;
i f ( f i r s t . getOrder ( ) != second . getOrder ( ) )
{
l . setNext ( cl ean ( l . getNext ( ) ) ) ;
return l ;
}
i f ( l . getNext ( ) . getNext ( ) == nul l )
return new Li nkedLi st <Bi nomi al Tree<K>>
( f i r s t . f us i on ( second ) ,
l . getNext ( ) . getNext ( ) ) ;
Bi nomi al Tree<K> t hi r d = l . getNext ( ) . getNext ( ) . getData ( ) ;
i f ( f i r s t . getOrder ( ) == t hi r d . getOrder ( ) )
{
l . setNext ( cl ean ( l . getNext ( ) ) ) ;
return l ;
}
el se
return new Li nkedLi st <Bi nomi al Tree<K>>
( f i r s t . f us i on ( second ) ,
l . getNext ( ) . getNext ( ) ) ;
}
/ /
/
publ i c s t a t i c voi d main( St ri ng [ ] args )
{
BinomialHeap<Int eger > h = new BinomialHeap<Int eger >();
f or ( i nt i = 1 ; i < 3000 ; i ++)
h . i ns er t (new Int eger (( i i i i i i i ) % 127));
whi l e ( ! h . isEmpty ( ) )
{
System. out . pr i nt (h . getMin () + > ) ;
h . del et eMi n ( ) ;
}
}
/
}
136
A.15 AVL
#include<s t di o . h>
#include<mal l oc . h>
#include avl . h
//
/
Noeud de l ABR.
/
typedef struct nd
{
/
key es t l a cl e du noeud courant .
/
i nt key ;
/
poi nt eur vers l el ement de cl e key
/
void data ;
/
hauteur du sousarbre :
0 s i ce noeud es t une f e u i l l e .
/
i nt hei ght ;
/
Pointeur vers l e sousarbre dr oi t .
/
struct nd l e f t ;
/
Pointeur vers l e sousarbre gauche .
/
struct nd r i ght ;
}node ;
//
/
Retourne l a hauteur de l arbre de raci ne l ,
1 s i l es t vi de .
/
i nt get Hei ght ( node l )
{
i f ( l == NULL)
return 1;
return l >hei ght ;
}
//
/
Retourne l a pl us grande des deux val eurs i et j .
/
i nt max( i nt i , i nt j )
{
i f ( i < j )
return j ;
return i ;
}
//
/
Met a j our l a hauteur de l a raci ne l en f onct i on des
haut eurs des raci nes des deux sousarbres .
/
void set Hei ght ( node l )
{
i f ( l != NULL)
{
l >hei ght = 1 + max( get Hei ght ( l >l e f t ) , get Hei ght ( l >r i ght ) ) ;
}
137
}
//
/
Cree un noeud contenant l a donnee data ,
ayant pour sousarbre gauche l et
pour sousarbre dr oi t r .
/
node nodeCreate ( i nt ( getKey ) ( void) , node l , void data , node r )
{
node n = ( node ) mal l oc ( si zeof ( node ) ) ;
i f ( n == NULL)
e r r or ( ) ;
n>data = data ;
n>l e f t = l ;
n>r i ght = r ;
n>key = getKey( data ) ;
set Hei ght ( n ) ;
return n ;
}
//
/
Retourne un avl vi de
/
avl avl Cr eat e ( i nt ( getKey ) ( void) , void ( f r eeDat a ) ( void) )
{
avl a = ( avl ) mal l oc ( si zeof ( avl ) ) ;
i f ( ! a)
e r r or ( ) ;
a>getKey = getKey ;
a>f r eeDat a = f r eeDat a ;
a>r oot = NULL;
return a ;
}
//
/
Fai t de f reeDat a l a f onct i on de des t r uct i on des donnees .
/
void avl Set Fr eeFunct i on( avl a , void ( f r eeDat a ) ( void) )
{
a>f r eeDat a = f r eeDat a ;
}
//
/
Af f i che t out es l e s c l es du sousarbre de raci ne n dans
l ordre cr oi s s ant .
/
void nodePri ntKeys ( node n)
{
i f ( n)
{
pr i nt f ( ( ) ;
nodePri ntKeys ( n>l e f t ) ;
pr i nt f ( , %d , , n>key ) ;
nodePri ntKeys ( n>r i ght ) ;
pr i nt f ( ) ) ;
}
}
//
/
Af f i che pour t ous l e s noeuds du sousarbre de raci ne n
l a di f f er ence ent re l e s haut eurs du sousarbre dr oi t et
gauche .
/
void nodePr i nt Level s ( node n)
{
i f ( n)
138
{
pr i nt f ( ( ) ;
nodePr i nt Level s ( n>l e f t ) ;
pr i nt f ( , %d , , get Hei ght ( n>l e f t ) get Hei ght ( n>r i ght ) ) ;
nodePr i nt Level s ( n>r i ght ) ;
pr i nt f ( ) ) ;
}
}
//
/
Ef f ect ue une r ot at i on dr oi t e de l arbre de raci ne x ,
ret ourne l a raci ne de l arbre apres r ot at i on .
/
node r ot at eRi ght ( node x)
{
node y = x>l e f t ;
node b = y>r i ght ;
y>r i ght = x ;
x>l e f t = b ;
set Hei ght ( x ) ;
set Hei ght ( y ) ;
return y ;
}
//
/
Ef f ect ue une r ot at i on gauche de l arbre de raci ne x ,
ret ourne l a raci ne de l arbre apres r ot at i on .
/
node r ot at e Le f t ( node x)
{
node y = x>r i ght ;
node b = y>l e f t ;
y>l e f t = x ;
x>r i ght = b ;
set Hei ght ( x ) ;
set Hei ght ( y ) ;
return y ;
}
//
/
Ef f ect ue une r ot at i on gauchedr oi t e de l arbre de raci ne x ,
ret ourne l a raci ne de l arbre apres r ot at i on .
/
node r ot at e Le f t Ri ght ( node x)
{
x>l e f t = r ot at e Le f t ( x>l e f t ) ;
return r ot at eRi ght ( x ) ;
}
//
/
Ef f ect ue une r ot at i on droi t e gauche de l arbre de raci ne x ,
ret ourne l a raci ne de l arbre apres r ot at i on .
/
node r ot at e Ri ght Le f t ( node x)
{
x>r i ght = r ot at eRi ght ( x>r i ght ) ;
return r ot at e Le f t ( x ) ;
}
//
/
Reequi l i bre l arbre de raci ne x , ret ourne l a raci ne de
l arbre apres r e equi l i b r ag e . On part du pri nci pe
que l e s haut eurs des sousarbres dr oi t et gauche d i f f e r e nt
de au pl us 1.
/
node bal ance ( node x)
139
{
i f ( x != NULL)
{
set Hei ght ( x ) ;
i f ( get Hei ght ( x>l e f t ) + 2 == get Hei ght ( x>r i ght ) )
{
i f ( get Hei ght ( x>l e f t ) + 1 == get Hei ght ( x>r i ght >r i ght ) )
return r ot at e Le f t ( x ) ;
el se
return r ot at e Ri ght Le f t ( x ) ;
}
i f ( get Hei ght ( x>l e f t ) == get Hei ght ( x>r i ght ) + 2)
{
i f ( get Hei ght ( x>l e f t >l e f t ) == get Hei ght ( x>r i ght ) + 1)
return r ot at eRi ght ( x ) ;
el se
return r ot at e Le f t Ri ght ( x ) ;
}
}
return x ;
}
//
/
Insere l a donnee v dans l arbre de raci ne n
et r e e q ui l i b r e l arbre , ret ourne l a raci ne de
l arbre apres i ns er t i on et r e equi l i br age .
/
node nodeI nser t ( i nt ( key ) ( void) , node n , void v)
{
i f ( n == NULL)
return nodeCreate ( key , NULL, v , NULL) ;
i f ( key ( v) == n>key )
return n ;
i f ( key ( v) < n>key )
n>l e f t = nodeI nser t ( key , n>l e f t , v ) ;
el se
n>r i ght = nodeI nser t ( key , n>r i ght , v ) ;
return bal ance ( n ) ;
}
//
/
Insere l a donnee v dans l arbre a , O( l og n) .
/
void av l I ns e r t ( avl a , void v)
{
a>r oot = nodeI nser t ( a>getKey , ( node ) a>root , v ) ;
}
//
/
Af f i che l e s c l es de l AVL a dans l ordre croi ssant , O(n)
/
void avl Pri ntKeys ( avl a)
{
nodePri ntKeys ( ( node ) a>r oot ) ;
pr i nt f ( \n ) ;
}
//
/
Af f i che pour chaque noeud l a di f f er ence ent re l e s haut eurs
des sousarbres dr oi t et gauche de l AVL.
/
void avl Pr i nt Le ve l s ( avl a )
{
nodePr i nt Level s ( ( node ) a>r oot ) ;
pr i nt f ( \n ) ;
}
//
140
/
Retourne l a donnee de cl e k s i e l l e se t rouve dans l e sousarbre
de raci ne n, NULL sinon .
/
void f i ndNode ( node n , i nt k)
{
i f ( n == NULL)
return NULL;
i f ( n>key == k)
return n>data ;
i f ( k < n>key )
return f i ndNode ( n>l e f t , k ) ;
el se
return f i ndNode ( n>r i ght , k ) ;
}
//
/
Retourne l a donnee de cl e x s i e l l e se t rouve dans l AVL a ,
NULL sinon , O( l og n)
/
void avl Fi nd ( avl a , i nt x)
{
return f i ndNode ( ( node ) a>root , x ) ;
}
//
/
Fai t poi nt er max vers l e noeud de cl e maximale dans
l e sousarbre de raci ne n, det ache l e noeud max de l arbre
et ret ourne l a raci ne de l arbre apres suppressi on .
/
node removeMax( node n , node max)
{
i f ( n == NULL)
{
max = NULL;
return NULL;
}
i f ( n>r i ght == NULL)
{
max = n ;
return NULL;
}
n>r i ght = removeMax( n>r i ght , max ) ;
return bal ance ( n ) ;
}
//
/
Fai t poi nt er min vers l e noeud de cl e minimale dans
l e sousarbre de raci ne n, det ache l e noeud min de l arbre
et ret ourne l a raci ne de l arbre apres suppressi on .
/
node removeMin ( node n , node min)
{
i f ( n == NULL)
{
min = NULL;
return NULL;
}
i f ( n>l e f t == NULL)
{
min = n ;
return NULL;
}
n>l e f t = removeMin ( n>l e f t , min ) ;
return bal ance ( n ) ;
}
//
/
Supprime l e noeud de cl e k du sousarbre de raci ne n,
141
appl i que l a f onct i on de des t r uct i on a l a donnee de ce noeud ,
et ret ourne l a raci ne de l arbre apres l a suppressi on .
/
node removeNode( node n , i nt k , void ( f r eeDat a ) ( void) )
{
node p ;
i f ( n == NULL)
return NULL;
i f ( k == n>key )
{
p = NULL;
n>l e f t = removeMax( n>l e f t , &p ) ;
i f ( p == NULL)
n>r i ght = removeMin ( n>r i ght , &p ) ;
i f ( p != NULL)
{
p>l e f t = n>l e f t ;
p>r i ght = n>r i ght ;
}
f r eeDat a ( n>data ) ;
f r e e ( n ) ;
return bal ance ( p ) ;
}
i f ( k < n>key )
n>l e f t = removeNode( n>l e f t , k , f r eeDat a ) ;
el se
n>r i ght = removeNode( n>r i ght , k , f r eeDat a ) ;
return bal ance ( n ) ;
}
//
/
Supprime l e noeud de cl e k de l AVL a , appl i que l a f onct i on
de des t r uct i on a l a donnee de cl e k , O( l og n) .
/
void avlRemove ( avl a , i nt k)
{
a>r oot = removeNode( ( node ) a>root , k , a>f r eeDat a ) ;
}
//
/
Pl ace dans l a l i s t e chai nee l t out es l e s donnees
du sousarbre de raci ne n dans l ordre cr oi s s ant .
/
void nodeToLi st ( node n , l i nke dLi s t l )
{
i f ( n != NULL)
{
nodeToLi st (n>l e f t , l ) ;
l i nkedLi stAppend ( l , n>data ) ;
nodeToLi st (n>r i ght , l ) ;
}
}
//
/
Retourne une l i s t e chai nee contenant t out es l e s donnees
de l AVL a di sposees dans l ordre croi ssant , O(n) .
/
l i nke dLi s t avl ToLi st ( avl a)
{
l i nke dLi s t l = l i nke dLi s t Cr e at e ( ) ;
nodeToLi st ( ( node ) a>root , l ) ;
return l ;
}
//
/
Det rui t t ous l e s noeuds du sousarbre de raci ne n,
appl i que l a f onct i on de des t r uct i on f r a t out es l e s
donnees du sousarbre .
/
142
void nodeDestroy ( node n , void ( f r ) ( void) )
{
i f ( n != NULL)
{
nodeDestroy ( n>l e f t , f r ) ;
nodeDestroy ( n>r i ght , f r ) ;
f r ( n>data ) ;
f r e e ( n ) ;
}
}
//
/
Det rui t l AVL a , appl i que l a f onct i on de des t r uct i on a
t out es l e s donnees du sousarbre , O(n) .
/
void avl Dest r oy ( avl a)
{
nodeDestroy ( ( node) a>root , a>f r eeDat a ) ;
f r e e ( a ) ;
}
//
//
/
Pour t e s t e r l es al gori t hmes
/
void de s t r oyI nt ( void i )
{
f r e e ( ( i nt ) i ) ;
}
i nt getIntKey( void i )
{
return ( ( i nt ) i ) ;
}
void doNothing ( )
{
}
i nt main ( )
{
i nt i ;
i nt d ;
l i nke dLi s t l ;
l i nk m;
avl a = avl Cr eat e ( getIntKey , de s t r oyI nt ) ;
for ( i = 0 ; i < 40 ; i ++)
{
d = ( i nt ) mal l oc ( si zeof ( i nt ) ) ;
d = i ;
avl I ns e r t ( a , d ) ;
}
avl Pri ntKeys ( a ) ;
avl Pr i nt Le ve l s ( a ) ;
for ( i = 0 ; i < 40 ; i +=5)
avlRemove ( a , i ) ;
avl Pri ntKeys ( a ) ;
avl Pr i nt Le ve l s ( a ) ;
l = avl ToLi st ( a ) ;
for (m = l i nke dLi s t Ge t Fi r s t ( l ) ; m != NULL ; m = m>next )
pr i nt f ( %d > , ( i nt ) (m>data ) ) ;
pr i nt f ( \n ) ;
l i nke dLi s t De s t r oy ( l , doNothing ) ;
avl Set Fr eeFunct i on( a , de s t r oyI nt ) ;
avl Dest r oy ( a ) ;
return 0;
}
143
A.16 Knapsack par recherche exhaustive
#include l i nke dLi s t . h
#include<s t di o . h>
#include<s t d l i b . h>
#include<mal l oc . h>
//
/
Inst ance d un probl eme de knapSack
/
typedef struct
{
/
nombre t ot a l d ob j e t s
/
long nbItems ;
/
t abl eau de nombreObjets el ement s contenant l e poi ds de
chaque el ement
/
long wei ght s ;
/
t abl eau de nombreObjets el ement s contenant l a val eur de
chaque el ement
/
long val ues ;
/
Poids maximum qu i l es t pos s i b l e de pl acer dans l e sac

A dos .
/
long maxWeight ;
}knapSack ;
//
knapSack knapSackMake ( long nbItems , long maxWeight )
{
knapSack k = ( knapSack) mal l oc ( si zeof ( knapSack ) ) ;
k>nbItems = nbItems ;
k>maxWeight = maxWeight ;
k>wei ght s = ( long) mal l oc ( si zeof ( long) nbItems ) ;
i f ( k>wei ght s == NULL)
e xi t ( 0 ) ;
k>val ues = ( long) mal l oc ( si zeof ( long) nbItems ) ;
i f ( k>val ues == NULL)
e xi t ( 0 ) ;
return k ;
}
//
void knapSackSetItem( knapSack k , long i ndex , long val ue , long wei ght )
{
( k>wei ght s + i ndex ) = wei ght ;
( k>val ues + i ndex ) = val ue ;
}
//
long knapSackValue ( knapSack i nst ance , l i nke dLi s t s ol ut i on )
{
long r e s = 0;
void i ncr Val ue ( void i )
{
r e s += ( i nst ance >val ues + ( ( long) i ) ) ;
}
l i nkedLi st Appl y ( s ol ut i on , i ncr Val ue ) ;
return r e s ;
}
//
long knapSackWeight( knapSack i nst ance , l i nke dLi s t s ol ut i on )
{
long r e s = 0;
144
void i ncr Val ue ( void i )
{
r e s += ( i nst ance >wei ght s + ( ( long) i ) ) ;
}
l i nkedLi st Appl y ( s ol ut i on , i ncr Val ue ) ;
return r e s ;
}
//
i nt knapSackI sFeasi bl e ( knapSack i nst ance , l i nke dLi s t s ol ut i on )
{
return knapSackWeight( i nst ance , s ol ut i on )
<= i nst ance >maxWeight ;
}
//
void knapSackPri ntInstance ( knapSack k)
{
long l = 0;
while ( l < k>nbItems)
{
pr i nt f ( ( i = %3l d , v = %3l d , w = %3l d )\n , l ,
( k>val ues + l ) , ( k>wei ght s + l ) ) ;
l ++;
}
pr i nt f ( max wei ght = %l d \n , k>maxWeight ) ;
}
//
void knapSackDestroy( knapSack k)
{
f r e e ( k>val ues ) ;
f r e e ( k>wei ght s ) ;
f r e e ( k ) ;
}
//
void l i nkedLi st Copy( void l )
{
void i d ( void i )
{
return i ;
}
return l i nkedLi stMap ( ( l i nke dLi s t ) l , i d ) ;
}
//
void knapSackPr i ntSol ut i on( l i nke dLi s t l )
{
void pr i nt I ndex ( void i )
{
pr i nt f ( %l d , ( ( long) i ) ) ;
}
l i nkedLi st Appl y ( l , pr i nt I ndex ) ;
}
//
l i nke dLi s t knapSackLi st I ni t ( long n)
{
l i nke dLi s t l ;
i f ( n <= 0)
l = l i nke dLi s t Cr e at e ( ) ;
el se
{
l = knapSackLi st I ni t ( n 1) ;
long p = mal l oc ( si zeof ( long ) ) ;
i f ( p == NULL)
e xi t ( 0 ) ;
p = n1;
l i nkedLi stAppend ( l , p ) ;
}
return l ;
}
//
145
void knapSackPr i nt Par ti es ( l i nke dLi s t l )
{
void knapSackPri ntVoi dSol uti on ( void l )
{
pr i nt f ( [ ) ;
knapSackPr i ntSol uti on ( ( l i nke dLi s t ) l ) ;
pr i nt f ( ] \n ) ;
}
l i nkedLi st Appl y ( l , knapSackPri ntVoi dSol uti on ) ;
}
//
void doNothing ( void v)
{
}
//
void de s t r oyI nt ( void v)
{
f r e e ( ( i nt ) v ) ;
}
//
void knapSackDestroyParti es ( l i nke dLi s t l )
{
void de s t r oyPar t i e ( void p)
{
l i nke dLi s t De s t r oy ( ( l i nke dLi s t ) p , doNothing ) ;
}
l i nke dLi s t De s t r oy ( l , de s t r oyPar t i e ) ;
}
//
l i nke dLi s t par t i e s ( l i nke dLi s t l )
{
l i nke dLi s t r e s = l i nke dLi s t Cr e at e ( ) ;
l i nke dLi s t parti esWi thoutX , parti esWi thX ;
i f ( l i nke dLi s t Ge t Si z e ( l ) == 0)
{
l i nkedLi stAppend ( res , l i nke dLi s t Cr e at e ( ) ) ;
}
el se
{
l i nk x = l i nke dLi s t Unl i nkFi r s t ( l ) ;
parti esWi thoutX = par t i e s ( l ) ;
parti esWi thX = l i nkedLi stMap ( parti esWi thoutX , l i nkedLi st Copy ) ;
void appendX( void data )
{
l i nkedLi stAppend ( ( l i nke dLi s t ) data , x>data ) ;
}
l i nkedLi st Appl y ( parti esWi thX , appendX ) ;
l i nkedLi stAppendLi nk ( l , x ) ;
l i nkedLi st Concat ( res , parti esWi thoutX) ;
l i nkedLi st Concat ( res , parti esWi thX ) ;
l i nke dLi s t De s t r oy ( parti esWi thX , doNothing ) ;
l i nke dLi s t De s t r oy ( parti esWi thoutX , doNothing ) ;
}
pr i nt f ( > 2%d\n , l i nke dLi s t Ge t Si z e ( l ) ) ;
return r e s ;
}
//
l i nke dLi s t knapSackBruteForceSol ve( knapSack k)
{
l i nke dLi s t i ndexes = knapSackLi st I ni t ( k>nbItems ) ;
l i nke dLi s t a l l So l ut i on s = par t i e s ( i ndexes ) ;
l i nke dLi s t be s t Sol ut i onSee n = NULL;
l i nke dLi s t Ge t Fi r s t ( a l l So l ut i on s ) ;
pr i nt f ( > s ubs e t s gener at ed . \ nTryi ng to f i nd the best s ol ut i on \n ) ;
void f i ndBe s t ( void v)
{
l i nke dLi s t l = ( l i nke dLi s t ) v ;
i f ( knapSackI sFeasi bl e ( k , l )
&& ( be s t Sol ut i onSee n == NULL | |
knapSackValue ( k , l ) > knapSackValue ( k , be s t Sol ut i onSeen ) ) )
146
be s t Sol ut i onSeen = l ;
}
l i nkedLi st Appl y ( al l So l ut i ons , f i ndBe s t ) ;
pr i nt f ( > Done . \ nDestroyi ng the s ubs e t s \n ) ;
void copyInt ( void i )
{
void v = mal l oc ( si zeof ( long ) ) ;
i f ( v == NULL)
e xi t ( 0 ) ;
( ( long) v) = ( ( long) i ) ;
return v ;
}
be s t Sol ut i onSeen = l i nkedLi stMap ( best Sol ut i onSeen , copyInt ) ;
void dest r oyTheLi nkedLi st ( void v)
{
l i nke dLi s t De s t r oy ( ( l i nke dLi s t ) v , de s t r oyI nt ) ;
}
l i nke dLi s t De s t r oy ( al l Sol ut i ons , dest r oyTheLi nkedLi st ) ;
pr i nt f ( > Done . \ nThanks f or your pat i e nc e . \n ) ;
return be s t Sol ut i onSeen ;
}
//
i nt main ( )
{
long t = 21;
knapSack k = knapSackMake ( t , 40) ;
l i nke dLi s t s ;
long l ;
for ( l = 0 ; l < k>nbItems ; l ++)
knapSackSetItem( k , l , ( l l l )%10 + 1 , ( l l l l )%10 + 1 ) ;
knapSackPri ntInstance ( k ) ;
s = knapSackBruteForceSol ve( k ) ;
knapSackPr i ntSol uti on( s ) ;
pr i nt f ( \n ) ;
l i nke dLi s t De s t r oy ( s , doNothing ) ;
knapSackDestroy( k ) ;
return 0;
}
147
A.17 Prise en main de GLPK
#include<s t di o . h>
#include gl pk . h
i nt main ( )
{
LPX l p = l px c r e at e pr ob ( ) ;
double c o e f f s [ 1 0 ] ;
i nt c ol s [ 1 0 ] , rows [ 1 0 ] ;
i nt k = 1;
l p x s e t o b j d i r ( l p , LPX MAX) ;
l px add c ol s ( l p , 3 ) ;
l p x s e t o bj c o e f ( l p , 1 , 4 ) ;
l p x s e t o bj c o e f ( l p , 2 , 6 ) ;
l p x s e t o bj c o e f ( l p , 3 , 2 ) ;
l px s e t c o l bnds ( l p , 1 , LPX LO, 0. 0 , 0 . 0 ) ;
l px s e t c o l bnds ( l p , 2 , LPX LO, 0. 0 , 0 . 0 ) ;
l px s e t c o l bnds ( l p , 3 , LPX LO, 0. 0 , 0 . 0 ) ;
l px add r ows ( l p , 3 ) ;
l px s e t r ow bnds ( l p , 1 , LPX UP, 0. 0 , 1 2 . ) ;
l px s e t r ow bnds ( l p , 2 , LPX UP, 0. 0 , 3 . ) ;
l px s e t r ow bnds ( l p , 3 , LPX UP, 0. 0 , 6 . ) ;
c o e f f s [ k ] = 3 . ; rows [ k ] = 1; c o l s [ k ] = 1; k++;
c o e f f s [ k ] = 7 . ; rows [ k ] = 1; c o l s [ k ] = 2; k++;
c o e f f s [ k ] = 1 . ; rows [ k ] = 1; c o l s [ k ] = 3; k++;
c o e f f s [ k ] = 0 . 6 ; rows [ k ] = 2; c ol s [ k ] = 1; k++;
c o e f f s [ k ] = 3; rows [ k ] = 2; c ol s [ k ] = 2; k++;
c o e f f s [ k ] = 2 . 8 ; rows [ k ] = 2; c ol s [ k ] = 3; k++;
c o e f f s [ k ] = 9 . ; rows [ k ] = 3; c o l s [ k ] = 1; k++;
c o e f f s [ k ] = 0. 08 ; rows [ k ] = 3; c ol s [ k ] = 2; k++;
c o e f f s [ k ] = 5 . ; rows [ k ] = 3; c o l s [ k ] = 3; k++;
l px l oad mat r i x ( l p , 9 , rows , c ol s , c o e f f s ) ;
l px s i mpl e x ( l p ) ;
pr i nt f ( f onc t i on o be c t i f = %l f \n , l px g e t ob j va l ( l p ) ) ;
for ( k = 1 ; k <= 3 ; k++)
pr i nt f ( x %d = %l f \n , k , l px ge t c ol pr i m ( l p , k ) ) ;
l px de l e t e pr ob ( l p ) ;
return 0;
}
148
A.18 Le plus beau metier du monde
#include<s t di o . h>
#include gl pk . h
#define N 10
double sommeTab( double t , i nt n)
{
i f ( n == 0)
return 0 . ;
return t + sommeTab( t +1, n1);
}
void quest i on1 ( double not e s Par t i e l , double notesCC1 , double notesCC2 )
{
double c o e f f s [ 4 ] ;
i nt rows [ 4 ] , c ol s [ 4 ] ;
LPX l p ;
i nt k = 1;
l p = l px c r e at e pr ob ( ) ;
l p x s e t o b j d i r ( l p , LPX MAX) ;
l px add c ol s ( l p , 3 ) ;
l p x s e t o bj c o e f ( l p , 1 , sommeTab( not e s Par t i e l , N)/N) ;
l p x s e t o bj c o e f ( l p , 2 , sommeTab( notesCC1 , N)/N) ;
l p x s e t o bj c o e f ( l p , 3 , sommeTab( notesCC2 , N)/N) ;
for ( k = 1 ; k <= 3 ; k++)
l px s e t c ol bnds ( l p , k , LPX DB, 0. 0 , 1 . 0 ) ;
l px add r ows ( l p , 1 ) ;
l px s e t r ow bnds ( l p , 1 , LPX UP, 0. 0 , 1 . 0 ) ;
for ( k = 1 ; k <= 3 ; k++)
{
rows [ k] =1; c o l s [ k]=k ; c o e f f s [ k ] = 1. 0 ;
}
l px l oad mat r i x ( l p , 3 , rows , c ol s , c o e f f s ) ;
l px s i mpl e x ( l p ) ;
l px g e t o bj v al ( l p ) ;
for ( k = 1 ; k <= 3 ; k++)
pr i nt f ( c o e f f %d i s %l f \n , k , l px ge t c ol pr i m ( l p , k ) ) ;
l px de l e t e pr ob ( l p ) ;
}
void quest i on2 ( double not e s Par t i e l , double notesCC1 , double notesCC2 )
{
double c o e f f s [ 4 ] ;
i nt rows [ 4 ] , c ol s [ 4 ] ;
LPX l p ;
i nt k = 1;
l p = l px c r e at e pr ob ( ) ;
l p x s e t o b j d i r ( l p , LPX MAX) ;
l px add c ol s ( l p , 3 ) ;
l p x s e t o bj c o e f ( l p , 1 , sommeTab( not e s Par t i e l , N)/N) ;
l p x s e t o bj c o e f ( l p , 2 , sommeTab( notesCC1 , N)/N) ;
l p x s e t o bj c o e f ( l p , 3 , sommeTab( notesCC2 , N)/N) ;
l px s e t c o l bnds ( l p , 1 , LPX DB, 0. 5 , 1 . 0 ) ;
for ( k = 2 ; k <= 3 ; k++)
l px s e t c ol bnds ( l p , k , LPX DB, 0. 1 , 1 . 0 ) ;
l px add r ows ( l p , 1 ) ;
l px s e t r ow bnds ( l p , 1 , LPX UP, 0. 0 , 1 . 0 ) ;
for ( k = 1 ; k <= 3 ; k++)
{
rows [ k] =1; c o l s [ k]=k ; c o e f f s [ k ] = 1. 0 ;
}
l px l oad mat r i x ( l p , 3 , rows , c ol s , c o e f f s ) ;
l px s i mpl e x ( l p ) ;
l px g e t o bj v al ( l p ) ;
for ( k = 1 ; k <= 3 ; k++)
pr i nt f ( c o e f f %d i s %l f \n , k , l px ge t c ol pr i m ( l p , k ) ) ;
l px de l e t e pr ob ( l p ) ;
}
void quest i on3 ( double not e s Par t i e l , double notesCC1 , double notesCC2 )
{
double c o e f f s [ 4(N+1) + 1 ] ;
i nt rows [ 4(N+1) + 1] , c ol s [ 4(N+1) + 1 ] ;
LPX l p ;
i nt el eveI ndex , c oe f f I nde x = 1 , i ;
l p = l px c r e at e pr ob ( ) ;
l p x s e t o b j d i r ( l p , LPX MAX) ;
l px add c ol s ( l p , 4 ) ;
l p x s e t o bj c o e f ( l p , 1 , 1 . ) ;
149
l px s e t c o l bnds ( l p , 1 , LPX FR, 0. 0 , 0 . 0 ) ;
l px s e t c o l bnds ( l p , 2 , LPX DB, 0. 5 , 1 . ) ;
l px s e t c o l bnds ( l p , 3 , LPX DB, 0. 1 , 1 . ) ;
l px s e t c o l bnds ( l p , 4 , LPX DB, 0. 1 , 1 . ) ;
l px add r ows ( l p , N+1);
for ( el eveI ndex = 0 ; el eveI ndex < N ; el eveI ndex++)
{
rows [ c oe f f I nde x ]=el eveI ndex + 1;
c ol s [ c oe f f I nde x ] =1;
c o e f f s [ c oe f f I nde x ] = 1. 0 ;
c oe f f I nde x++;
rows [ c oe f f I nde x ]=el eveI ndex + 1;
c ol s [ c oe f f I nde x ] =2;
c o e f f s [ c oe f f I nde x ] = ( not e s Par t i e l + el eveI ndex ) ;
c oe f f I nde x++;
rows [ c oe f f I nde x ]=el eveI ndex + 1;
c ol s [ c oe f f I nde x ] =3;
c o e f f s [ c oe f f I nde x ] = (notesCC1 + el eveI ndex ) ;
c oe f f I nde x++;
rows [ c oe f f I nde x ]=el eveI ndex + 1;
c ol s [ c oe f f I nde x ] =4;
c o e f f s [ c oe f f I nde x ] = (notesCC2 + el eveI ndex ) ;
c oe f f I nde x++;
l px s e t r ow bnds ( l p , el eveI ndex + 1 , LPX UP, 0. 0 , 0 . 0 ) ;
}
for ( i = 2; i <= 4; i ++)
{
rows [ c oe f f I nde x ] = N+1 ;
c ol s [ c oe f f I nde x ] = i ;
c o e f f s [ c oe f f I nde x ] = 1. 0 ;
c oe f f I nde x++;
}
l px s e t r ow bnds ( l p , N+1, LPX DB, 0. 0 , 1 . 0 ) ;
l px l oad mat r i x ( l p , c oe f f I nde x 1 , rows , c ol s , c o e f f s ) ;
l px s i mpl e x ( l p ) ;
l px g e t o bj v al ( l p ) ;
for ( i = 2 ; i <= 4 ; i ++)
pr i nt f ( c o e f f %d i s %l f \n , i 1, l px ge t c ol pr i m ( l p , i ) ) ;
l px pr i nt pr ob ( l p , quest i on3 . l px ) ;
l px de l e t e pr ob ( l p ) ;
}
i nt main ( )
{
double not e s Par t i e l [N] = {10 , 13 , 2 , 4. 5 , 9 , 12 , 16 , 8 , 5 , 12};
double notesCC1 [ N] = {11 , 16 , 11 , 8 , 10 , 11 , 11 , 6 , 4 , 13};
double notesCC2 [ N] = { 9 , 18 , 7 , 8 , 11 , 3 , 13 , 10 , 7 , 19};
pr i nt f ( QUESTION 1\n\n ) ;
quest i on1 ( not e s Par t i e l , notesCC1 , notesCC2 ) ;
pr i nt f ( QUESTION 2\n\n ) ;
quest i on2 ( not e s Par t i e l , notesCC1 , notesCC2 ) ;
pr i nt f ( QUESTION 3\n\n ) ;
quest i on3 ( not e s Par t i e l , notesCC1 , notesCC2 ) ;
return 0;
}
150
A.19 Prise en main de GMP
#include<s t di o . h>
#include<gmp. h>
/
Af f i che l a t ab l e de mul t i pl i cat i on de n, de 1 a t o .
n doi t et r e i n i t i a l i s e .
/
void af f i c he Tabl e Mul t i pl i c at i on ( mpz t n , long to )
{
mpz t r e s ;
i f ( to > 0)
{
af f i c he Tabl e Mul t i pl i c at i on ( n , to 1) ;
mpz i ni t ( r e s ) ;
mpz mul ui ( res , n , to ) ;
mpz out st r (NULL, 10 , r e s ) ;
pr i nt f ( \n ) ;
}
}
/
Pl ace bn dans res . res doi t et r e i n i t i a l i s e
/
void pui ssance ( mpz t b , mpz t n , mpz t r e s )
{
mpz t temp ;
i f ( ! mpz cmp ui ( n , 0) )
{
mpz set ui ( res , 1 ) ;
}
el se
{
mpz i ni t ( temp ) ;
i f ( mpz di vi s i bl e ui p ( n , 2) )
{
mpz t q ;
mpz t deux ;
mpz mul ( temp , b , b ) ;
mpz i ni t ( q ) ;
mpz i ni t s e t ui ( deux , 2 ) ;
mpz cdi v q ( q , n , deux ) ;
pui ssance ( temp , q , r e s ) ;
mpz cl ear ( q ) ;
mpz cl ear ( deux ) ;
}
el se
{
mpz t nMoinsUn ;
mpz i ni t ( nMoinsUn ) ;
mpz sub ui ( nMoinsUn , n , 1) ;
pui ssance ( b , nMoinsUn , temp ) ;
mpz mul ( res , temp , b ) ;
mpz cl ear ( nMoinsUn ) ;
}
mpz cl ear ( temp ) ;
}
}
/
Fonction d Ackermann. res doi t et r e i n i t i a l i s e .
At t ent i on ! Ne doi t et r e u t i l i s e qu avec des p e t i t e s val eurs !
/
void ackermann ( mpz t m, mpz t n , mpz t r e s )
{
i f ( ! mpz cmp ui (m, 0) )
{
mpz add ui ( res , n , 1 ) ;
}
el se
{
mpz t mMoinsUn ;
mpz i ni t (mMoinsUn ) ;
mpz sub ui (mMoinsUn , m, 1) ;
i f ( ! mpz cmp ui ( n , 0) )
{
151
mpz t un ;
mpz i ni t s e t ui ( un , 1) ;
ackermann (mMoinsUn , un , r e s ) ;
mpz cl ear ( un ) ;
}
el se
{
mpz t nMoinsUn ;
mpz t appe l Re c ur s i f ;
mpz i ni t ( nMoinsUn ) ;
mpz i ni t ( appe l Re c ur s i f ) ;
mpz sub ui ( nMoinsUn , n , 1) ;
ackermann (m, nMoinsUn , appe l Re c ur s i f ) ;
ackermann (mMoinsUn , appel Recur si f , r e s ) ;
mpz cl ear ( appe l Re c ur s i f ) ;
mpz cl ear ( nMoinsUn ) ;
}
mpz cl ear (mMoinsUn ) ;
}
}
/
Af f i che t out es l e s images par l a f onct i on d Ackermann des coupl es
{( i , j ) | 0 <= i <= m, 0 <= j <= n}
/
void af f i cheAckermann( long m, long n)
{
mpz t i ;
mpz t j ;
mpz t a ;
mpz i ni t ( i ) ;
mpz i ni t ( j ) ;
mpz i ni t ( a ) ;
mpz set ui ( i , 0) ;
while ( mpz cmp ui ( i , m) <= 0)
{
mpz set ui ( j , 0) ;
while ( mpz cmp ui ( j , n) <= 0)
{
pr i nt f ( ackermann ( ) ;
mpz out st r (NULL, 10 , i ) ;
pr i nt f ( , ) ;
mpz out st r (NULL, 10 , j ) ;
pr i nt f ( )= ) ;
ackermann ( i , j , a ) ;
mpz out st r (NULL, 10 , a ) ;
pr i nt f ( \n ) ;
mpz add ui ( j , j , 1) ;
}
mpz add ui ( i , i , 1) ;
}
}
i nt main ( )
{
mpz t v ;
mpz t di x ;
mpz t vi ngt ;
mpz i ni t ( v ) ;
mpz i ni t s e t ui ( di x , 10) ;
mpz i ni t s e t ui ( vi ngt , 20) ;
pui ssance ( di x , vi ngt , v ) ;
af f i c he Tabl e Mul t i pl i c at i on ( v , 10) ;
af f i cheAckermann( 4 , 15) ;
return 0;
}
152
A.20 Algorithme dEuclide etendu
#include<s t di o . h>
#include<gmp. h>
//
/
Cal cul e u et v t e l s que au + bv = pgcd , ou pgcd es t l e pgcd de a et b .
Toutes l e s v ar i ab l e s doi vent et r e i n i t i a l i s e e s .
/
void bezout ( mpz t a , mpz t b , mpz t u , mpz t v , mpz t pgcd)
{
i f ( ! mpz cmp ui ( b , 0) )
{
mpz set ( pgcd , a ) ;
mpz set ui (u , 1) ;
mpz set ui ( v , 0) ;
pr i nt f ( 1 ) ;
mpz out st r (NULL, 10 , a ) ;
pr i nt f ( + 0 0 = ) ;
mpz out st r (NULL, 10 , a ) ;
}
el se
{
mpz t quot i ent ;
mpz t r e s t e ;
mpz t uRec ;
mpz t vRec ;
mpz t vFoi sQuoti ent ;
mpz i ni t ( quot i ent ) ;
mpz i ni t ( r e s t e ) ;
mpz i ni t ( uRec ) ;
mpz i ni t ( vRec ) ;
mpz i ni t ( vFoi sQuoti ent ) ;
mpz t di v qr ( quot i ent , r e s t e , a , b ) ;
mpz out st r (NULL, 10 , a ) ;
pr i nt f ( = ) ;
mpz out st r (NULL, 10 , quot i ent ) ;
pr i nt f ( ) ;
mpz out st r (NULL, 10 , b ) ;
pr i nt f ( + ) ;
mpz out st r (NULL, 10 , r e s t e ) ;
pr i nt f ( \n ) ;
bezout ( b , r e s t e , uRec , vRec , pgcd ) ;
mpz out st r (NULL, 10 , uRec ) ;
pr i nt f ( ( ) ;
mpz out st r (NULL, 10 , b ) ;
pr i nt f ( ) + ) ;
mpz out st r (NULL, 10 , vRec ) ;
pr i nt f ( ( ) ;
mpz out st r (NULL, 10 , a ) ;
pr i nt f ( ) ;
mpz out st r (NULL, 10 , quot i ent ) ;
pr i nt f ( ) ;
mpz out st r (NULL, 10 , b ) ;
pr i nt f ( ) = ) ;
mpz out st r (NULL, 10 , pgcd ) ;
pr i nt f ( \n ) ;
mpz set ( u , vRec ) ;
mpz mul ( vFoi sQuoti ent , vRec , quot i ent ) ;
mpz sub ( v , uRec , vFoi sQuoti ent ) ;
mpz out st r (NULL, 10 , u ) ;
pr i nt f ( ) ;
mpz out st r (NULL, 10 , a ) ;
pr i nt f ( + ) ;
mpz out st r (NULL, 10 , v ) ;
pr i nt f ( ) ;
mpz out st r (NULL, 10 , b ) ;
pr i nt f ( = ) ;
mpz out st r (NULL, 10 , pgcd ) ;
mpz cl ear ( quot i ent ) ;
mpz cl ear ( r e s t e ) ;
mpz cl ear ( uRec ) ;
mpz cl ear ( vRec ) ;
mpz cl ear ( vFoi sQuoti ent ) ;
}
pr i nt f ( \n ) ;
}
153
//
/
Impl ementation de l a f onct i on phi de f i ni e dans l e s uj e t
phi (a , b , 0) = b et phi (a , b , n) = phi (a + b , b , n1).
Tous l e s parametres doi vent et r e i n i t i a l i s e s .
/
void phi ( mpz t a , mpz t b , mpz t n , mpz t r e s )
{
i f ( ! mpz cmp ui ( n , 0) )
{
mpz set ( res , b ) ;
}
el se
{
mpz t aPlusB;
mpz t nMoinsUn ;
mpz i ni t ( aPlusB) ;
mpz i ni t ( nMoinsUn ) ;
mpz add( aPlusB , a , b ) ;
mpz sub ui ( nMoinsUn , n , 1) ;
phi ( aPlusB , a , nMoinsUn , r e s ) ;
mpz cl ear ( aPlusB ) ;
mpz cl ear ( nMoinsUn ) ;
}
}
//
/
Pl ace dans res l e neme nombes de Fi bonacci .
Tous l e s parametres doi vent et r e i n i t i a l i s e s .
/
void f i bo ( mpz t n , mpz t r e s )
{
mpz t zer o ;
mpz t un ;
mpz i ni t s e t ui ( zero , 0) ;
mpz i ni t s e t ui ( un , 1 ) ;
phi ( un , zero , n , r e s ) ;
mpz cl ear ( zer o ) ;
mpz cl ear ( un ) ;
}
//
i nt main ( )
{
mpz t u ;
mpz t v ;
mpz t p ;
mpz t cent ;
mpz t centUn ;
mpz t Fcent ;
mpz t FcentUn ;
mpz i ni t ( u ) ;
mpz i ni t ( v ) ;
mpz i ni t ( p ) ;
mpz i ni t s e t ui ( cent , 100) ;
mpz i ni t s e t ui ( centUn , 101) ;
mpz i ni t ( Fcent ) ;
mpz i ni t ( FcentUn ) ;
f i bo ( cent , Fcent ) ;
f i bo ( centUn , FcentUn ) ;
bezout ( FcentUn , Fcent , u , v , p ) ;
mpz cl ear ( u ) ;
mpz cl ear ( v ) ;
mpz cl ear ( p ) ;
mpz cl ear ( cent ) ;
mpz cl ear ( centUn ) ;
mpz cl ear ( Fcent ) ;
mpz cl ear ( FcentUn ) ;
return 0;
}
154
A.21 Espaces Quotients
#include<s t di o . h>
#include<gmp. h>
//
/
Cal cul e u et v t e l s que au + bv = pgcd , ou pgcd es t l e pgcd de a et b .
Toutes l e s v ar i ab l e s doi vent et r e i n i t i a l i s e e s .
/
void bezout ( mpz t a , mpz t b , mpz t u , mpz t v , mpz t pgcd)
{
i f ( ! mpz cmp ui ( b , 0) )
{
mpz set ( pgcd , a ) ;
mpz set ui (u , 1) ;
mpz set ui ( v , 0) ;
}
el se
{
mpz t quot i ent ;
mpz t r e s t e ;
mpz t uRec ;
mpz t vRec ;
mpz t vFoi sQuoti ent ;
mpz i ni t ( quot i ent ) ;
mpz i ni t ( r e s t e ) ;
mpz i ni t ( uRec ) ;
mpz i ni t ( vRec ) ;
mpz i ni t ( vFoi sQuoti ent ) ;
mpz t di v qr ( quot i ent , r e s t e , a , b ) ;
bezout ( b , r e s t e , uRec , vRec , pgcd ) ;
mpz set ( u , vRec ) ;
mpz mul ( vFoi sQuoti ent , vRec , quot i ent ) ;
mpz sub ( v , uRec , vFoi sQuoti ent ) ;
mpz cl ear ( quot i ent ) ;
mpz cl ear ( r e s t e ) ;
mpz cl ear ( uRec ) ;
mpz cl ear ( vRec ) ;
mpz cl ear ( vFoi sQuoti ent ) ;
}
}
//
i nt t r ouve I nve r s e ( mpz t val eur , mpz t module , mpz t i nve r s e )
{
mpz t u , v , pgcd ;
i nt r e s = 1;
mpz i ni t ( u ) ;
mpz i ni t ( v ) ;
mpz i ni t ( pgcd ) ;
bezout ( val eur , module , u , v , pgcd ) ;
i f ( ! mpz cmp ui ( pgcd , 1) )
mpz set ( i nver se , u ) ;
el se
r e s = 0;
mpz cl ear ( u ) ;
mpz cl ear ( v ) ;
mpz cl ear ( pgcd ) ;
return r e s ;
}
//
void et udi eEspaceQuot i ent ( mpz t n)
{
mpz t i , phi , i nve r s e I ;
mpz i ni t ( i ) ;
mpz i ni t ( phi ) ;
mpz i ni t ( i nve r s e I ) ;
mpz set ui ( i , 0) ;
mpz set ui ( phi , 0 ) ;
pr i nt f ( Z/ ) ;
mpz out st r (NULL, 10 , n ) ;
pr i nt f ( Z : ) ;
while ( mpz cmp( i , n ) )
{
pr i nt f ( \n ) ;
155
mpz out st r (NULL, 10 , i ) ;
i f ( t r ouve I nve r s e ( i , n , i nve r s e I ) )
{
pr i nt f ( a pour i nve r s e ) ;
mpz add ui ( phi , phi , 1) ;
mpz mod( i nve r s e I , i nve r s e I , n ) ;
mpz out st r (NULL, 10 , i nve r s e I ) ;
}
el se
pr i nt f ( ( non i n ve r s i b l e ) ) ;
mpz add ui ( i , i , 1) ;
}
pr i nt f ( \nOn a phi ( ) ;
mpz out st r (NULL, 10 , n ) ;
pr i nt f ( ) = ) ;
mpz out st r (NULL, 10 , phi ) ;
pr i nt f ( \n ) ;
mpz add ui ( phi , phi , 1) ;
i f ( ! mpz cmp( n , phi ) )
pr i nt f ( Cet ensembl e e s t un cor ps \n ) ;
el se
pr i nt f ( Cet ensembl e n e s t pas un cor ps \n ) ;
}
//
i nt main ( )
{
mpz t t e s t ;
mpz i ni t ( t e s t ) ;
mpz i ni t s e t ui ( t e s t , 20) ;
et udi eEspaceQuot i ent ( t e s t ) ;
mpz cl ear ( t e s t ) ;
return 0;
}
156
Annexe B
Rappels mathematiques
B.1 Sommations
Parmi les outils mathematiques permettant devaluer la complexite dun algorithme se trouvent les sommations.
Commen cons par rappeler quelques proprietes :
1.
n

i=p
1 = n p + 1
2.
n

i=p
u
i
= (
n1

i=p
u
i
) +u
n
= u
p
+
n

i=p+1
u
i
3.
n

i=p
(a.u
i
) = a
n

i=p
u
i
4.
n

i=p
(a
i
+b) =
n

i=p
a
i
+
n

i=p
b = (
n

i=p
a
i
) + (n p + 1)b
5.
n

i=p
(a
i
+b
i
) =
n

i=p
a
i
+
n

i=p
b
i
6.
n

i=p
u
i
=
n+1

i=p+1
u
i1
=
n1

i=p1
u
i+1
7.
n

i=1
m

j=1
u
ij
=
m

j=1
n

i=1
u
ij
Bien que le

soit prioritaire sur le + mais pas sur le , il usuel pour eviter toute confusion de rajouter des parenth`eses,
meme inutiles. Parmi les sommes que vous devez matriser parfaitement gurent les deux suivantes :
1.
n

i=1
i =
n(n + 1)
2
(serie arithmetique)
2.
n

i=0
r
i
=
r
n+1
1
r 1
(serie geometrique)
On se ram`ene souvent `a ce type de formule en algorithmique.
B.1.1 Exercices
Calculer les sommes suivantes :
1.
n

i=1
2i + 1
157
2.
n

i=1
(i + 1)
2
3.
n

i=1
(
i

j=1
j)
4.
n

i=1
(
n

j=i
j)
5.
n

i=p
i
6.
n

i=p
r
i
B.2 Ensembles
B.2.1 Denition
Denition B.2.1 Un ensemble est un regroupement en un tout dobjets. Etant donne un ensemble E, les objets
regroupes dans E sont appeles elements de E.
On denit un ensemble notament en enumerant ses elements et en les separant par des virgules. Par exemple E =
{1, 2, 3, 4} denit un ensemble E contenant les elements 1, 2, 3 et 4. Si e est un element de E, on dit alors quil
appartient `a E, note e E.
Denition `a laide dun predicat
On denit aussi un ensemble par une condition dappartenance. Par exemple, E = {e|(e N) (e 5)} denit
lensemble des elements e veriant (e N) (e 5), `a savoir {0, 1, 2, 3, 4, 5}. Plus formellement,
Denition B.2.2 Soient P(x) un predicat et E = {x|P(x)}, alors
x E P(x)
E = {x|P(x)} est alors lensemble E des elements x veriant P(x).
Ensemble vide
F est le predicat constant prenant toujours la valeur faux.
Denition B.2.3 On note lensemble vide deni comme suit
= {i|F}
est lensemble auquel nappartient aucun element. Lensemble vide peut etre deni par tout predicat constant etant
toujours faux. Par exemple,
= {i|(i N) (i = i + 1)}
B.2.2 Operations ensemblistes
On denit sur les ensembles les operations suivantes :
Denition B.2.4 Lunion de deux ensembles A et B, notee , est denie par A B = {x|(x A) (x B)}.
158
Un element appartient `a A B sil appartient `a A, ou sil appartient `a B. Par exemple,
{1, 3, 7, 8} {2, 4, 6, 8, 10} = {1, 2, 3, 4, 6, 7, 8, 10}
Denition B.2.5 Lintersection de deux ensembles A et B, notee , est denie par AB = {x|(x A)(x B)}.
Un element appartient `a A B sil appartient `a A, et sil appartient `a B. Par exemple,
{1, 3, 4, 6, 7, 9, 10} {2, 4, 6, 8, 10, 12} = {4, 10}
Denition B.2.6 La dierence de deux ensembles A et B, notee \ ou , est denie par A\ B = {x|(x A) (x
B)}.
Un element appartient `a A \ B (ou A B) sil appartient `a A, mais pas `a B. Par exemple,
{1, 2, 3, 4, 6, 7, 8} \ {1, 2, 3} = {4, 6, 7, 8}
On note lunion de n ensembles E
1
E
2
. . . E
n
de la fa con suivante :
n
_
i=1
E
i
De meme
E
1
E
2
. . . E
n
=
n

i=1
E
i
B.2.3 Cardinal
Un ensemble est inni sil contient un nombre inni delements, sinon, on dit quil est ni.
Denition B.2.7 Le cardinal dun ensemble ni E, note |E| est le nombre delements quil contient.
Par exemple, || = 0, |{1, 2, 4}| = 3. Seul lensemble vide est de cardinal 0, un ensemble de cardinal 1 est appele un
singleton, un ensemble de cardinal 2 est appele une paire.
Propriete B.2.1 Le cardinal dun ensemble a les proprietes suivantes :
|A B| |A|
|A B| |B|
|A B| |A|
A \ B |A|
|A B| |B|
|A B| |A| +|B|
|A B| +|A B| = |A| +|B|
Si A B = , |A B| = |A| +|B|
|P(E)| = 2
|E|
B.2.4 n-uplets
Un n-uplet est un regroupement ordonne de n elements non necessairement distincts. On note X = (x
1
, . . . , x
n
) le
n-uplet compose des elements x
1
, . . . , x
n
, on les appelle composantes des E. Par exemple, (4, 8) est un 2-uplet, dit
aussi couple, et ((3, 2), (6, 12), (0, 3)) est un triplet compose des trois couples (3, 2), (6, 12) et (0, 3).
159
Produit cartesien
Denition B.2.8 Le produit cartesien de n ensembles E
1
, . . . , E
n
, note E
1
. . . E
n
est lensemble de tous les
n-uplets (x
1
, . . . , x
n
) tels que i {1, . . . , n}, x
i
E
i
.
Par exemple,
{1, 2} {a, b, c} = {(1, a), (2, a), (1, b), (2, b), (1, c), (2, c)}
Formellement,
E
1
. . . E
n
= {(x
1
, . . . , x
n
)|i {1, . . . , n}, x
i
E
i
}
B.2.5 Parties
Inclusion
Denition B.2.9 A est contenu dans B, note A B si et seulement si e A, e B,
En dautres termes si tout element de A est aussi un element de B. On dit aussi que A est un sous-ensemble de B,
que A est inclus dans B, ou encore que A est une partie de B.
Parties de E
Denition B.2.10 Lensemble P(E) des parties de E, est deni par
P(E) = {e|e E}
P(E) est donc lensemble de tous les ensembles inclus dans E. Par exemple, P({1, 2, 3}) = {{1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, , {1, 2, 3
on remarque que P(E) est un ensemble densembles. Prennez note du fait que est un sous-ensemble de tous les en-
sembles, y compris de lui-meme, et que le seul ensemble contenu dans est . A votre avis, que vaut P() ? Cette
question vous am`enera `a distinuer de {}, qui est lensemble qui contient lensemble vide.
Exercice
Calculer P(), P({1, 2}), P({}).
Autre exercice
Soit f la fonction qui a un ensemble densembles F et un element x associe f(F, x) = {e {x}|e F}. Montrer que
P(E) = f(P(E {x}), x) P(E {x}). En deduire un algorithme recursif calculant P(E).
B.2.6 Denition
Denition B.2.11 Une relation f entre deux ensembles A et B est un sous-ensemble de AB.
Etant donne deux elements x A et y B, si (x, y) f, alors on dit que f associe y `a x. Lensemble des elements
qui sont associes `a x est {y|(x, y) f}.
Denition B.2.12 Une relation f entre deux ensembles A et B est une application si a A, |{b|(a, b) f}| = 1
Plus explicitement, f est une application si `a tout element de A est associe exactement un element de B. On dit alors
que f est une application de A dans B, ce qui se note f : A B. On dit par abus de langage que A est lensemble
de depart et B lensemble darrivee. Pour tout a A, on note f(a) lelement de B qui lui est associe. On dit que f(a)
est limage de a par f et a un antecedent de f(a) par f.
Etant donne un ensemble E, il existe une application, appelee identite, et notee id, telle que tout element `a pour
image lui-meme. Autrement dit : id : E E, x x. La succession de symboles a b signie que b est limage de
a, donc x x signie que x a pour image lui-meme.
160
B.2.7 Composition
Etant donnes f : A B et g : B C, on denit lapplication composee de g et f, notee g f, dite g rond f, et
denie par g f : A C, x g(f(x)). Autrement dit, g f est une application de A dans C, qui `a tout element x
de A, associe lelement g(f(x)) de C.
B.2.8 Classication des applications
Soit f : A B,
Denition B.2.13 f est injective si
a A, a

A, f(a) = f(a

) a = a

f est injective si deux elements distincts ne peuvent pas avoir la meme image.
Denition B.2.14 f est surjective si
b B, a A, f(a) = b
f est surjective si tout element de lensemble darrivee a un antecedent.
Denition B.2.15 f est bijective si elle est ` a la fois injective et surjective.
f est bijective si tous les elements de A et de B sont relies deux `a deux.
Propriete B.2.2 Soient A et B deux ensembles et f : A B,
Si f est injective, alors |A| |B|
Si f est surjective, alors |A| |B|
Si f est bijective, alors |A| = |B|
Cette propriete est tr`es importante ! En denombrement, lorsque le cardinal dun ensemble est dicile `a determiner, on
passe par une bijection vers un autre ensemble dont il est davantage aise de calculer le cardinal.
B.2.9 Application reciproque
Soit f : A B une application bijective.
Theor`eme B.2.1 Il existe une unique fonction f
1
, appelee application reciproque de f, telle que pour tous x A,
y B tels que f(x) = y, on ait f
1
(y) = x.
On remarque que f f
1
= f
1
f = id.
B.3 Raisonnements par recurrence
B.3.1 Principe
Ce type de raisonnement ne sapplique que dans des proprietes faisant intervenir des nombres entiers. Par exemple,
Quel que soit n 0, n
2
n est pair. Pour prouver quune propriete est veriee quelle que soit la valeur de n, on
eectue une preuve par recurrence en procedant en deux temps :
linitialisation, On prouve que pour n = 0 (ou 1, ca depend des cas), la propriete est veriee.
lheredite, on prouve que si la propriete est veriee au rang n, alors elle lest au rang n + 1.
161
B.3.2 Exemple
Montrons par recurrence sur n que Quel que soit n 0, n
2
n est pair :
initialisation : , 0
2
0 est pair, cest evident.
heredite : , supposons que n
2
n est pair, verions si (n + 1)
2
(n + 1) est pair lui aussi. Calculons
(n + 1)
2
(n + 1) = n
2
+ 2n + 1 n 1 = (n
2
n) + 2n
Comme (n
2
n) et 2n sont tous deux pairs, et que la somme de deux nombres pairs est paire, alors (n+1)
2
(n+1)
est pair.
Demandons-nous si 2
2
2 est pair, on sait dapr`es linitialisation que 0
2
0 est pair. Posons n = 0, comme la propriete
est veriee au rang n, elle est, dapr`es lheredite, necessairement veriee au rang n + 1, donc 1
2
1 est pair. Posons
n = 1, comme 1
2
1 est pair, la propriete est veriee au rang n, elle est, dapr`es lheredite, necessairement veriee au
rang n + 1, donc 2
2
2 est pair. On peut generaliser ce raisonnement `a nimporte quelle valeur de n.
B.3.3 Exercices
Exercice 10
Prouver par recurrence les proprietes suivantes :
1. Quel que soit n 0, n
2
+n + 1 est impaire.
2. Soit (u) une suite denie par u
0
= 2, u
n+1
= (1/2)u
n
+ 3, alors u
n
< 6
3. Soit (u) une suite denie par u
0
= 2, u
n+1
= (1/2)u
n
+ 3, alors u
n
= 6
8
(2
n
)
4. Soit (u) une suite denie par u
0
= 2, u
n+1
= 2u
n
n, alors u
n
= 2
n
+n + 1
5. Pour tout n > 0,
n

i=1
i =
n(n + 1)
2
6. Pour tout n 0, q = 1,
n

i=0
q
i
=
1 q
n+1
1 q
7. Pour tout n > 0,
n

i=1
i
2
=
n(n + 1)(2n + 1)
6
Derivee de fonctions puissance n
On rappelle que (fg)

= f

g +fg

et que f
n
est denie par (f
n
)(x) = [f(x)]
n
. Prouvez par recurrence que n IN

(f
n
)

= nf

(f
n1
)
Formule de Leibniz
On note f
(n)
la derivee n-i`eme de f. Prouvez par recurrence la formule de Leibniz : n IN

(fg)
n
=
n

i=0
C
i
n
f
(i)
g
(ni)
Derivee de fonctions composees
On rappelle que f g est deni par (f g)(x) = f(g(x)) et que (f g)

= g

(f

g). Etant donne un ensemble {f


1
, . . . , f
n
}
de n fonctions, on note

n
i=1
[f
i
] = f
1
. . . f
n
la composition de ces fonctions. Demontrez par recurrence que
(
n
i=1
[f
i
])

=
n

i=1
[f

i
(
n
j=i+1
[f
j
])]
162
B.4 Analyse combinatoire
B.4.1 Factorielles
Pour tout n 0, le nombre n!, appele factorielle n, est deni par recurrence `a laide des relations suivantes :
0! = 1
n! = n (n 1)!
On a donc n! =
n

i=1
i avec le cas particulier 0! = 1.
B.4.2 Arrangements
Denition B.4.1 Soient n et p tels que 0 p n, on note A
p
n
, et on lit A n p le nombre
n!
(n p)!
B.4.3 Combinaisons
Denition B.4.2 Soient n et p tels que 0 p n, on note C
p
n
, et on lit C n p le nombre
n!
p!(n p)!
Propriete B.4.1 Les egalites suivantes sont veriees pour tous k et n tels que 0 k n,
C
i
n
=
1
p!
A
i
n
C
0
n
= 1
C
1
n
= n
C
p
n
= C
np
n
pC
p
n
= nC
p1
n1
C
p
n
= C
p1
n1
+C
p
n1

i=0
C
i
n
= 2
n
(a +b)
n
=
n

i=0
C
i
n
a
i
b
ni

n1

i=p1
C
p1
i
= C
p
n
B.4.4 Triangle de Pascal
Le triangle de Pascal est un tableau triangulaire de taille innie dont les lignes sont indicees par n et les colonnes par
p, les indices commen cant `a 0. Les seules case du trianles renseignees sont celles dont les indices verient 0 p n.
Les valeurs se trouvant `a la ligne dindice n et la colonne dindice p du triangle de Pascal est C
p
n
, on a ainsi
(n, p) p = 0 1 2 3 4 5 6 . . .
n = 0 1
1 1 1
2 1 2 1
3 1 3 3 1
4 1 4 6 4 1
5 1 5 10 10 5 1
6 1 6 15 20 15 6 1
. . . . . . . . . . . . . . . . . . . . . . . . . . .
163
Vous remarquez que la propriete C
0
n
= 1 traduit le fait que la premi`ere colonne ne comporte que des 1. Comme chaque
ligne est symetrique alors C
p
n
= C
np
n
. Pour chaque ligne, le premier element est 1, donc la symetrie fait que le dernier
est 1 aussi. La propriete C
p
n
= C
p1
n1
+C
p
n1
traduit le fait que chaque element C
p
n
ne se trouvant pas dans la premi`ere
colonne ou sur la diagonale est la somme de celui qui est au dessus C
p
n1
et de celui qui est juste `a gauche de ce dernier
C
p1
n1
. Si on somme les elements sur chaque ligne, on obtient des puissances successives de 2 :
(n, p) p = 0 1 2 3 4 5 6 . . .
n

p=0
C
p
n
n = 0 1 2
0
1 1 1 2
1
2 1 2 1 2
2
3 1 3 3 1 2
3
4 1 4 6 4 1 2
4
5 1 5 10 10 5 1 2
5
6 1 6 15 20 15 6 1 2
6
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Cette propriete se traduit
n

i=0
C
i
n
= 2
n
. Lidentite remarquable (a + b)
n
secrit `a laide des coecients su triangle de
Pascal. Par exemple,
(a +b)
3
= a
3
+ 3a
2
b + 3ab
2
+b
3
Vous remarquez que le developpement de (a+b)
3
secrit avec un polynome `a deux variable dont la somme des exposants
de chaque terme est 3, chaque terme est donc de la forme a
i
b
3i
. Les coecients devant chaque termes sont issus de
la ligne dindice 3 du triangle de Pascal, `a savoir (1, 3, 3, 1), autrement dit (C
0
3
, C
1
3
, C
2
3
, C
3
3
). Donc
(a +b)
3
=
3

i=0
C
i
3
a
i
b
ni
On a plus generalement que
(a +b)
n
=
n

i=0
C
i
n
a
i
b
ni
Par exemple,
(a +b)
4
= a
4
+ 4a
3
b + 6a
2
b
2
+ 4ab
3
+b
4
Le soin de le demontrer par recurrence vous est laisse.
B.4.5 Liens avec les ensembles
Le nombre de fa cons dordonner n elements distincts est donnee par n! (la preuve vous est laisse en exercice).
Propriete B.4.2 Le nombre de sous-ensembles ` a k elements dun ensemble E ` a n elements, ` a savoir |{x|(x
E) (|x| = k)}| est donne par C
k
n
.
On le demontre par recurrence sur n,
si n = 0, le seul ensemble `a 0 elements est , son seul sous-ensemble est , donc
|{x|(x ) (|x| = 0)}| = |{}| = 1 = C
0
0
Supposons que pour tout ensemble E

`a n 1 0 elements, et tout k

{0, . . . , n 1},
|{x|(x E

) (|x| = k

)}| = C
k

n1
Considerons un ensemble E `a n 1 elements et une valeur k {0, . . . , n}, montrons que le cardinal de
P = {x|(x E) (|x| = k)}
est C
k
n
164
Si k {1, . . . , n1}, choisissons un element arbitraire e E, cet element existe necessairement car |E| = n 1.
On decompose {x|(x E) (|x| = k)} en deux ensembles P
1
et P
2
. P
1
est lensemble des sous-ensembles de
E `a k elements qui contiennent e, deni par
P
1
= {x|(x E) (|x| = k) (e x)}
P

est celui des sous-ensembles `a k elements qui ne contiennent pas e,


P
2
= {x|(x E) (|x| = k) (e x)}
On remarque que P
1
P
2
= P et que P
1
P
2
= , donc |P| = |P
1
| + |P
2
|. Comme P
2
est lensemble des
sous-ensembles `a k elements de E {e}, on le redenit de la sorte :
P
2
= {x|(x E {e}) (|x| = k)}
Comme |E {e}| = n 1 et k {1, . . . , n 1}, alors par hypoth`ese de recurrence, |P
2
| = C
k
n1
. Par ailleurs,
chaque element x de P
1
se decompose de la sorte : x = x

{e} o` u x

est un ensemble `a (k 1) elements ne


contenant pas e. Donc
P
1
= {x

{e}|(x

E {e}) (|x

| = k 1)}
Il a donc autant delement dans P
1
que de sous-ensembles `a k1 elements de E{e}. Comme |E{e}| = n1 et
(k1) {0, . . . , n2}, alors par hypoth`ese de recurrence, on a |P
1
| = C
k1
n1
. De ce fait |P| = C
k
n1
+C
k1
n1
= C
k
n
.
Dans le cas o` u k = 0 et n 1, on remarque que
P = {x|(x E) (|x| = 0)} = {}
et que par consequent |P| = |{}| = 1 = C
0
n
Il nous reste `a traiter le cas o` u k = n et n 1, on remarque que
P = {x|(x E) (|x| = |E|)} = {E}
et que par consequent |P| = |{E}| = 1 = C
n
n
.
On a bien
{x|(x E) (|x| = k)} = C
k
n
Pour tout k {0, . . . , n}.
Etant donne un ensemble E `a n elements, denombrons les parties de E, ce qui revient `a calculer |P(E)|. Pour ce faire,
on decompose P(E) en n + 1 sous-ensembles P
k
(E), k {0, . . . , n}, denis comme suit
P
k
(E) = {e|(e E) (|e| = k)}
On remarque que pour tout e E, e P
|e|
(E), donc P(E)
n
_
k=0
P
k
(E). Reciproquement, pour tout k {0, . . . , n},
tout element de P
k
(E) est, par denition, une partie de E, donc
n
_
k=0
P
k
(E) P(E). On deduit de cette double
inclusion que
P(E) =
n
_
k=0
P
k
(E)
Deux ensembles P
k
(E) et P
k
(E) tels que k = k

sont necessairements disjoints(si ca vous semble pas evident, cherchez


un contre-exemple et vous comprendrez pourquoi...). Donc
|
n
_
k=0
P
k
(E)| =
n

k=0
|P
k
(E)|
165
Si cette propriete ne vous parle pas, demontrez-la par recurrence en utilisant le fait que si A B = , alors |A B| =
|A| + |B|. Nous avons demontre que k {0, . . . , n}, |P
k
(E)| = C
k
n
. Donc
n

k=0
|P
k
(E)| =
n

k=0
C
k
n
= 2
n
. Le nombre
de parties dun ensemble `a n elements est donc 2
n
. Il vous est possible, de verier ce resultat par recurrence, le
raisonnement est analogue `a celui employe pour prouver que |{x|(x E) (|x| = k)}| = C
k
n
, mais en plus facile.
B.5 Exercices recapitulatifs
B.5.1 Echauement
Demontrer avec la methode la plus appropriee les propositions suivantes :
C
0
n
= 1
C
1
n
= n
C
p
n
= C
np
n
pC
p
n
= nC
p1
n1
C
p
n
= C
p1
n1
+C
p
n1

i=0
C
i
n
= 2
n
(a +b)
n
=
n

i=0
C
i
n
a
i
b
ni

n1

i=p1
C
p1
i
= C
p
n
B.5.2 Formule de Poincare
Le but de cet exercice est de prouver la formule de Poincare :
|
n
_
i=1
E
i
| =
n

i=1
(1)
i+1

eI
n
i
(

ie
|E
i
|)
En notant I
n
k
lensemble des sous-ensembles de {1, . . . , n} `a k elements, formellement : I
n
k
= {e {1, . . . , n} tel que |e| =
k}
1. Reecrivez la formule de Poincare avec n = 1
2. Reecrivez la formule de Poincare avec n = 2
3. Soient A = {1, 3, 5, 6} et B = {1, 2, 3, 4}. Calculez |AB| en utilisant la propriete |AB| = |A| +|B| |AB|.
4. Reecrivez la formule de Poincare avec n = 3
5. Soit C = {6, 7, 8}, utilisez la formule de Poincare pour calculer |A B C|.
6. On consid`ere n+1 ensembles {E
1
, . . . E
n+1
}. Supposons la formule de Poincare veriee veriee au rang n. Donnez
alors une relation entre
|
n+1
_
i=1
E
i
|
et
n

i=1
(1)
i+1

eI
n
i
(

ie
|E
i
|)
7. Utilisez les resultats des questions precedentes pour prouver par recurrence la formule de Poincare.
166
B.5.3 La moulinette `a meninges
Soient A et B deux ensembles nis de cardinaux respectifs m et n.
1. Combien existe-t-il de relations entre A et B? (Bijection avec les parties de lensemble AB)
2. Combien existe-t-il dapplications de A dans B? (Raisonnez par recurrence)
3. Combien existe-t-il dapplications bijectives de A dans B? (une bijection)
4. Combien existe-t-il de k-uplets delements de A? (demerdez-vous)
5. Combien existe-t-il de k-uplets delements distincts de A?
6. Combien existe-t-il dapplications injectives de A dans B? (raisonnez par recurrence)
7. Combien existe-t-il de fa con de partitionner un ensemble E de cardinal n en 3 sous-ensembles ? Cest-`a-dire de
determiner 3 ensembles A, B et C tels que A B C = E, A B = , A C = et B C = . (bijection)
8. Une application est croissante au sens large si x, y A, x < y = f(x) f(y). Combien existe-t-il dapplications
croissantes au sens large de A dans B (supposes ordonnes) ? (une bijection)
9. Une application est croissante au sens strict si x, y A, x < y = f(x) < f(y). Combien existe-t-il dapplica-
tions croissantes au sens large de A dans B? (plus dicile, bijection...)
10. Combien existe-t-il de fa con de partitionner un ensemble E de cardinal n > 3 en 3 sous-ensembles non-vides ?
(bijections + poincare)
11. Soit f : A A, un point xe de f est un element x de A tel que f(x) = x. Combien existe-t-il de bijection
sans point xe ? (vraiment dicile, utilisez la formule de Poincare puis le binome de Newton)
167
Bibliographie
[1] Simon Singh. The code book : the evolution of secrecy from Mary, Queen of Scots, to quantum cryptography. 1999.
[2] Thomas Cormen, Charles Leiserson, and Ronald Rivest. Introduction to algorithms. Dunod, 1992.
[3] Chretienne P. Beauquier D., Berstel J. Elements dalgorithmique. Masson, 1992.
[4] http://webpages.ull.es/users/jriera/Docencia/AVL/AVLtreeapplet.htm.
[5] Vasek Chvatal. Linear Programming. Freeman, 1983.
[6] http://www.gnu.org/software/glpk/.
[7] http://www.lmbe.seu.edu.cn/CRAN/doc/packages/glpk.pdf.
[8] Johnson D Garey M. Computers and Intractability. 1979.
[9] Hackademy Journal.
[10] Hackademy Journal.
[11] Hackademy Journal.
[12] http://www.gnupg.org/(fr)/documentation/guides.html.
[13] http://www.gnupg.org/gph/en/manual.pdf.
[14] http://gmplib.org/.
[15] http://gmplib.org/#DOC.
168

Vous aimerez peut-être aussi