Qu'est-ce que la stabilité dans les algorithmes de tri et pourquoi est-ce important?

292

Je suis très curieux, pourquoi la stabilité est ou n'est pas importante dans les algorithmes de tri?

Dark Vador
la source
2
À des fins de parallélisation? Par exemple: le tri par fusion est stable et peut être bien parallélisé, tout comme le tri rapide.
DarthVader
13
Classic QuickSort est instable
Konstantin Spirin
9
stable sort algo -IBM (Insertion, Bubble, Merge)
roottraveller
Une note pour ceux qui pourraient mal comprendre le concept comme moi: l'ordre des éléments égaux est garanti d'être préservé. signifie: si les éléments en tri stable sont considérés comme égaux, alors ils suivraient l'ordre précédent. Ce n'est pas ce que je pensais: si les éléments dans l'ordre précédent sont considérés comme égaux, alors dans le tri stable à venir, ils suivraient l'ordre précédent. Bien que vous puissiez trouver cette dernière compréhension est également logique dans de nombreux cas.
Rick

Réponses:

371

Un algorithme de tri est dit stable si deux objets avec des clés égales apparaissent dans le même ordre en sortie triée comme ils apparaissent dans le tableau d'entrée à trier. Certains algorithmes de tri sont stables par nature comme le tri par insertion, le tri par fusion, le tri par bulles, etc. Et certains algorithmes de tri ne le sont pas, comme le tri par segments, le tri rapide, etc.

Contexte : un algorithme de tri "stable" conserve les éléments avec la même clé de tri dans l'ordre. Supposons que nous ayons une liste de mots de 5 lettres:

peach
straw
apple
spork

Si nous trions la liste en fonction de la première lettre de chaque mot, un tri stable produirait:

apple
peach
straw
spork

Dans un algorithme de tri instable , strawou sporkpeuvent être échangés, mais dans un algorithme stable, ils restent dans les mêmes positions relatives (c'est-à-dire, puisqu'apparaît strawavant sporkdans l'entrée, il apparaît également avant sporkdans la sortie).

On pourrait trier la liste des mots en utilisant cet algorithme: tri stable par colonne 5, puis 4, puis 3, puis 2, puis 1. Au final, il sera correctement trié. Convainquez-vous de cela. (à propos, cet algorithme est appelé tri radix)

Maintenant, pour répondre à votre question, supposons que nous ayons une liste de prénoms et de noms. On nous demande de trier "par nom, puis par prénom". Nous pourrions d'abord trier (stable ou instable) par le prénom, puis trier par le nom de famille. Après ces tris, la liste est principalement triée par nom de famille. Cependant, lorsque les noms de famille sont identiques, les prénoms sont triés.

Vous ne pouvez pas empiler des tris instables de la même manière.

Joey Adams
la source
Alors, comment appelleriez-vous le tri pour faire les mots dans un ordre de tri correct de la paille de sport pomme-pêche? Le tri stable nous a donné une pomme de paille peach peach, mais st devrait être après sp (alphabétiquement correct), donc le tri correct ultime devrait être paille sport apple peach
user1416486
2
@ user1416486: nous trions uniquement par la première lettre. Avec cette hypothèse, strawet sporkcomparer égal. Le tri stable préservera l'ordre de saisie, tandis que le tri instable ne garantit pas cela. "Correct" dépend de l'application. La fonction de tri dans la plupart des langages de programmation permet à l'utilisateur de fournir une fonction de commande personnalisée. Si la fonction de l'utilisateur traite différents éléments comme égaux (par exemple, même prénom, nom de famille différent), il est utile de savoir si l'ordre d'origine sera conservé. Voir les fonctions de tri de tableaux d'OCaml pour un exemple réel.
Joey Adams
3
Je ne comprends pas la ligne ..même clé de tri ? Qu'entendez-vous par clé ici? Veuillez expliquer la déclaration ..même clé de tri
saplingPro
2
@saplingPro: par "clé de tri", je veux dire la chose par laquelle vous triez les éléments. Ainsi, lors du tri par première lettre, puis pour chaque article, sa "clé de tri" est sa première lettre.
Joey Adams du
12
Exemple - Supposons que vous ayez une liste avec chaque élément contenant des informations sur la destination du vol et l'heure de départ. Vous triez d'abord la liste en fonction du temps. Nous le trions ensuite en fonction de la destination. Si le deuxième type est stable, nous avons maintenant tous les vols vers la même destination ensemble et dans l'ordre croissant des heures de départ. Si ce n'était pas stable, ils ne seraient pas en ordre croissant de temps.
roottraveller
55

Un algorithme de tri stable est celui qui trie les éléments identiques dans le même ordre qu'ils apparaissent dans l'entrée, tandis que le tri instable peut ne pas satisfaire le cas. - Je remercie mon professeur d'algorithme Didem Gozupek d'avoir fourni un aperçu des algorithmes .

Algorithmes de tri stables:

  • Tri par insertion
  • Tri par fusion
  • Tri des bulles
  • Tim Sort
  • Tri par comptage
  • Tri par bloc
  • Quadsort
  • Tri de bibliothèque
  • Mélangeur à cocktail Sort
  • Tri des gnomes
  • Tri pair-impair

Algorithmes de tri instables:

  • Tri par tas
  • Tri de sélection
  • Tri des coques
  • Tri rapide
  • Introsort (soumis à Quicksort)
  • Tri des arbres
  • Tri par cycle
  • Smoothsort
  • Tri par tournoi (soumis à Hesapsort)

entrez la description de l'image ici

snr
la source
2
Vos valeurs ne sont pas égales. Vous comparez 9,7 et 9,8 mais selon le contrôle de stabilité, vous avez besoin des mêmes valeurs que 9,7 ou 9,8. Et que les mêmes valeurs doivent être ordonnées dans les mêmes dans des algorithmes stables.
erhun
1
Non, pour vérifier la stabilité, vos valeurs doivent être identiques. Je veux dire que vous utilisez deux 9,7 et que vous les nommez au nœud A et au nœud B. Si chaque ordre d'opération de tri est comme A, B (au lieu d'être égal) comprenez que l'algorithme de tri est stable (comme le tri par fusion). Si l'ordre A, B change lorsque vous les triez plusieurs fois (1. triez A, B puis B, A à nouveau A, B, etc.), comprenez que l'algorithme de tri est instable (comme le tri rapide) @snr
erhun
@snr [9, 6] n'est pas présent dans le tableau d'entrée. Je pense que vous vouliez dire [9, 8] dans la dernière bande de tableau.
Usman
4
@erhun Je crois qu'il trie uniquement par le premier nombre (celui avant la virgule) et utilise le deuxième nombre comme référence pour vous de voir que le premier 9 est différent du deuxième 9.
Tiago
20

La stabilité du tri signifie que les enregistrements avec la même clé conservent leur ordre relatif avant et après le tri.

La stabilité est donc importante si et seulement si le problème que vous résolvez nécessite le maintien de cet ordre relatif.

Si vous n'avez pas besoin de stabilité, vous pouvez utiliser un algorithme rapide de mémoire en mémoire à partir d'une bibliothèque, comme heapsort ou quicksort, et l'oublier.

Si vous avez besoin de stabilité, c'est plus compliqué. Les algorithmes stables ont une utilisation du processeur Big-O et / ou de la mémoire plus élevée que les algorithmes instables. Donc, lorsque vous avez un grand ensemble de données, vous devez choisir entre battre le CPU ou la mémoire. Si vous êtes limité à la fois par le processeur et la mémoire, vous avez un problème. Un bon algorithme stable de compromis est un tri d'arbre binaire; l' article de Wikipedia a une implémentation pathétiquement facile C ++ basé sur la STL.

Vous pouvez transformer un algorithme instable en un algorithme stable en ajoutant le numéro d'enregistrement d'origine comme clé de dernière place pour chaque enregistrement.

Bob Murphy
la source
1
Les algorithmes stables comme Merge Sort ont la même complexité O (NlogN) que Quicksort; le multiplicateur constant de l'effort est cependant plus important.
Jonathan Leffler
Oui, et l'utilisation de la mémoire sur Merge Sort est O (N), tandis que sur Quicksort c'est O (log N). La raison pour laquelle j'ai mentionné Quicksort est que qsort () est une routine de bibliothèque standard C, donc il est vraiment disponible.
Bob Murphy
1
Meilleure réponse globale à mon humble avis. la technique multi-clés mentionnée dans d'autres est intéressante mais surfaite; il est simple à appliquer, mais a tendance à être beaucoup plus lent que les alternatives évidentes (utilisez simplement un tri avec une comparaison multi-clés; ou triez par la première clé puis identifiez et triez toutes les sous-listes avec des doublons). Le fait qu'un tri stable produise un résultat prévisible peut être important dans certaines applications. En particulier, si vous avez deux listes d'entrées A, B qui sont identiques sauf que la liste B a une entrée supplémentaire, les sorties pour un tri stable seront identiques sauf que B a cette même entrée supplémentaire. Et +1 pour le dernier pgph.
greggo
16

Cela dépend de ce que vous faites.

Imaginez que vous avez des enregistrements de personnes avec un champ de prénom et un nom de famille. Vous triez d'abord la liste par prénom. Si vous triez ensuite la liste avec un algorithme stable par nom de famille, vous aurez une liste triée par prénom ET par nom de famille.

svens
la source
4
Je pense que vous voulez dire "nom de famille ET prénom". Le nom de famille est généralement le nom de famille.
Bacon Bits
14

Il y a plusieurs raisons pour lesquelles la stabilité peut être importante. La première est que, si deux enregistrements n'ont pas besoin d'être échangés en les échangeant, vous pouvez provoquer une mise à jour de la mémoire, une page est marquée comme sale et doit être réécrite sur le disque (ou un autre support lent).

Clinton Pierce
la source
Qu'est-ce que l'échange d'enregistrements a à voir avec la stabilité?
user1683793
4

Un algorithme de tri est dit stable si deux objets avec des clés égales apparaissent dans le même ordre dans la sortie triée comme ils apparaissent dans le tableau d'entrée non trié. Certains algorithmes de tri sont stables par nature comme le tri par insertion, le tri par fusion, le tri par bulles, etc. Et certains algorithmes de tri ne le sont pas, comme le tri par segments, le tri rapide, etc.

Cependant, tout algo de tri donné qui n'est pas stable peut être modifié pour être stable. Il peut y avoir des moyens spécifiques de tri pour le rendre stable, mais en général, tout algorithme de tri basé sur la comparaison qui n'est pas stable par nature peut être modifié pour être stable en modifiant l'opération de comparaison de clés de sorte que la comparaison de deux clés considère la position comme un facteur pour les objets avec des clés égales.

Références: http://www.math.uic.edu/~leon/cs-mcs401-s08/handouts/stability.pdf http://en.wikipedia.org/wiki/Sorting_algorithm#Stability

roottraveller
la source
3

Je sais qu'il y a beaucoup de réponses à cela, mais pour moi, cette réponse , par Robert Harvey , le résume beaucoup plus clairement:

Un tri stable est celui qui préserve l'ordre d'origine de l'ensemble d'entrée, où l'algorithme [unstable] ne fait pas de distinction entre deux ou plusieurs éléments.

La source

John R Perry
la source
1

Si vous supposez que ce que vous triez ne sont que des nombres et que seules leurs valeurs les identifient / les distinguent (par exemple, les éléments de même valeur sont identiques), alors le problème de stabilité du tri n'a pas de sens.

Cependant, les objets avec la même priorité dans le tri peuvent être distincts, et parfois leur ordre relatif est une information significative. Dans ce cas, le tri instable génère des problèmes.

Par exemple, vous avez une liste de données qui contient le coût en temps [T] de tous les joueurs pour nettoyer un labyrinthe avec le niveau [L] dans un jeu. Supposons que nous devons classer les joueurs selon la vitesse à laquelle ils nettoient le labyrinthe. Cependant, une règle supplémentaire s'applique: les joueurs qui nettoient le labyrinthe avec un niveau supérieur ont toujours un rang plus élevé, peu importe la durée du coût.

Bien sûr, vous pouvez essayer de mapper la valeur appariée [T, L] à un nombre réel [R] avec un algorithme qui suit les règles, puis classer tous les joueurs avec la valeur [R].

Cependant, si un tri stable est possible, vous pouvez simplement trier la liste entière par [T] (joueurs plus rapides en premier) puis par [L]. Dans ce cas, l'ordre relatif des joueurs (par coût en temps) ne sera pas modifié après les avoir regroupés par niveau de labyrinthe qu'ils ont nettoyé.

PS: bien sûr, l'approche de trier deux fois n'est pas la meilleure solution au problème particulier mais pour expliquer la question de l'affiche, cela devrait suffire.

M Ciel
la source
0

Le tri stable retournera toujours la même solution (permutation) sur la même entrée.

Par exemple, [2,1,2] sera trié en utilisant le tri stable comme permutation [2,1,3] (d'abord l'index 2, puis l'index 1 puis l'index 3 dans la sortie triée) Cela signifie que la sortie est toujours mélangée de la même manière. L'autre permutation non stable, mais toujours correcte est [2,3,1].

Le tri rapide n'est pas un tri stable et les différences de permutation entre les mêmes éléments dépendent de l'algorithme de sélection du pivot. Certaines implémentations prennent au hasard et cela peut faire un tri rapide produisant différentes permutations sur la même entrée en utilisant le même algorithme.

Un algorithme de tri stable est déterministe nécessaire.

Luka Rahne
la source
2
Ce n'est pas ce que signifie la stabilité. Voir en.wikipedia.org/wiki/Sorting_algorithm#Stability
Luís Oliveira
Je devrais corriger la dernière phrase que le tri non stable peut produire une solution différente même dans la même implémentation, où tout tri stable génère la même solution.
Luka Rahne
1
Pourquoi -1? Quelqu'un peut-il indiquer ce qui ne va pas ici? Ce n'est pas ce qu'est le tri stable, mais ce que le tri stable possède.
Luka Rahne
Que le tri soit déterministe ou non ne détermine pas s'il est stable. Je peux écrire un algorithme de tri déterministe non stable en définissant un comportement de départage différent (en sous-triant les parties non clés, par exemple). Le tri stable implique spécifiquement que l'ordre relatif pré-trié des éléments est préservé lorsque les liens sont triés. exemple d'une sortie d'une sorte de stable: sort([(5,3),(1,5),(3,3),(1,3)], x) => [(1,5),(1,3),(3,3),(5,3)]. Je peux faire un tri déterministe qui produit toujours (de manière déterministe): [(1,3),(1,5),(3,3),(5,3)]mais ce n'est pas un tri stable.
cowbert
@cowbert C'est plus de déclaration, sur une belle propriété que chaque tri stable a. Peu importe que l'algorithme de tri stable ou l'implémentation soit utilisé, chaque fois il y aura le même résultat. Il est plus difficile de conserver une telle propriété parmi différentes implémentations de tri non stables.
Luka Rahne
0

Quelques autres exemples de la raison de vouloir des tris stables. Les bases de données sont un exemple courant. Prenons le cas d'une base de données de transaction comprenant le nom, le prénom, la date et l'heure d'achat, le numéro d'article et le prix. Supposons que la base de données soit normalement triée par date | heure. Ensuite, une requête est effectuée pour faire une copie triée de la base de données par nom | prénom, puisqu'un tri stable préserve l'ordre d'origine, même si la comparaison de l'enquête n'implique que le nom | prénom, les transactions pour chaque nom | être dans les données | ordre de temps.

Un exemple similaire est Excel classique, qui limitait les tris à 3 colonnes à la fois. Pour trier 6 colonnes, un tri est effectué avec les 3 colonnes les moins significatives, suivi d'un tri avec les 3 colonnes les plus significatives.

Un exemple classique de tri Radix stable est un trieur de cartes, utilisé pour trier par un champ de colonnes numériques de base 10. Les cartes sont triées du chiffre le moins significatif au chiffre le plus significatif. A chaque passage, un jeu de cartes est lu et séparé en 10 cases différentes selon le chiffre de cette colonne. Ensuite, les 10 bacs de cartes sont replacés dans la trémie d'entrée dans l'ordre ("0" en premier, "9" en dernier). Ensuite, un autre passage est effectué par la colonne suivante, jusqu'à ce que toutes les colonnes soient triées. Les trieurs de cartes réels ont plus de 10 bacs car il y a 12 zones sur une carte, une colonne peut être vierge et il y a un bac mal lu. Pour trier les lettres, 2 passes par colonne sont nécessaires, 1ère passe pour le chiffre, 2ème passe pour la zone 12 11.

Plus tard (1937), il y avait des machines d'assemblage (fusion) de cartes qui pouvaient fusionner deux jeux de cartes en comparant les champs. L'entrée était deux jeux de cartes déjà triés, un jeu de cartes maître et un jeu de mise à jour. Le collateur a fusionné les deux ponts en un nouveau bac de collecte et un bac d'archivage, qui étaient éventuellement utilisés pour les doublons principaux afin que le nouveau bac principal ne dispose de cartes de mise à jour qu'en cas de doublons. C'était probablement la base de l'idée derrière le tri de fusion d'origine (ascendant).

rcgldr
la source