Remplacement du tri à bulles par un tri par tas pour améliorer les performances de tri

This commit is contained in:
rabot
2026-10-07 12:20:50 +02:00
parent 1c4405c75e
commit 57c9ce933b
6 changed files with 237 additions and 9 deletions
+51 -1
View File
@@ -365,4 +365,54 @@ Empreinte du rapport : 1d53de903efd2b7c
real 0m0.751s
user 0m0.703s
sys 0m0.004s
```
```
## Remplacement du tri à bulles par un tri par tas
Le tri à bulles effectuait systématiquement n(n - 1)/2 comparaisons,
soit 17 202 045 appels à `doit_echanger` pour 5 866 mots distincts.
`trier_entrees` utilise maintenant un tri par tas. La racine du tas contient
l'entrée qui doit apparaître le plus tard dans le classement. Elle est
échangée avec la dernière entrée de la partie non triée, puis `retablir_tas`
restaure cette propriété sur les entrées restantes. La construction du tas
coûte O(n), puis les extractions coûtent O(log n) chacune : le tri complet
passe de O(n²) à O(n log n), y compris dans le pire cas.
Le tri travaille directement dans le tableau, avec O(1) de mémoire
supplémentaire. `doit_echanger` reste inchangée : fréquence décroissante,
puis ordre alphabétique croissant. Chaque échange déplace l'entrée entière,
y compris la longueur mémorisée.
Profil enregistré dans [out/profil_apres_tri.txt](out/profil_apres_tri.txt).
La comparaison porte sur la version précédente, décrite dans
`out/profil_apres_longueurs.txt`.
| Mesure | Tri à bulles | Tri par tas |
| --- | ---: | ---: |
| Appels à `doit_echanger` pendant le tri | 17 202 045 | 129 602 |
| Appels à `comparer` pour départager les fréquences égales | 12 172 087 | 32 813 |
| Temps réel médian du programme sans profiling (`gcc -O0`, 5 exécutions par version) | 0,367 s | 0,113 s |
Le tri effectue environ 133 fois moins de comparaisons d'entrées.
Le temps total baisse de 69,3 %, soit une accélération d'environ 3,25.
Les cinq mesures, réalisées en alternant les deux versions sur la même
machine, sont respectivement : 0,365 / 0,363 / 0,372 / 0,383 / 0,367 s
avant, et 0,112 / 0,113 / 0,115 / 0,113 / 0,112 s après.
Validation : compilation sans avertissement avec `-Wall -Wextra -Wpedantic`,
rapport et sortie console identiques octet par octet sur les dix exécutions,
avec `-pg` et sous AddressSanitizer et UndefinedBehaviorSanitizer.
L'empreinte reste **`1d53de903efd2b7c`**.
Des tests temporaires ont comparé le résultat à `qsort` sur des tableaux
de 0 à 20 000 entrées, aléatoires, déjà triés ou inversés. Ils vérifient
aussi les fréquences égales, les doublons, les préfixes, les valeurs
extrêmes de fréquence et la conservation des longueurs des mots.
Commandes pour reproduire ce profil :
```bash
mkdir -p out/apres_tri
gcc -O0 -pg analyseur.c -o out/apres_tri/analyseur
(cd out/apres_tri && ./analyseur && gprof -b ./analyseur gmon.out > ../profil_apres_tri.txt)
```