diff --git a/lessons/contenu_cours_5.md b/lessons/contenu_cours_5.md new file mode 100644 index 0000000000000000000000000000000000000000..5affcce9f309fca459ba11a908acdd532c937a76 --- /dev/null +++ b/lessons/contenu_cours_5.md @@ -0,0 +1,192 @@ +# Algorithmique et structures de données 2019-20 + +Contenu du cours 5 du 16.10.2019 + +****** + +## Type composé : `struct` + +- **Exemple des fractions** + - On considère une structure pour stocker des fractions : +```C + struct _fraction { + int num; + int den; + } fraction; +``` + - On aimerait aussi définir les opérations arithmétiques associées ou utilitaires : +```C + void print(fraction frac); + int pgcd(int n,int m); + void reduire(fraction* frac); + fraction fraction_build(int num,int den); + fraction add(fraction frac1,fraction frac2); + fraction add1(int n,fraction frac); + fraction add2(fraction frac,int n); + void add_inplace(fraction* frac1,fraction frac2); + fraction sub(fraction frac1,fraction frac2); + fraction sub1(int n,fraction frac); + fraction sub2(fraction frac,int n); + void sub_inplace(fraction* frac1,fraction frac2); + fraction mult(fraction frac1,fraction frac2); + fraction mult1(int n,fraction frac); + fraction mult2(fraction frac,int n); + void mult_inplace(fraction* frac1,fraction frac2); + fraction divise(fraction frac1,fraction frac2); + fraction divise1(int n,fraction frac); + fraction divise2(fraction frac,int n); + void divise_inplace(fraction* frac1,fraction frac2); + fraction puiss(fraction frac,int n); + float reel(fraction frac); +``` + - Quelques implémentations de fonctions +```C + void reduire(fraction* frac) { + if (0 == frac>num) { + frac>den = 1; + } else { + int gcd = pgcd(abs(frac>num),frac>den); + frac>num /= gcd; + frac>den /= gcd; + } + } + + fraction fraction_build(int num,int den) { + assert(den != 0); + int sign = den/abs(den); + fraction res = {sign*num,sign*den}; + reduire(&res); + return res; + } + + fraction add(fraction frac1,fraction frac2) { + return fraction_build( + frac1.num*frac2.den+frac1.den*frac2.num, + frac1.den*frac2.den + ); + } + + fraction add1(int n,fraction frac) { + return add(fraction_build(n,1),frac); + } + + fraction add2(fraction frac,int n,) { + return add1(n,frac); + } + + void add_inplace(fraction* frac1,fraction frac2) { + *frac1 = add(*frac1,frac2); + } + + fraction puiss(fraction frac,int n) { + fraction prod = fraction_build(1,1); + for (int i=1;i<=abs(n);i++) { + prod = mult(prod,frac); + } + if (n < 0) { + prod = divise1(1,prod); + } + return prod; + } +``` + +- **Exemple des chaînes de caractères** + + - On peut définir un type pour les chaînes de caractères en stockant la longueur effective de la chaîne, c'est-à-dire la première occurrence du caractère `\0` +```C + struct _chaine { + char* str; + int len; + } chaine; +``` + - Quelques implémentations de fonctions +```C + chaine chaine_build(char* phrase) { + chaine ch; + ch.len = length(phrase); + ch.str = malloc((ch.len+1)*sizeof(char)); + for (int i=0;i<ch.len;i++) { + ch.str[i] = phrase[i]; + } + return ch; + } + + chaine deep_copy(chaine ch) { + return chaine_build(ch.str); + } + + // Dangereux, car plusieurs pointeurs + // sur le même tableau de caractères !!! + chaine shallow_copy(chaine ch) { + chaine cpy; + cpy.len = ch.len; + cpy.str = ch.str; + return cpy; + } + + // Si plusieurs pointeurs sur même tableau de caractères, + // alors autres pointeurs dessus ne seront pas mis à NULL + void chaine_free(chaine* ch) { + if (NULL != ch>str) + free(ch>str); + ch>str = NULL; + } + ch>len = -1; + } +``` + - Illustration + + +## Récursivité + +- Exemple de la factorielle : n ! = n·(n-1)·(n-2)·... ·3·2·1 = n·(n-1) ! + Donc fact(n) = n·fact(n-1) (récursivité) + et fact(1) = 1 (condition d'arrêt) +```C + int fact(int n) { + if (n > 1) { + return n*fact(n1); + } else { + return 1; + } + } + void main() { + int f = fact(4); + } +``` +- Exemple du PGCD + Algorithme d'Euclide pour le PGCD de 42 et 27 + +> 42 = 27·1 + 15 +> 27 = 15·1 + 12 +> 15 = 12·1 + 3 +> 12 = 3·4 + 0 + PGCD(42,27)=PGCD(27,15)=PGCD(15,12)=PGCD(12,3)=3 +```C + int pgcd(int n,int m) { + if (n%m > 0) { + return pgcd(m,n%m); + } else { + return m; + } + } +``` +- Exemple de l'écriture binaire +```C + void binaire(int n) { + printf("%d",n%2); + if (n/2 != 0) { + binaire(n/2); + } else { + printf("\n"); + } + // printf("%d",n%2); + } + + Binaire(13); // affiche 1 0 1 1 puis un retour à la ligne` +``` +> > > $\hspace*{36mm} 2^0 2^1 2^2 2^3$ + +- Que se passe-t-il si on décommente le deuxième `printf` ? + +