J'essaie de comprendre quelques algorithmes de tri, mais j'ai du mal à voir la différence entre les algorithmes de tri à bulle et à insertion.
Je sais que les deux sont O (n2), mais il me semble que le tri par bulle ne fait que calquer la valeur maximale du tableau vers le haut pour chaque passe, tandis que le tri par insertion ne fait que plonger la valeur la plus basse vers le bas à chaque passe. Ne font-ils pas exactement la même chose mais dans des directions différentes?
Pour le tri par insertion, le nombre de comparaisons/échanges potentiels commence à zéro et augmente chaque fois (c'est-à-dire 0, 1, 2, 3, 4, ..., n), mais pour le tri à bulle, le même problème se produit, mais à la fin de le tri (c.-à-d. n, n-1, n-2, ... 0), car le tri par bulle n'a plus besoin d'être comparé aux derniers éléments au fur et à mesure qu'ils sont triés.
Pour tout cela cependant, il semble un consensus que le type d'insertion est mieux en général. Quelqu'un peut-il me dire pourquoi?
Edit: Je suis principalement intéressé par les différences de fonctionnement des algorithmes, et non par leur efficacité ou leur complexité asymptotique.
En tri bulle dans la itération, vous avez ni-1 itérations internes (n ^ 2)/2 au total, mais en tri par insertion, vous avez le maximum d'itérations à la cinquième étape, mais i/2 en moyenne car vous pouvez arrêter la boucle plus tôt, après avoir trouvé la position correcte pour l’élément en cours. Donc vous avez (somme de 0 à n)/2 qui est (n ^ 2)/4 total;
C'est pourquoi le tri par insertion est plus rapide que le tri par bulle.
Après i itérations, les premiers i éléments sont ordonnés.
À chaque itération, l'élément suivant est envoyé dans la section sort - jusqu'à ce qu'il atteigne le bon endroit:
sorted | unsorted
1 3 5 8 | 4 6 7 9 2
1 3 4 5 8 | 6 7 9 2
Le 4 est barboté dans la section triée
Pseudocode:
for i in 1 to n
for j in i downto 2
if array[j - 1] > array[j]
swap(array[j - 1], array[j])
else
break
Après i itérations, les derniers éléments i sont les plus gros et ordonnés.
À chaque itération, parcourez la section unsorted pour trouver le maximum.
unsorted | biggest
3 1 5 4 2 | 6 7 8 9
1 3 4 2 | 5 6 7 8 9
Le 5 est projeté hors de la section non triée
Pseudocode:
for i in 1 to n
for j in 1 to n - i
if array[j] > array[j + 1]
swap(array[j], array[j + 1])
Notez que les implémentations typiques se terminent tôt si aucun échange n'est effectué pendant l'une des itérations de la boucle externe (car cela signifie que le tableau est trié).
Dans l'insertion, les éléments de tri sont filtrés dans la section triée, tandis que dans le tri à bulles, les maximums sont filtrés dans la section non triée.
Une autre différence, je n'ai pas vu ici:
Tri par bulles a 3 assignations de valeurs par échange : Vous devez d'abord créer une variable temporaire pour enregistrer la valeur que vous voulez transmettre (n ° 1), puis écrire l'autre swap-variable à l'endroit où vous venez de sauvegarder la valeur (n ° 2), puis vous devez écrire votre variable temporaire à l'emplacement autre (n ° 3) . Vous devez le faire pour chaque emplacement - vous vouloir aller de l'avant - pour trier votre variable au bon endroit.
Avec insertion trier , vous mettez votre variable à trier dans une variable temporaire, puis vous placez toutes les variables en face de cet emplacement 1 point en arrière, tant que vous atteignez le bon emplacement pour votre variable. Cela fait 1 assignation de valeur par spot . En fin de compte, vous écrivez votre variable-temp dans le spot.
Cela fait aussi beaucoup moins d'affectations de valeur.
Ce n’est pas le principal avantage en termes de vitesse, mais je pense que cela peut être mentionné.
J'espère que je me suis bien compris, sinon, désolée, je ne suis pas une Grande-Bretagne
Le principal avantage du tri par insertion est qu'il s'agit d'un algorithme en ligne. Vous n'avez pas besoin d'avoir toutes les valeurs au début. Cela pourrait être utile lorsque vous manipulez des données provenant du réseau ou de certains capteurs.
J'ai l'impression que cela serait plus rapide que d'autres algorithmes n log(n)
conventionnels. Parce que la complexité serait n*(n log(n))
p. Ex. lire/stocker chaque valeur du flux (O(n)
) puis en triant toutes les valeurs (O(n log(n))
), ce qui donne O(n^2 log(n))
Au contraire, utiliser Insert Sort nécessite O(n)
pour lire les valeurs du flux et O(n)
pour placer la valeur au bon endroit, donc O(n^2)
uniquement. Un autre avantage est que vous n’avez pas besoin de tampons pour stocker les valeurs, vous les triez dans la destination finale.
Bubble Sort n'est pas en ligne (il ne peut pas trier un flux d'entrées sans savoir combien d'éléments il y aura) car il ne garde pas vraiment la trace d'un maximum global d'éléments triés. Lorsqu'un élément est inséré, vous devrez commencer le bouillonnement dès le début.
ainsi, le tri à bulles est préférable au tri par insertion uniquement lorsque quelqu'un recherche les k éléments les plus performants parmi une grande liste de nombres Dans bulle trier après k itérations vous obtiendrez k premiers éléments. Cependant, après k itérations dans le tri par insertion, cela garantit uniquement que ces k éléments sont triés.
Le tri à bulles est presque inutile en toutes circonstances. Dans les cas d'utilisation où le tri par insertion peut comporter trop de swaps, le tri par sélection peut être utilisé car il garantit moins de N fois de swap. Étant donné que le tri par sélection est meilleur que le tri à bulles, le tri à bulles n'a pas de cas d'utilisation.
Bien que les deux tris soient O (N ^ 2). Les constantes masquées sont beaucoup plus petites dans le tri par insertion. Les constantes masquées font référence au nombre réel d'opérations primitives effectuées.
Quand le tri par insertion a un meilleur temps d'exécution?
Notez que le tri par insertion n'est pas toujours meilleur que le tri par bulle. Pour obtenir le meilleur des deux mondes, vous pouvez utiliser le tri par insertion si le tableau est de petite taille et probablement fusionner le tri (ou le tri rapide) pour les tableaux plus grands.
Le tri par insertion peut être repris sous la forme " Recherchez l'élément qui devrait être en première position (le minimum), faites de la place en décalant les éléments suivants et mettez-le en première position. Bon. Maintenant, regardez l'élément qui devrait être à 2e .... "et ainsi de suite ...
Le tri des bulles fonctionne différemment et peut être repris comme " Tant que je trouve deux éléments adjacents dans le mauvais ordre, je les échange ".
adjacent-inputs
. adjacent-inputs
dans chaque itération.tri par insertion:
1.L'échange de tri par insertion n'est pas requis.
2.la complexité temporelle du type d'insertion est Ω (n) pour le meilleur des cas et O (n ^ 2) dans le pire des cas.
3. moins complexe par rapport au type à bulle.
4. exemple: insérez des livres dans la bibliothèque, organisez des cartes.
tri à bulle: 1. Échange requis dans le tri à bulle.
2.La complexité temporelle du type de bulle est Ω (n) pour le meilleur des cas et O (n ^ 2) dans le pire des cas.
3.plus complexe par rapport au tri par insertion.