4.1 KiB
Compte rendu — TD 3 : complexité algorithmique
Nathan COUCHOT et Lucas POT
1. Mesurer le programme
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
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 ` |
|
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 ` |
|
F9 categorie |
11 if/else if + 1 ` |
|
F10 ajouter_ligne |
1 while |
1 + 1 = 2 |