Algorithmes de base

Factorielle

Complexité : \( C_n = \mathcal{O}(n) \)

let rec factorielle n = if n = 0 then 1 else n * (factorielle (n - 1))

HR : "Si \( n \) désigne l'entrée, factorielle n termine et renvoie \( n! \)"

int factorielle(int n) {
  int res = 1;
  for (int i = 1; i <= n; i += 1) {
    res *= i;
  }
  return res;
}

Variant : \( n + 1 - i \)

Invariant : \( res = i! \)

Expo rapide

Complexité : \( C_n = \mathcal{O}(log(n)) \)

let rec expo_rapide x n = if n = 0 then 1
  else if n mod 2 = 0 then expo_rapide (x*x) (n/2)
  else x * (expo_rapide (x*x) ((n - 1) / 2))

HR : Par récurence sur \( n \) : "expo_rapide x n termine et renvoie \( x^n \)"

int expo_rapide(int x, int n) {
  int resultat = 1;
  while (n > 0) {
    if (n % 2 == 0) {
      n = n/2;
    } else {
      resultat *= x;
      n = (n - 1)/2;
    }
    x = x*x;
  }
  return resultat;
}

Variant : \( n \)

Invariant : En notant \( N \) la valeur initiale de \( n \) et \( X \) la valeur initiale de \( x \), on prend \( X^N = resultat \cdot (x^n) \)

Euclide

Complexité : Pas au programme, nous n'avons pas les outils pour la calculer

let rec euclide a b = if b = 0 then a else euclide b (a mod b)

HR : Récurrence sur \( b \). "euclide a b termine et renvoie \( pgcd(a,b) \)"

int euclide(int a, int b) {
  while (b > 0) {
    int tmp = a;
    a = b;
    b = tmp % b;
  }
  return a;
}

Variant : \( b \)

Invariant : En notant \( A \) et \( B \) les valeurs originales de \( a \) et \( b \) on prend \( pgcd(a,b) = pgcd(A,B) \)

PS : Pour la récurrence/l'invariant voir le cours de maths pour la relation entre pgcd de deux nombres et division euclidienne.

Recherche dichotomique

Complexité : \( C_n = \mathcal{O}(log(n)) \)

let rec recherche_dicho_interne tab value imin imax = if imin > imax then false
  else let imoy = (imin + imax) / 2 in let vmoy = t.(imoy) in
  if vmoy = value then true
  else if vmoy < value then recherche_dicho_interne tab value (imoy + 1) imax
  else recherche_dicho_interne tab value imin (imoy - 1)

let recherche_dicho tab value = recherche_dicho_interne tab value 0 (Array.length tab - 1)

HR (pour recherche_dicho_interne) : Sur \( imax - imin \), "recherche_dicho_interne et renvoie vrai si et seulement si la valeur \( val \) est dans le tableau entre les indices \( imin \) et \( imax \)"

bool recherche_dichotomique(int tab[], int taille_tab, int val) {
  int imin = 0;
  int imax = taille_tab - 1;
  while (imin <= imax) {
    int imoy = (imin + imax) / 2;
    int vmoy = tab[imoy];
    if (vmoy == val) {
      return true;
    } else if (vmoy < val) {
      imin = imoy + 1;
    } else {
      imax = imoy - 1;
    }
  }
  return false;
}

Variant : \( imax - imin \)

Invariant : "Si tab contient val c'est entre les indices imin et imax"

Nombre de chiffre d'un entier naturel

Complexité : \( C_n = \mathcal{O}(k) \) où \( k \) désigne le nombre de chiffres de \( n \)

let rec nb_chiffres n = if n < 10 then 1 else
  1 + (nb_chiffres (n / 10))

HR : "nb_chiffres(n) termine et renvoie le nombre de chiffre de n"

int nb_chiffres(int n) {
  int nb = 1;
  while (n > 9) {
    nb += 1;
    n = n / 10;
  }
  return nb;
}

Variant : \( n \)

Invariant : En notant \( N \) la valeur initiale de \( n \), et \( l(a) \) le nombre de chiffres de \( a \), on pose \( l(N) = l(n) + nb \)