opti tri_par_montant

This commit is contained in:
2026-10-21 12:04:00 +02:00
parent 11303d3e2b
commit 8cce27c295
7 changed files with 146 additions and 80 deletions
+42 -9
View File
@@ -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);
}
}
}
BIN
View File
Binary file not shown.
+43 -11
View File
@@ -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 %).
BIN
View File
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

+61 -60
View File
@@ -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
<spontaneous>
[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]
-----------------------------------------------
<spontaneous>
[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