forked from menault/2026_TD3_DEV51_Qualite_Algo
Optimiser F7 par tri et parcours à deux pointeurs
This commit is contained in:
@@ -313,3 +313,21 @@ des transactions imposerait de reconstruire l'index. F6 garde **M = 3** et
|
||||
`indexer_par_id` a **M = 2**. Les tests comparent les pointeurs renvoyés
|
||||
à une recherche linéaire sur des identifiants permutés pour les tailles
|
||||
1 à 128, et vérifient les recherches hors bornes et dans un tableau vide.
|
||||
|
||||
### F7 — Tri et deux pointeurs pour les paires opposées
|
||||
|
||||
Une copie des transactions est triée avec F1 pour préserver l'ordre du
|
||||
tableau d'entrée. Deux pointeurs partent ensuite des extrémités : une somme
|
||||
négative fait avancer le pointeur gauche, une somme positive fait reculer
|
||||
le droit. Pour deux montants opposés, on compte leurs multiplicités `a` et
|
||||
`b` et on ajoute `a × b`. Pour un groupe de `z` zéros, on ajoute
|
||||
`z(z - 1) / 2` : chaque paire d'indices distincts est comptée une seule fois.
|
||||
|
||||
Le tri coûte `O(n log n)` et chaque pointeur traverse au plus `n` éléments,
|
||||
soit **`O(n log n)`** au total au lieu de `O(n²)`, avec `O(n)` de mémoire.
|
||||
F7 passe de **M = 4 à M = 3** ; l'auxiliaire `compter_paires_triees` a
|
||||
**M = 9**. Les tests comparent le compteur à l'énumération de toutes les
|
||||
paires sur les **97 655 tableaux** de longueur 1 à 7 à montants dans
|
||||
`[-2, 2]`, ainsi que sur une entrée vide. Ils vérifient aussi que les
|
||||
transactions d'origine restent inchangées, notamment en présence de
|
||||
doublons et de plusieurs zéros.
|
||||
|
||||
@@ -186,13 +186,53 @@ const Transaction *rechercher_par_id(const Transaction *const *index_ids, int n,
|
||||
}
|
||||
|
||||
/* F7 : nombre de paires de transactions de montants opposés (a + b = 0) */
|
||||
long nb_paires_opposees(const Transaction *t, int n)
|
||||
static long compter_paires_triees(const Transaction *t, int n)
|
||||
{
|
||||
long nb = 0;
|
||||
for (int i = 0; i < n; i++)
|
||||
for (int j = i + 1; j < n; j++)
|
||||
if (t[i].montant + t[j].montant == 0)
|
||||
nb++;
|
||||
int gauche = 0;
|
||||
int droite = n - 1;
|
||||
while (gauche < droite) {
|
||||
long somme = t[gauche].montant + t[droite].montant;
|
||||
if (somme < 0) {
|
||||
gauche++;
|
||||
} else if (somme > 0) {
|
||||
droite--;
|
||||
} else if (t[gauche].montant == 0) {
|
||||
long taille = droite - gauche + 1;
|
||||
nb += taille * (taille - 1) / 2;
|
||||
break;
|
||||
} else {
|
||||
long nb_gauche = 1;
|
||||
long nb_droite = 1;
|
||||
while (gauche + 1 < droite && t[gauche + 1].montant == t[gauche].montant) {
|
||||
gauche++;
|
||||
nb_gauche++;
|
||||
}
|
||||
while (droite - 1 > gauche && t[droite - 1].montant == t[droite].montant) {
|
||||
droite--;
|
||||
nb_droite++;
|
||||
}
|
||||
nb += nb_gauche * nb_droite;
|
||||
gauche++;
|
||||
droite--;
|
||||
}
|
||||
}
|
||||
return nb;
|
||||
}
|
||||
|
||||
long nb_paires_opposees(const Transaction *t, int n)
|
||||
{
|
||||
if (n < 2)
|
||||
return 0;
|
||||
Transaction *copie = malloc((size_t)n * sizeof(*copie));
|
||||
if (copie == NULL) {
|
||||
perror("Allocation de la copie des transactions");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
memcpy(copie, t, (size_t)n * sizeof(*copie));
|
||||
trier_par_montant(copie, n);
|
||||
long nb = compter_paires_triees(copie, n);
|
||||
free(copie);
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
@@ -177,6 +177,36 @@ static void tester_recherches(void)
|
||||
}
|
||||
}
|
||||
|
||||
static long paires_reference(const Transaction *t, int n)
|
||||
{
|
||||
long nb = 0;
|
||||
for (int i = 0; i < n; i++)
|
||||
for (int j = i + 1; j < n; j++)
|
||||
if (t[i].montant + t[j].montant == 0)
|
||||
nb++;
|
||||
return nb;
|
||||
}
|
||||
|
||||
static void tester_paires(void)
|
||||
{
|
||||
assert(nb_paires_opposees(NULL, 0) == 0);
|
||||
Transaction t[7], original[7];
|
||||
int nb_cas = 1;
|
||||
for (int n = 1; n <= 7; n++) {
|
||||
nb_cas *= 5;
|
||||
for (int cas = 0; cas < nb_cas; cas++) {
|
||||
int valeurs = cas;
|
||||
for (int i = 0; i < n; i++) {
|
||||
t[i] = (Transaction){i, i, i, valeurs % 5 - 2};
|
||||
valeurs /= 5;
|
||||
}
|
||||
memcpy(original, t, (size_t)n * sizeof(*t));
|
||||
assert(nb_paires_opposees(t, n) == paires_reference(t, n));
|
||||
assert(memcmp(original, t, (size_t)n * sizeof(*t)) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
tester_tri();
|
||||
@@ -185,6 +215,7 @@ int main(void)
|
||||
tester_totaux_jours();
|
||||
tester_periodes();
|
||||
tester_recherches();
|
||||
tester_paires();
|
||||
puts("Tests banque : OK");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user