diff --git a/COMPTE_RENDU.md b/COMPTE_RENDU.md index 60db236..d8b58f9 100644 --- a/COMPTE_RENDU.md +++ b/COMPTE_RENDU.md @@ -299,3 +299,17 @@ conservés comme dans les boucles initiales. Les **97 655 séries** de longueur 1 à 7 à valeurs dans `[-2, 2]` sont comparées à la version cubique, sur la somme et sur les deux bornes : elles couvrent notamment les zéros, les égalités et les séries entièrement négatives. + +### F6 — Index direct par identifiant + +Les identifiants sont une permutation de `[0, n - 1]`. Un index de pointeurs +est construit en **`O(n)`** avant la boucle des requêtes. Chaque recherche +contrôle les bornes et renvoie `index_ids[id]` en **`O(1)`**, au lieu de +parcourir les transactions en `O(n)`. Le coût des `Q` requêtes, construction +comprise, devient **`O(n + Q)`**, avec `O(n)` de mémoire supplémentaire. + +Les recherches ont toutes lieu avant le tri des transactions : un déplacement +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. diff --git a/banque.c b/banque.c index f2a50f9..9c06b76 100644 --- a/banque.c +++ b/banque.c @@ -171,12 +171,18 @@ long meilleure_periode(const long *totaux, int nb_jours, int *debut, int *fin) } /* F6 : retrouve une transaction à partir de son id */ -const Transaction *rechercher_par_id(const Transaction *t, int n, int id) +/* Les id forment une permutation de 0 à n - 1. Reconstruire après tout tri. */ +void indexer_par_id(const Transaction *t, int n, const Transaction **index_ids) { for (int i = 0; i < n; i++) - if (t[i].id == id) - return &t[i]; - return NULL; + index_ids[t[i].id] = &t[i]; +} + +const Transaction *rechercher_par_id(const Transaction *const *index_ids, int n, int id) +{ + if (id < 0 || id >= n) + return NULL; + return index_ids[id]; } /* F7 : nombre de paires de transactions de montants opposés (a + b = 0) */ @@ -280,11 +286,13 @@ int main(void) rapport[0] = '\0'; /* recherches par id, dans l'ordre d'origine */ + static const Transaction *index_ids[NB_TRANSACTIONS]; + indexer_par_id(t, NB_TRANSACTIONS, index_ids); long somme_requetes = 0; unsigned long etat = 12345; for (int q = 0; q < NB_REQUETES; q++) { etat = etat * 1103515245UL + 12345UL; - const Transaction *r = rechercher_par_id(t, NB_TRANSACTIONS, (int)((etat >> 8) % NB_TRANSACTIONS)); + const Transaction *r = rechercher_par_id(index_ids, NB_TRANSACTIONS, (int)((etat >> 8) % NB_TRANSACTIONS)); if (r != NULL) somme_requetes += r->montant; } diff --git a/tests/test_banque.c b/tests/test_banque.c index 967a048..b98ade6 100644 --- a/tests/test_banque.c +++ b/tests/test_banque.c @@ -154,6 +154,29 @@ static void tester_periodes(void) } } +static void tester_recherches(void) +{ + assert(rechercher_par_id(NULL, 0, 0) == NULL); + assert(rechercher_par_id(NULL, 0, -1) == NULL); + Transaction t[128]; + const Transaction *index_ids[128]; + for (int n = 1; n <= 128; n++) { + for (int i = 0; i < n; i++) + t[i] = (Transaction){n - 1 - i, i, i, i * 77 - 12}; + indexer_par_id(t, n, index_ids); + for (int id = 0; id < n; id++) { + const Transaction *attendu = NULL; + for (int i = 0; i < n; i++) + if (t[i].id == id) + attendu = &t[i]; + assert(rechercher_par_id(index_ids, n, id) == attendu); + } + assert(rechercher_par_id(index_ids, n, -1) == NULL); + assert(rechercher_par_id(index_ids, n, n) == NULL); + assert(rechercher_par_id(index_ids, n, INT_MAX) == NULL); + } +} + int main(void) { tester_tri(); @@ -161,6 +184,7 @@ int main(void) tester_totaux_clients(); tester_totaux_jours(); tester_periodes(); + tester_recherches(); puts("Tests banque : OK"); return 0; }