web-dev-qa-db-fra.com

Pire cas pour QuickSort - quand peut-il se produire?

Lors de l'analyse de QS, chacun se réfère toujours au pire des cas "presque triés". Quand un tel scénario peut-il se produire avec un apport naturel?

Le seul exemple que j'ai trouvé est la réindexation.

42
user290301

Je pense que les gens confondent Quicksort l'algorithme de tri basé sur les partitions et "qsort" les différentes implémentations de bibliothèques.

Je préfère voir Quicksort l'algorithme comme ayant un algorithme de sélection de pivot enfichable, ce qui est assez essentiel pour analyser son comportement.

Si le premier élément est toujours choisi comme pivot, alors une liste déjà triée est le pire des cas. Il y a souvent une forte probabilité que le tableau soit déjà/presque trié, donc cette implémentation est plutôt pauvre.

De même, la sélection du dernier élément comme pivot est mauvaise pour la même raison.

Certaines implémentations tentent d'éviter ce problème en choisissant l'élément central comme pivot. Cela ne fonctionnerait pas aussi mal sur des tableaux déjà/presque triés, mais on pourrait toujours construire une entrée qui exploiterait cette sélection de pivot prévisible et la ferait fonctionner en temps quadratique.

Ainsi, vous obtenez des algorithmes de sélection de pivot randomisés, mais même cela ne garantit pas O(N log N).

Ainsi, d'autres algorithmes ont été développés qui utiliseraient certaines informations de la séquence avant de choisir un pivot. Vous pouvez bien sûr scanner toute la séquence et trouver la médiane, et l'utiliser comme pivot. Cela garantit O(N log N), mais bien sûr plus lent en pratique.

Donc, certains coins sont coupés, et les gens ont conçu l'algorithme de la médiane de 3. Bien sûr, plus tard, même cela a été exploitable par le soi-disant "tueur" médian de 3.

De plus en plus de tentatives sont faites pour trouver des algorithmes de sélection de pivot plus "intelligents" qui garantissent un comportement asymptotique O(N log N) qui est encore assez rapide pour être pratique, avec un degré de succès variable.

Donc, à moins que l'on ne spécifie une implémentation particulière de Quicksort, la question de savoir quand le pire des scénarios se produit est mal définie. Si vous utilisez ce que l'on appelle l'algorithme de sélection pivotante médiane des médianes, il n'y a pas de pire scénario quadratique.

Cependant, la plupart des implémentations de bibliothèques risquent de perdre la garantie de O(N log N) pour un tri beaucoup plus rapide dans le cas moyen. Certaines des implémentations vraiment anciennes utilisent le premier élément comme pivot, qui est maintenant bien compris comme pauvre et n'est plus une pratique largement suivie.

42
polygenelubricants

Je pense que le pire des cas pour le tri rapide dépend du choix de l'élément pivot à chaque étape. Quicksort a ses pires performances, si le pivot est susceptible d'être le plus petit ou le plus grand élément de la liste (par exemple, le premier ou le dernier élément d'une liste déjà triée).

Si, par exemple vous choisissez l'élément du milieu de la liste, une liste déjà triée n'a pas le pire cas d'exécution.

Donc, si vous pensez que votre scénario est susceptible de présenter un mauvais scénario de tri rapide, vous pouvez simplement modifier votre choix d'élément pivot pour améliorer le tri rapide.

Remarque: je sais que cela ne donne pas plus d'exemples de situations réelles pour les pires cas de tri rapide. Des exemples de cela dépendent de l'implémentation avec laquelle vous travaillez.

34
Jens

La vraie question était: "Quand un tel scénario (presque trié) peut-il se produire avec un apport naturel?".

Bien que toutes les réponses portent sur "ce qui cause les performances les plus défavorables", aucune n'a couvert "ce qui cause les données qui répondent au pire scénario de performances".

Donc, pour répondre à la question réelle

  • Erreur du programmeur : En gros, vous décrochez une liste deux fois. Cela se produit généralement car une liste est triée à un endroit dans le code. Et plus tard, dans un autre morceau de code, vous savez que vous avez besoin que la liste soit triée, alors vous la triez à nouveau.

  • Utilisation de données quasi chronologiques : vous disposez de données généralement reçues par ordre chronologique, mais certains éléments sont parfois hors de position. (Envisagez un environnement multithread ajoutant des éléments horodatés à une liste. Les conditions de concurrence peuvent entraîner l'ajout d'éléments dans un ordre différent dans lequel ils ont été horodatés.) Dans cette situation, si vous avez besoin de données triées, vous devez re -Trier. Parce que l'ordre des données n'est pas garanti.

  • Ajout d'éléments à une liste : Si vous avez une liste triée et ajoutez simplement quelques éléments (c'est-à-dire sans utiliser d'insertion binaire). Vous auriez besoin de trier à nouveau une liste presque triée.

  • Données provenant d'une source externe : Si vous recevez des données d'une source externe, rien ne garantit qu'elles sont triées. Donc, vous le triez vous-même. Cependant, si la source externe est triée, vous trierez à nouveau les données.

  • Ordre naturel : Ceci est similaire aux données chronologiques. Fondamentalement, l'ordre naturel des données que vous recevez peut être trié. Considérez une compagnie d'assurance qui ajoute des immatriculations de voitures. Si l'autorité qui attribue les immatriculations de voitures le fait dans un ordre prévisible, les voitures plus récentes sont susceptibles mais pas garanties d'avoir des numéros d'immatriculation plus élevés. Comme vous n'êtes pas assuré qu'il est trié, vous devez trier à nouveau.

  • Données entrelacées : Si vous recevez des données de plusieurs sources triées avec des clés qui se chevauchent, vous pouvez obtenir des clés ressemblant à ce qui suit: 1 3 2 5 4 7 6 9 8 11 10 13 12 15 14 17 16 19 18. Même si la moitié des éléments sont hors séquence avec son voisin, la liste est "presque triée". Certes, l'utilisation de QuickSort qui pivote sur le premier élément présenterait des performances de O(n^2).

Conclusion

Donc, compte tenu de tous les scénarios ci-dessus, il est en fait assez facile d'atterrir en triant des données presque triées. Et c'est exactement pourquoi il est préférable d'éviter QuickSort qui pivote sur le premier élément. polygene a fourni --- intéressant des informations sur d'autres considérations de pivotement.

En guise de remarque: l'un des algorithmes de tri les moins performants, se débrouille plutôt bien avec les données "presque triées". Dans les données entrelacées ci-dessus, le tri à bulles ne nécessite que 9 opérations de swap. Ses performances seraient en fait O(n).

8
Disillusioned

De Quicksort

pour quicksort, le "pire des cas" correspond à déjà trié

Une liste avec tous les éléments du même numéro est déjà triée .

7
Adriaan Stander

pire cas en tri rapide:

  1. Tous les éléments du tableau sont identiques
  2. Le tableau est déjà trié dans le même ordre
  3. Le tableau est déjà trié dans l'ordre inverse.
3

Le pire des cas dépend du choix de l'élément pivot. le problème ne se produit donc que lorsque 1) Array est déjà trié dans le même ordre. 2) Le tableau est déjà trié dans l'ordre inverse. 3) Tous les éléments sont identiques (cas particulier des cas 1 et 2)

1
Ankit jain