diff --git a/banque.c b/banque.c index 02b0e39..aff9e89 100644 --- a/banque.c +++ b/banque.c @@ -71,15 +71,48 @@ Transaction *generer_transactions(int n) /* ------------------------------------------------------------------ */ /* F1 : trie les transactions par montant croissant, puis par id */ -void trier_par_montant(Transaction *t, int n) -{ - for (int i = 0; i < n - 1; i++) { - for (int j = 0; j < n - 1 - i; j++) { - if (t[j].montant > t[j + 1].montant || - (t[j].montant == t[j + 1].montant && t[j].id > t[j + 1].id)) { - Transaction tmp = t[j]; - t[j] = t[j + 1]; - t[j + 1] = tmp; +static void fusionner(Transaction *t, int debut, int milieu, int fin) { + int n1 = milieu - debut + 1; + int n2 = fin - milieu; + + Transaction *gauche = malloc(n1 * sizeof(Transaction)); + Transaction *droite = malloc(n2 * sizeof(Transaction)); + + for (int i = 0; i < n1; i++) + gauche[i] = t[debut + i]; + for (int j = 0; j < n2; j++) + droite[j] = t[milieu + 1 + j]; + + int i = 0, j = 0, k = debut; + + while (i < n1 && j < n2) { + if (gauche[i].montant < droite[j].montant || + (gauche[i].montant == droite[j].montant && gauche[i].id <= droite[j].id)) { + t[k++] = gauche[i++]; + } else { + t[k++] = droite[j++]; + } + } + + while (i < n1) + t[k++] = gauche[i++]; + while (j < n2) + t[k++] = droite[j++]; + + free(gauche); + free(droite); +} + +void trier_par_montant(Transaction *t, int n) { + if (n <= 1) return; + + for (int taille = 1; taille < n; taille *= 2) { + for (int debut = 0; debut < n - 1; debut += 2 * taille) { + int milieu = debut + taille - 1; + int fin = (debut + 2 * taille - 1 < n - 1) ? (debut + 2 * taille - 1) : (n - 1); + + if (milieu < fin) { + fusionner(t, debut, milieu, fin); } } } diff --git a/banque_pg b/banque_pg index 863d807..ec53781 100644 Binary files a/banque_pg and b/banque_pg differ diff --git a/compte_rendu.md b/compte_rendu.md index 261552d..9a7935d 100644 --- a/compte_rendu.md +++ b/compte_rendu.md @@ -1,13 +1,45 @@ -complexités Algorithmique : +# Compte rendu — TD3 Complexité algorithmique (R5.A.04) -F1 : O(n^2) -F2 : O(n^2) -F3 : O(n*c) -F4 : O(n*J) -F5 : O(J^3) -F6 : O(n) -F7: O(n^2) -F8 : O(2^S) -F9 : M=14 -F10 : O(L) +## 1. Complexités algorithmiques +| Fonction | Rôle | Avant | Après | +|---|---|---|---| +| F1 | `trier_par_montant` — tri par montant puis par id | O(n²) | **O(n log n)** (tri fusion) | +| F2 | `nb_clients_distincts` | O(n²) | | +| F3 | `total_par_client` | O(n·c) | | +| F4 | `total_par_jour` | O(n·J) | | +| F5 | `meilleure_periode` | O(J³) | | +| F6 | `rechercher_par_id` | O(n) | | +| F7 | `nb_paires_opposees` | O(n²) | | +| F8 | `nb_facons_rendre` | O(2^S) | | +| F9 | `categorie` | M = 14 | | +| F10 | `ajouter_ligne` | O(L) | | + +## 2. Profil gprof initial + +Programme d'origine compilé avec `gcc -O0 -g -pg`, temps total mesuré : **6,83 s**. + +![Profil gprof initial](gprof/1-%20Original.png) + +`trier_par_montant` représente à elle seule **48 %** du temps (3,28 s) : c'est la première fonction à optimiser. + +## 3. Optimisations + +### 3.1 F1 — `trier_par_montant` : tri à bulles → tri fusion + +**Avant :** tri à bulles, deux boucles imbriquées qui comparent et échangent les éléments voisins → O(n²). + +**Après :** tri fusion itératif (ascendant). On fusionne des sous-tableaux triés de taille 1, 2, 4, 8… jusqu'à couvrir tout le tableau. La fonction `fusionner` copie les deux moitiés dans des tableaux temporaires puis les recombine dans l'ordre → O(n log n). + +L'ordre de tri est conservé (montant croissant, puis id croissant en cas d'égalité), donc l'empreinte reste `ff68d260a7a58441`. + +**Profil gprof après modification :** + +![Profil gprof après tri fusion](gprof/2_modif_tri_par_montant.png) + +| | Avant | Après | +|---|---|---| +| Temps de `trier_par_montant` | 3,28 s | 0,01 s (via `fusionner`) | +| Temps total du programme | 6,83 s | 3,06 s | + +Le tri passe de 48 % du temps à un coût négligeable ; le temps total est divisé par plus de 2. Les fonctions les plus coûteuses sont maintenant `nb_facons_rendre` (30 %), `nb_paires_opposees` (24 %) et `rechercher_par_id` (22 %). diff --git a/gmon.out b/gmon.out index 80fa984..a75709b 100644 Binary files a/gmon.out and b/gmon.out differ diff --git a/gprof/1- Original.png b/gprof/1- Original.png new file mode 100644 index 0000000..d751ff3 Binary files /dev/null and b/gprof/1- Original.png differ diff --git a/gprof/2_modif_tri_par_montant.png b/gprof/2_modif_tri_par_montant.png new file mode 100644 index 0000000..6eddad2 Binary files /dev/null and b/gprof/2_modif_tri_par_montant.png differ diff --git a/profil_avant.txt b/profil_avant.txt index 1a943c5..62edb4b 100644 --- a/profil_avant.txt +++ b/profil_avant.txt @@ -2,82 +2,83 @@ Flat profile: Each sample counts as 0.01 seconds. % cumulative self self total - time seconds seconds calls s/call s/call name - 48.02 3.28 3.28 1 3.28 3.28 trier_par_montant - 12.59 4.14 0.86 30000 0.00 0.00 rechercher_par_id - 11.71 4.94 0.80 1 0.80 0.80 nb_paires_opposees - 9.96 5.62 0.68 1 0.68 0.68 nb_facons_rendre - 6.30 6.05 0.43 6017 0.00 0.00 longueur - 4.69 6.37 0.32 1 0.32 0.32 meilleure_periode - 2.20 6.52 0.15 _init - 1.76 6.64 0.12 1 0.12 0.12 total_par_client - 1.46 6.74 0.10 1 0.10 0.10 nb_clients_distincts - 0.88 6.80 0.06 1 0.06 0.06 total_par_jour - 0.44 6.83 0.03 30000 0.00 0.00 categorie - 0.00 6.83 0.00 149998 0.00 0.00 alea - 0.00 6.83 0.00 6017 0.00 0.00 ajouter_ligne - 0.00 6.83 0.00 1 0.00 0.00 empreinte - 0.00 6.83 0.00 1 0.00 0.00 generer_transactions + time seconds seconds calls ms/call ms/call name + 30.39 0.93 0.93 1 930.00 930.00 nb_facons_rendre + 23.86 1.66 0.73 1 730.00 730.00 nb_paires_opposees + 21.57 2.32 0.66 30000 0.02 0.02 rechercher_par_id + 8.50 2.58 0.26 6017 0.04 0.04 longueur + 7.52 2.81 0.23 1 230.00 230.00 meilleure_periode + 3.59 2.92 0.11 1 110.00 110.00 nb_clients_distincts + 2.61 3.00 0.08 1 80.00 80.00 total_par_client + 1.31 3.04 0.04 1 40.00 40.00 total_par_jour + 0.33 3.05 0.01 30000 0.00 0.00 categorie + 0.33 3.06 0.01 29999 0.00 0.00 fusionner + 0.00 3.06 0.00 149998 0.00 0.00 alea + 0.00 3.06 0.00 6017 0.00 0.04 ajouter_ligne + 0.00 3.06 0.00 1 0.00 0.00 empreinte + 0.00 3.06 0.00 1 0.00 0.00 generer_transactions + 0.00 3.06 0.00 1 0.00 10.00 trier_par_montant Call graph -granularity: each sample hit covers 4 byte(s) for 0.15% of 6.83 seconds +granularity: each sample hit covers 4 byte(s) for 0.33% of 3.06 seconds index % time self children called name -[1] 97.8 0.00 6.68 main [1] - 3.28 0.00 1/1 trier_par_montant [2] - 0.86 0.00 30000/30000 rechercher_par_id [3] - 0.80 0.00 1/1 nb_paires_opposees [4] - 0.68 0.00 1/1 nb_facons_rendre [5] - 0.00 0.43 6017/6017 ajouter_ligne [6] - 0.32 0.00 1/1 meilleure_periode [8] - 0.12 0.00 1/1 total_par_client [10] - 0.10 0.00 1/1 nb_clients_distincts [11] - 0.06 0.00 1/1 total_par_jour [12] - 0.03 0.00 30000/30000 categorie [13] +[1] 100.0 0.00 3.06 main [1] + 0.93 0.00 1/1 nb_facons_rendre [2] + 0.73 0.00 1/1 nb_paires_opposees [3] + 0.66 0.00 30000/30000 rechercher_par_id [4] + 0.00 0.26 6017/6017 ajouter_ligne [5] + 0.23 0.00 1/1 meilleure_periode [7] + 0.11 0.00 1/1 nb_clients_distincts [8] + 0.08 0.00 1/1 total_par_client [9] + 0.04 0.00 1/1 total_par_jour [10] + 0.01 0.00 30000/30000 categorie [11] + 0.00 0.01 1/1 trier_par_montant [13] 0.00 0.00 1/1 generer_transactions [16] 0.00 0.00 1/1 empreinte [15] ----------------------------------------------- - 3.28 0.00 1/1 main [1] -[2] 48.0 3.28 0.00 1 trier_par_montant [2] + 266723738 nb_facons_rendre [2] + 0.93 0.00 1/1 main [1] +[2] 30.4 0.93 0.00 1+266723738 nb_facons_rendre [2] + 266723738 nb_facons_rendre [2] ----------------------------------------------- - 0.86 0.00 30000/30000 main [1] -[3] 12.6 0.86 0.00 30000 rechercher_par_id [3] + 0.73 0.00 1/1 main [1] +[3] 23.9 0.73 0.00 1 nb_paires_opposees [3] ----------------------------------------------- - 0.80 0.00 1/1 main [1] -[4] 11.7 0.80 0.00 1 nb_paires_opposees [4] + 0.66 0.00 30000/30000 main [1] +[4] 21.6 0.66 0.00 30000 rechercher_par_id [4] ----------------------------------------------- - 266723738 nb_facons_rendre [5] - 0.68 0.00 1/1 main [1] -[5] 10.0 0.68 0.00 1+266723738 nb_facons_rendre [5] - 266723738 nb_facons_rendre [5] + 0.00 0.26 6017/6017 main [1] +[5] 8.5 0.00 0.26 6017 ajouter_ligne [5] + 0.26 0.00 6017/6017 longueur [6] ----------------------------------------------- - 0.00 0.43 6017/6017 main [1] -[6] 6.3 0.00 0.43 6017 ajouter_ligne [6] - 0.43 0.00 6017/6017 longueur [7] + 0.26 0.00 6017/6017 ajouter_ligne [5] +[6] 8.5 0.26 0.00 6017 longueur [6] ----------------------------------------------- - 0.43 0.00 6017/6017 ajouter_ligne [6] -[7] 6.3 0.43 0.00 6017 longueur [7] + 0.23 0.00 1/1 main [1] +[7] 7.5 0.23 0.00 1 meilleure_periode [7] ----------------------------------------------- - 0.32 0.00 1/1 main [1] -[8] 4.7 0.32 0.00 1 meilleure_periode [8] + 0.11 0.00 1/1 main [1] +[8] 3.6 0.11 0.00 1 nb_clients_distincts [8] ----------------------------------------------- - -[9] 2.2 0.15 0.00 _init [9] + 0.08 0.00 1/1 main [1] +[9] 2.6 0.08 0.00 1 total_par_client [9] ----------------------------------------------- - 0.12 0.00 1/1 main [1] -[10] 1.8 0.12 0.00 1 total_par_client [10] + 0.04 0.00 1/1 main [1] +[10] 1.3 0.04 0.00 1 total_par_jour [10] ----------------------------------------------- - 0.10 0.00 1/1 main [1] -[11] 1.5 0.10 0.00 1 nb_clients_distincts [11] + 0.01 0.00 30000/30000 main [1] +[11] 0.3 0.01 0.00 30000 categorie [11] ----------------------------------------------- - 0.06 0.00 1/1 main [1] -[12] 0.9 0.06 0.00 1 total_par_jour [12] + 0.01 0.00 29999/29999 trier_par_montant [13] +[12] 0.3 0.01 0.00 29999 fusionner [12] ----------------------------------------------- - 0.03 0.00 30000/30000 main [1] -[13] 0.4 0.03 0.00 30000 categorie [13] + 0.00 0.01 1/1 main [1] +[13] 0.3 0.00 0.01 1 trier_par_montant [13] + 0.01 0.00 29999/29999 fusionner [12] ----------------------------------------------- 0.00 0.00 149998/149998 generer_transactions [16] [14] 0.0 0.00 0.00 149998 alea [14] @@ -92,8 +93,8 @@ index % time self children called name Index by function name - [9] _init [16] generer_transactions [4] nb_paires_opposees - [6] ajouter_ligne [7] longueur [3] rechercher_par_id - [14] alea [8] meilleure_periode [10] total_par_client - [13] categorie [11] nb_clients_distincts [12] total_par_jour - [15] empreinte [5] nb_facons_rendre [2] trier_par_montant + [5] ajouter_ligne [16] generer_transactions [3] nb_paires_opposees + [14] alea [6] longueur [4] rechercher_par_id + [11] categorie [7] meilleure_periode [9] total_par_client + [15] empreinte [8] nb_clients_distincts [10] total_par_jour + [12] fusionner (banque.c) [2] nb_facons_rendre [13] trier_par_montant