# Compte rendu — TD 3 : complexité algorithmique Nathan COUCHOT et Lucas POT ## 1. Mesurer le programme ```bash gcc -O2 banque.c -o banque time ./banque ``` La version initiale s'exécute en environ **2,26 s**. | Mesure initiale | Résultat | | --- | ---: | | Temps réel (`real`) | 2,26 s | | Temps CPU utilisateur (`user`) | 2,23 s | | Temps CPU système (`sys`) | 0,00 s | | Empreinte | `ff68d260a7a58441` | L'empreinte attendue est **`ff68d260a7a58441`**. ## 2. Profiler et analyser le programme initial ```bash gcc -O0 -g -pg banque.c -o banque_pg ./banque_pg gprof ./banque_pg gmon.out > profil_avant.txt ``` Le temps réel mesuré avec l'instrumentation est **8,35 s**, contre **2,26 s** sans `-pg`. Cette différence vient en partie du coût ajouté par le comptage des appels. Le profil complet est fourni dans profil_avant.txt. | Fonction | Part du temps propre | Temps propre | Appels | | --- | ---: | ---: | ---: | | `trier_par_montant` | 49,43 % | 3,02 s | 1 | | `rechercher_par_id` | 13,42 % | 0,82 s | 30 000 | | `nb_paires_opposees` | 11,95 % | 0,73 s | 1 | | `nb_facons_rendre` | 8,27 % | 0,51 s | 1 appel depuis `main` | | `longueur` | 6,87 % | 0,42 s | 6 017 | | `meilleure_periode` | 4,91 % | 0,30 s | 1 | | `total_par_client` | 1,80 % | 0,11 s | 1 | | `nb_clients_distincts` | 1,64 % | 0,10 s | 1 | | `total_par_jour` | 0,82 % | 0,05 s | 1 | Le tri à bulles est le principal point chaud du profil. `rechercher_par_id` est appelée 30 000 fois et parcourt le tableau à chaque recherche. `ajouter_ligne` appelle `longueur` pour retrouver la fin du rapport ; comme le rapport grandit à chaque ajout, ces recherches répétées reparcourent une quantité croissante de caractères. Le graphe d'appels permet aussi de voir le coût récursif de `nb_facons_rendre`. Le profil plat ne montre qu'un appel depuis `main`, mais cet appel entraîne de nombreux appels récursifs. Le temps propre observé ne suffit donc pas à lui seul pour expliquer le coût total. Les fonctions les plus coûteuses n'ont pas nécessairement les complexités les plus élevées. Le tri traite 30 000 transactions, tandis que `meilleure_periode` traite 1 000 jours. Le temps mesuré dépend à la fois de la complexité et de la taille effective des données. ## 3. Complexités algorithmiques et cyclomatiques On note **n** le nombre de transactions, **C** le nombre de clients, **J** le nombre de jours, **Q** le nombre de requêtes, **S** la somme à rendre, **k** le nombre de pièces et **L** la longueur finale du rapport. Les paramètres sont considérés variables pour l'analyse, même si le programme utilise des constantes. | Fonction | Calcule | Actuelle | Objectif | | --- | --- | --- | --- | | F1 `trier_par_montant` | tri des transactions | O(n²) | O(n log n) | | F2 `nb_clients_distincts` | clients différents | O(n²) | O(n + C) | | F3 `total_par_client` | solde par client | O(n * c) | O(n + C) | | F4 `total_par_jour` | solde par jour | O(n * J) | O(n + J) | | F5 `meilleure_periode` | période la plus rentable | O(J³) | O(J) | | F6 `rechercher_par_id` | recherche par identifiant | O(n) | O(1) par requête | | F7 `nb_paires_opposees` | paires a + b = 0 | O(n²) | O(n log n) | | F8 `nb_facons_rendre` | rendu de monnaie | O(S^n) | O(S × k) | | F9 `categorie` | catégorie d'une transaction | M = 14 | M ≤ 10 | | F10 `ajouter_ligne` | construction du rapport | O(n) | O(L) au total | ### Complexité cyclomatique des fonctions F1 à F10 On calcule **M = nombre de décisions + 1**. | Fonction | Décisions | Calcul de M | | --- | --- | ---: | | F1 `trier_par_montant` | 2 `for` + 1 `if` + 1 `||` + 1 `&&` | 5 + 1 = **6** | | F2 `nb_clients_distincts` | 2 `for` + 2 `if` | 4 + 1 = **5** | | F3 `total_par_client` | 2 `for` + 1 `if` | 3 + 1 = **4** | | F4 `total_par_jour` | 2 `for` + 1 `if` | 3 + 1 = **4** | | F5 `meilleure_periode` | 3 `for` + 1 `if` | 4 + 1 = **5** | | F6 `rechercher_par_id` | 1 `for` + 1 `if` | 2 + 1 = **3** | | F7 `nb_paires_opposees` | 2 `for` + 1 `if` | 3 + 1 = **4** | | F8 `nb_facons_rendre` | 2 `if` + 1 `||` | 3 + 1 = **4** | | F9 `categorie` | 11 `if`/`else if` + 1 `||` + 1 `&&` | 13 + 1 = **14** | | F10 `ajouter_ligne` | 1 `while` | 1 + 1 = **2** |