-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathlog1-chapitre-tri.tex
1896 lines (1720 loc) · 48.1 KB
/
log1-chapitre-tri.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
%===============
\chapter{Le tri}
%===============
\marginicon{objectif}
Dans ce chapitre nous voyons quelques algorithmes simples pour trier un
ensemble d'informations~: recherche des maxima, tri
par insertion et tri bulle dans un tableau.
Des algorithmes plus efficaces seront vus
en deuxième année.
%===================
\section{Motivation}
%===================
Une application importante de l’informatique est le tri d’informations.
La conception d’algorithmes efficaces pour ce type de traitement s’est
imposée avec l’apparition de bases de données de taille importante. On
citera par exemple la recherche d’un numéro de téléphone ou une adresse
dans la version informatisée des pages blanches, ou de façon plus
spectaculaire l’efficacité de certains moteurs de recherche qui
permettent de retrouver en quelques secondes des mots clés arbitraires
parmi plusieurs millions de pages sur le web.
La recherche efficace d’information implique un tri préalable de
celle-ci. En effet, si les données ne sont pas classées ou triées, le
seul algorithme possible reviendrait à parcourir entièrement l’ensemble
des informations. Pour exemple, il suffit d’imaginer un dictionnaire
dans lequel les mots seraient mélangés de façon aléatoire au lieu
d’être classés par ordre alphabétique. Pour trouver le moindre mot dans
ce dictionnaire, il faudrait à chaque fois le parcourir entièrement !
Il est clair que le classement préalable (ordre alphabétique) accélère
grandement la recherche.
Ainsi, recherche et tri sont étroitement liés, et la façon dont les
informations sont triées conditionne bien entendu la façon de
rechercher l’information (cf. algorithme de recherche dichotomique).
Pour exemple, prenons cette fois-ci un dictionnaire des mots croisés
dans lequel les mots sont d’abord regroupés selon leur longueur et
ensuite par ordre alphabétique. La façon de rechercher un mot dans ce
dictionnaire est bien sûr différente de la recherche dans un
dictionnaire usuel.
Le problème central est donc le tri des informations. Celui-ci a pour
but d’organiser un ensemble d’informations qui ne l’est pas \textit{à
priori}. On peut distinguer trois grands cas de figure~:
\liststyleWWviiiNumi
\begin{enumerate}
\item
D’abord les situations impliquant le classement total d’un ensemble de
données «~bru-tes~», c’est-à-dire complètement désordonnées. Prenons
pour exemple les feuilles récoltées en vrac à l’issue d’un examen ; il
y a peu de chances que celles-ci soient remises à l’examinateur de
manière ordonnée ; celui-ci devra donc procéder au tri de l’ensemble
des copies, par exemple par ordre alphabétique des noms des étudiants,
ou par numéro de groupe etc.
\item
Ensuite les situations où on s’arrange pour ne jamais devoir trier la
totalité des éléments d’un ensemble, qui resterait cependant à tout
moment ordonné. Imaginons le cas d’une bibliothèque~dont les livres
sont rangés par ordre alphabétique des auteurs~: à l’achat d’un nouveau
livre, ou au retour de prêt d’un livre, celui-ci est immédiatement
rangé à la bonne place. Ainsi, l’ordre global de la bibliothèque est
maintenu par la répétition d’une seule opération élémentaire consistant
à insérer à la bonne place un livre parmi la collection. C’est la
situation que nous considérerions dans le cas d'une structure
où les éléments sont ordonnés.
\item
Enfin, les situations qui consistent à devoir re-trier des données
préalablement ordonnées sur un autre critère. Prenons l’exemple d’un
paquet de copies d’examen déjà triées sur l’ordre alphabétique des noms
des étudiants, et qu’on veut re-trier cette fois-ci sur les numéros de
groupe. Il est clair qu’une méthode efficace veillera à conserver
l’ordre alphabétique déjà présent dans la première situation afin que
les copies apparaissent dans cet ordre dans chacun des groupes.
\end{enumerate}
Le dernier cas illustre un classement sur une \textbf{clé complexe}
(ou \textbf{composée}) impliquant la comparaison de plusieurs champs
d’une même structure~: le premier classement se fait sur le numéro de
groupe, et à numéro de groupe égal, l’ordre se départage sur le nom de
l’étudiant. On dira de cet ensemble qu’il est classé en \textbf{majeur}
sur le numéro de groupe et en \textbf{mineur} sur le nom d’étudiant.
Notons que certains tris sont dits \textbf{stables} parce
qu'en cas de tri sur une nouvelle clé, l’ordre de la
clé précédente est préservé pour des valeurs identiques de la nouvelle
clé, ce qui évite de faire des comparaisons sur les deux champs à la
fois. Les méthodes nommées \textbf{tri par insertion}, \textbf{tri
bulle} et \textbf{tri par recherche de minima successifs }(que nous
allons aborder dans ce chapitre) sont stables.
Le tri d’un ensemble d’informations n’offre que des avantages. Outre le
fait déjà mentionné de permettre une recherche et une obtention rapide
de l’information, il permet aussi l’application de traitements
algorithmiques efficaces (comme par exemple celui des ruptures que nous
verrons plus loin) qui s’avéreraient trop coûteux (en temps, donc en
argent !) s’ils s’effectuaient sur des ensembles non triés.
Certains tris sont évidemment plus performants que d’autres. Le choix
d’un tri particulier dépend de la taille de l’ensemble à trier et de la
manière dont il se présente, c’est-à-dire déjà plus ou moins ordonné.
La performance quant à elle se juge sur deux critères~: le nombre de
tests effectués (comparaisons de valeurs) et le nombre de transferts de
valeurs réalisés.
Les algorithmes classiques de tri présentés dans ce chapitre le sont
surtout à titre pédagogique. Ils ont tous une «~complexité en
$n^2$~», ce qui veut dire que si $n$ est le nombre
d’éléments à trier, le nombre d’opérations élémentaires (tests et
transferts de valeurs) est proportionnel à $n^2$. Ils conviennent
donc pour des ensembles de taille «~raisonnable~», mais peuvent devenir
extrêmement lents à l’exécution pour le tri de grands ensembles, comme
par exemple les données de l’annuaire téléphonique. Plusieurs solutions
existent, comme la méthode de tri \textbf{Quicksort}. Cet algorithme
très efficace faisant appel à la récursivité et qui sera étudié en
deuxième année a une complexité en $n \log(n)$.
\marginicon{attention}
Dans ce chapitre, les algorithmes traiteront du tri dans un
\textbf{tableau d’entiers à une }\textbf{dimension}. Toute autre
situation peut bien entendu se ramener à celle-ci moyennant la
définition de la relation d’ordre propre au type de données utilisé. Ce
sera par exemple, l’ordre alphabétique pour les chaines de caractères,
l’ordre chronologique pour des objets \textstyleCodeInsr{Date} ou
\textstyleCodeInsr{Moment} (que nous verrons
plus tard), etc. De plus, le seul ordre envisagé sera l’ordre
\textbf{croissant} des données. Plus loin, on envisagera le tri
d'autres structures de données.
Enfin, dans toutes les méthodes de tri abordées, nous supposerons la
taille physique du tableau à trier (notée $n$) égale à sa taille
logique, celle-ci n’étant pas modifiée par l’action de tri.
%==========================
\section{Tri par insertion}
%===========================
Cette méthode de tri repose sur le principe d’insertion de valeurs dans
un tableau ordonné.
{\sffamily\bfseries\upshape
Description de l’algorithme}
Le tableau à trier sera à chaque étape subdivisé en deux sous-tableaux~:
le premier cadré à gauche contiendra des éléments déjà ordonnés, et le
second, cadré à droite, ceux qu’il reste à insérer dans le sous-tableau
trié. Celui-ci verra sa taille s’accroitre au fur et à mesure des
insertions, tandis que celle du sous-tableau des éléments non triés
diminuera progressivement.
Au départ de l’algorithme, le sous-tableau trié est le premier élément
du tableau. Comme il ne possède qu’un seul élément, ce sous-tableau est
donc bien ordonné ! Chaque étape consiste ensuite à prendre le premier
élément du sous-tableau non trié et à l’insérer à la bonne place dans
le sous-tableau trié.
Prenons comme exemple un tableau \code{tab} de 20 entiers.
Au départ, le sous-tableau trié est formé du premier élément,
\code{tab[1]} qui vaut 20~:
\begin{center}
\begin{tabular}{*{20}{>{\centering\sffamily\itshape\arraybackslash}m{0.47cm}}}
1 &
2 &
3 &
4 &
5 &
6 &
7 &
8 &
9 &
10 &
11 &
12 &
13 &
14 &
15 &
16 &
17 &
18 &
19 &
20
\\
\end{tabular}
\begin{tabular}{|*{20}{>{\centering\arraybackslash}m{0.46cm}|}}
\hline
\multicolumn{1}{|m{0.49700004cm}|}{\cellcolor{gray!25}20} &
{ 12} &
{ 18} &
{ 17} &
{ 15} &
{ 14} &
{ 15} &
{ 16} &
{ 18} &
{ 17} &
{ 12} &
{ 14} &
{ 16} &
{ 18} &
{ 15} &
{ 15} &
{ 19} &
{ 11} &
{ 11} &
{ 13}\\\hline
\end{tabular}
\end{center}
\bigskip
L’étape suivante consiste à insérer \code{tab[2]}, qui vaut 12, dans ce sous-tableau, de
taille 2~:
\begin{center}
\begin{tabular}{*{20}{>{\centering\sffamily\itshape\arraybackslash}m{0.47cm}}}
1 &
2 &
3 &
4 &
5 &
6 &
7 &
8 &
9 &
10 &
11 &
12 &
13 &
14 &
15 &
16 &
17 &
18 &
19 &
20
\\
\end{tabular}
\begin{tabular}{|*{20}{>{\centering\arraybackslash}m{0.46cm}|}}
\hline
\multicolumn{1}{|m{0.49700004cm}|}{\cellcolor{gray!25}12} &
{\cellcolor{gray!25}20} &
{18} &
{ 17} &
{ 15} &
{ 14} &
{ 15} &
{ 16} &
{ 18} &
{ 17} &
{ 12} &
{ 14} &
{ 16} &
{ 18} &
{ 15} &
{ 15} &
{ 19} &
{ 11} &
{ 11} &
{ 13}\\\hline
\end{tabular}
\end{center}
\bigskip
Ensuite, c’est au tour de \code{tab[3]}, qui vaut 18, d’être inséré~:
\begin{center}
\begin{tabular}{*{20}{>{\centering\sffamily\itshape\arraybackslash}m{0.47cm}}}
1 &
2 &
3 &
4 &
5 &
6 &
7 &
8 &
9 &
10 &
11 &
12 &
13 &
14 &
15 &
16 &
17 &
18 &
19 &
20
\\
\end{tabular}
\begin{tabular}{|*{20}{>{\centering\arraybackslash}m{0.46cm}|}}
\hline
{\cellcolor{gray!25}12} &
{\cellcolor{gray!25}18} &
{\cellcolor{gray!25}20} &
{ 17} &
{ 15} &
{ 14} &
{ 15} &
{ 16} &
{ 18} &
{ 17} &
{ 12} &
{ 14} &
{ 16} &
{ 18} &
{ 15} &
{ 15} &
{ 19} &
{ 11} &
{ 11} &
{ 13}\\\hline
\end{tabular}
\end{center}
\bigskip
Et ainsi de suite jusqu’à insertion du dernier élément dans le
sous-tableau trié.
{\sffamily\bfseries
Algorithme}
On combine la recherche de la position d’insertion et le décalage
concomitant de valeurs.
\cadre{
\begin{pseudo}
\LComment Trie le tableau reçu en paramètre (via un tri par insertion).
\Module{triInsertion}{tab\InOut~: tableau[1 à n] d’entiers}{}
\Decl i, j, valAInsérer~: entiers
\For{i \K{de} 2 \K{à} n}
\Let valAInsérer \Gets tab[i]
\LComment recherche de l’endroit où insérer valAInsérer dans le
\LComment sous-tableau trié et décalage simultané des éléments
\Let j \Gets i - 1
\While{j ${\geq}$ 1 ET valAInsérer < tab[j]}
\Let tab[j+1] \Gets tab[j]
\Let j \Gets j – 1
\EndWhile
\Let tab[j+1] \Gets valAInsérer
\EndFor
\EndModule
\end{pseudo}
}
\bigskip
%================================================
\section{Tri par sélection des minima successifs}
%=================================================
Dans ce tri, on recherche à chaque étape la plus petite valeur de
l’ensemble non encore trié et on peut la placer immédiatement
à sa position définitive.
{\sffamily\bfseries\upshape
Description de l’algorithme}
Prenons par exemple un tableau de 20 entiers.
La première étape consiste
à rechercher la valeur minimale du tableau. Il s’agit de l’élément
d’indice 10 et de valeur 17.
\begin{center}
\begin{tabular}{*{20}{>{\centering\sffamily\itshape\arraybackslash}m{0.47cm}}}
1 &
2 &
3 &
4 &
5 &
6 &
7 &
8 &
9 &
10 &
11 &
12 &
13 &
14 &
15 &
16 &
17 &
18 &
19 &
20
\\
\end{tabular}
\begin{tabular}{|*{20}{>{\centering\arraybackslash}m{0.46cm}|}}
\hline
{20} &
{ 52} &
{ 61} &
{ 47} &
{ 82} &
{ 64} &
{ 95} &
{ 66} &
{ 84} &
{\cellcolor{gray!25}17} &
{ 32} &
{ 24} &
{ 46} &
{ 48} &
{ 75} &
{ 55} &
{ 19} &
{ 61} &
{ 21} &
{ 30}\\\hline
\end{tabular}
\end{center}
Celui-ci devrait donc apparaitre en 1\textsuperscript{ère }position du
tableau. Hors, cette position est occupée par la valeur 20. Comment
procéder dès lors pour ne perdre aucune valeur et sans faire appel à un
second tableau ? La solution est simple, il suffit d’échanger le
contenu des deux éléments d’indices 1 et 10~:
\begin{center}
\begin{tabular}{*{20}{>{\centering\sffamily\itshape\arraybackslash}m{0.47cm}}}
1 &
2 &
3 &
4 &
5 &
6 &
7 &
8 &
9 &
10 &
11 &
12 &
13 &
14 &
15 &
16 &
17 &
18 &
19 &
20
\\
\end{tabular}
\begin{tabular}{|*{20}{>{\centering\arraybackslash}m{0.46cm}|}}
\hline
{\cellcolor{gray!25}17} &
{ 52} &
{ 61} &
{ 47} &
{ 82} &
{ 64} &
{ 95} &
{ 66} &
{ 84} &
{ 20} &
{ 32} &
{ 24} &
{ 46} &
{ 48} &
{ 75} &
{ 55} &
{ 19} &
{ 61} &
{ 21} &
{ 30}\\\hline
\end{tabular}
\end{center}
Le tableau se subdivise à présent en deux sous-tableaux, un sous-tableau
déjà trié (pour le moment réduit au seul élément $tab[1]$) et le
sous-tableau des autres valeurs non encore triées (de l’indice 2 à 20).
On recommence ce processus dans ce second sous-tableau~: le minimum est
à présent l'élément d’indice 17 et de valeur 19.
Celui-ci viendra donc en 2\textsuperscript{ème} position, échangeant sa
place avec la valeur 52 qui s’y trouvait~:
\begin{center}
\begin{tabular}{*{20}{>{\centering\sffamily\itshape\arraybackslash}m{0.47cm}}}
1 &
2 &
3 &
4 &
5 &
6 &
7 &
8 &
9 &
10 &
11 &
12 &
13 &
14 &
15 &
16 &
17 &
18 &
19 &
20
\\
\end{tabular}
\begin{tabular}{|*{20}{>{\centering\arraybackslash}m{0.46cm}|}}
\hline
{\cellcolor{gray!25}17} &
{\cellcolor{gray!25}19} &
{ 61} &
{ 47} &
{ 82} &
{ 64} &
{ 95} &
{ 66} &
{ 84} &
{ 20} &
{ 32} &
{ 24} &
{ 46} &
{ 48} &
{ 75} &
{ 55} &
{ 52} &
{ 61} &
{ 21} &
{ 30}\\\hline
\end{tabular}
\end{center}
Le sous-tableau trié est maintenant formé des deux premiers éléments, et
le sous-tableau non trié par les 18 éléments suivants.
Pour un tableau de taille $n$,
à l’étape $i$ de cet algorithme, on sélectionne donc le minimum du
sous-tableau non trié (entre les indices $i$ et $n$). Une
fois le minimum localisé, on l’échange avec l’élément d’indice
$i$. À chaque étape, la taille du sous-tableau trié augmente de
1 et celle du sous-tableau non trié diminue de 1. L’algorithme s’arrête
à la $n$\textsuperscript{ème} étape, lorsque le sous-tableau
trié correspond au tableau de départ. En pratique l’arrêt se fait après
l’étape $n - 1$, car lorsque le sous-tableau non trié n’est plus
que de taille 1, il contient nécessairement le maximum de l’ensemble.
{\sffamily\bfseries\upshape
Algorithme}
\cadre{
\begin{pseudo}
\LComment Trie le tableau reçu en paramètre (via un tri par sélection des minima successifs).
\Module{triSélectionMinimaSuccessifs}{tab\InOut~: tableau[1 à n] d’entiers}{}
\Decl i, indiceMin~: entier
\For{i \K{de} 1 \K{à} n – 1}
\RComment i correspond à l’étape de l’algorithme
\Let indiceMin \Gets positionMin( tab, i, n )
\Stmt swap( tab[i], tab[indiceMin] )
\EndFor
\EndModule
\end{pseudo}
}
\bigskip
\cadre{
\begin{pseudo}
\LComment Retourne l’indice du minimum entre les indices début et fin du tableau reçu.
\Module{positionMin}{tab\In~: tableau[1 à n] d’entiers, début, fin~: entiers}{entier}
\Decl indiceMin, i~: entiers
\Let indiceMin \Gets début
\For{i \K{de} début+1 \K{à} fin}
\If{tab[i] < tab[indiceMin]}
\Decl indiceMin \Gets i
\EndIf
\EndFor
\Return indiceMin
\EndModule
\Empty
\LComment {Échange le contenu de 2 variables.}
\Module{swap}{a\InOut, b\InOut~: entiers}{}
\Decl aux~: entiers
\Let aux \Gets a
\Let a \Gets b
\Let b \Gets aux
\EndModule
\end{pseudo}
}
%==================
\section{Tri bulle}
%===================
Il s’agit d’un tri par \textbf{permutations} ayant pour but d’amener à
chaque étape à la «~surface~» du sous-tableau non trié (on entend par
là l’élément d’indice minimum) la valeur la plus petite, appelée la
\textbf{bulle}. La caractéristique de cette méthode est que les
comparaisons ne se font qu’entre éléments consécutifs du tableau.
{\sffamily\bfseries\upshape
Description de l’algorithme}
Prenons pour exemple un tableau de taille 14. En partant de la fin du
tableau, on le parcourt vers la gauche en comparant chaque couple de
valeurs consécutives. Quand deux valeurs sont dans le désordre, on les
permute. Le premier parcours s’achève lorsqu’on arrive à l’élément
d’indice 1 qui contient alors la «~bulle~»,
c'est-à-dire la plus petite valeur du tableau, soit 1~:
\clearpage
\begin{center}
\begin{tabular}{*{14}{>{\centering\sffamily\itshape\arraybackslash}m{0.75cm}}}
1 &
2 &
3 &
4 &
5 &
6 &
7 &
8 &
9 &
10 &
11 &
12 &
13 &
14
\\
\end{tabular}
\end{center}
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
{10} &
{ 5} &
{ 12} &
{ 15} &
{ 4} &
{ 8} &
{ 1} &
{ 7} &
{ 12} &
{ 11} &
{ 3} &
{ 6} &
{ 5} &
{\cellcolor{gray!25}4}\\\hline
\end{tabular}
\end{center}
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
{10} &
{ 5} &
{ 12} &
{ 15} &
{ 4} &
{ 8} &
{ 1} &
{ 7} &
{ 12} &
{ 11} &
{ 3} &
{ 6} &
{\cellcolor{gray!25}4} &
{ 5}\\\hline
\end{tabular}
\end{center}
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
{10} &
{ 5} &
{ 12} &
{ 15} &
{ 4} &
{ 8} &
{ 1} &
{ 7} &
{ 12} &
{ 11} &
{ 3} &
{\cellcolor{gray!25}4} &
{ 6} &
{ 5}\\\hline
\end{tabular}
\end{center}
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
{10} &
{ 5} &
{ 12} &
{ 15} &
{ 4} &
{ 8} &
{ 1} &
{ 7} &
{ 12} &
{ 11} &
{\cellcolor{gray!25}3} &
{ 4} &
{ 6} &
{ 5}\\\hline
\end{tabular}
\end{center}
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
{10} &
{ 5} &
{ 12} &
{ 15} &
{ 4} &
{ 8} &
{ 1} &
{ 7} &
{ 12} &
{\cellcolor{gray!25}3} &
{ 11} &
{ 4} &
{ 6} &
{ 5}\\\hline
\end{tabular}
\end{center}
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
{10} &
{ 5} &
{ 12} &
{ 15} &
{ 4} &
{ 8} &
{ 1} &
{ 7} &
{\cellcolor{gray!25}3} &
{ 12} &
{ 11} &
{ 4} &
{ 6} &
{ 5}\\\hline
\end{tabular}
\end{center}
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
{10} &
{ 5} &
{ 12} &
{ 15} &
{ 4} &
{ 8} &
{ 1} &
{\cellcolor{gray!25}3} &
{ 7} &
{ 12} &
{ 11} &
{ 4} &
{ 6} &
{ 5}\\\hline
\end{tabular}
\end{center}
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
{10} &
{ 5} &
{ 12} &
{ 15} &
{ 4} &
{ 8} &
{\cellcolor{gray!25}1} &
{ 3} &
{ 7} &
{ 12} &
{ 11} &
{ 4} &
{ 6} &
{ 5}\\\hline
\end{tabular}
\end{center}
\begin{center}
\tablehead{}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
{10} &
{ 5} &
{ 12} &
{ 15} &
{ 4} &
{\cellcolor{gray!25}1} &
{ 8} &
{ 3} &
{ 7} &
{ 12} &
{ 11} &
{ 4} &
{ 6} &
{ 5}\\\hline
\end{tabular}
\end{center}
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
{10} &
{ 5} &
{ 12} &
{ 15} &
{\cellcolor{gray!25}1} &
{ 4} &
{ 8} &
{ 3} &
{ 7} &
{ 12} &
{ 11} &
{ 4} &
{ 6} &
{ 5}\\\hline
\end{tabular}
\end{center}
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
{10} &
{ 5} &
{ 12} &
{\cellcolor{gray!25}1} &
{ 15} &
{ 4} &
{ 8} &
{ 3} &
{ 7} &
{ 12} &
{ 11} &
{ 4} &
{ 6} &
{ 5}\\\hline
\end{tabular}
\end{center}
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
{10} &
{ 5} &
{\cellcolor{gray!25}1} &
{ 12} &
{ 15} &
{ 4} &
{ 8} &
{ 3} &
{ 7} &
{ 12} &
{ 11} &
{ 4} &
{ 6} &
{ 5}\\\hline
\end{tabular}
\end{center}
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
{10} &
{\cellcolor{gray!25}1} &
{ 5} &
{ 12} &
{ 15} &
{ 4} &
{ 8} &
{ 3} &
{ 7} &
{ 12} &
{ 11} &
{ 4} &
{ 6} &
{ 5}\\\hline
\end{tabular}
\end{center}
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
\cellcolor{gray!25}1 &
10 &
5 &
12 &
15 &
4 &
8 &
3 &
7 &
12 &
11 &
4 &
6 &
5
\\\hline
\end{tabular}
\end{center}
Ceci achève le premier parcours. On recommence à présent le même
processus dans le sous-tableau débutant au deuxième élément, ce qui
donnera le contenu suivant~:
\begin{center}
\begin{tabular}{|*{14}{>{\centering\arraybackslash}m{0.75cm}|}}
\hline
1 & 3 & 10 & 5 & 12 & 15 & 4 & 8 & 4 & 7 & 12 & 11 & 5 & 6
\\\hline
\end{tabular}
\end{center}
Comme pour le tri par recherche des minima successifs, à l’issue de
l’étape $i$ de l’algorithme, on obtient un sous-tableau trié
(entre les indices 1 et \textit{i }) et un tableau non encore trié
(entre les indices $i + 1$ et $n$). Le tri est donc
achevé à l’issue de l’étape $n - 1$. Cependant, on notera que
petit à petit, outre le déplacement de la bulle, les éléments plus
petits évoluent progressivement vers la gauche, et les plus gros vers
la droite, de sorte qu’il est fréquent que le nombre d’étapes effectif
est inférieur au nombre d’étapes théorique.
{\sffamily\bfseries\upshape
Algorithme}
Dans cet algorithme, la variable \textstyleCodeInsr{indiceBulle} est à
la fois le compteur d’étapes et aussi l’indice de l’élément récepteur
de la bulle à la fin d’une étape donnée.
\bigskip
\cadre{
\begin{pseudo}
\LComment Trie le tableau reçu en paramètre (via un tri bulle).
\Module{triBulle}{tab\InOut~: tableau[1 à n] d’entiers}{}
\Decl indiceBulle, i~: entiers
\For{indiceBulle \K{de} 1 \K{à} n}
\For{i \K{de} n – 1 \K{à} indiceBulle \K{par} – 1}
\If{tab[i] > tab[i + 1]}
\Stmt swap( tab[i], tab[i + 1] )
\RComment voir algorithme précédent
\EndIf
\EndFor
\EndFor
\EndModule
\end{pseudo}
}
\bigskip
%=========================
\section{Cas particuliers}
%==========================
{\sffamily\bfseries\upshape
Tri partiel}
Parfois, on n’est pas intéressé par un tri complet de l’ensemble mais on
veut uniquement les «~$k$~» plus petites (ou plus grandes) valeurs. Le
tri par recherche des minima et le tri bulle sont particulièrement
adaptés à cette situation ; il suffit de les arrêter plus tôt. Par
contre, le tri par insertion est inefficace car il ne permet pas un
arrêt anticipé.
%--------------------------------------------
% @mcd : le chef demande si on peut virer
% le paragraphe qui suit ?
% --------------------------------------------
{\sffamily\bfseries\upshape
Ensemble (presque) trié}
Les trois tris que nous avons vus ont la même complexité quadratique
(voir plus loin) dans le cas général mais comment se comportent-ils
dans le cas d’un tableau (presque) trié ? Dans ce cas, on peut vérifier
que le tri par recherche des minima successifs reste quadratique alors
que les deux autres deviennent linéaires (en $n$).
{\sffamily\bfseries\upshape
Sélection des meilleurs}
Une autre situation courante est la suivante~: un ensemble de valeurs
sont traitées (lues, calculées, ...) et il ne faut garder que les
$k$ plus petites (ou plus grandes).