Je suis totalement nouveau sur python et j'essaye d'y implémenter quicksort. Quelqu'un pourrait-il m'aider à compléter mon code?
Je ne sais pas comment concaténer les trois tableaux et les imprimer.
def sort(array=[12,4,5,6,7,3,1,15]):
less = []
equal = []
greater = []
if len(array) > 1:
pivot = array[0]
for x in array:
if x < pivot:
less.append(x)
if x == pivot:
equal.append(x)
if x > pivot:
greater.append(x)
sort(less)
sort(pivot)
sort(greater)
my_list = list1 + list2 + ...
. Ou décompressez les listes dans une nouvelle listemy_list = [*list1, *list2]
Réponses:
la source
if
s de la boucle for avecelif
etelse
pour éviter de faire des comparaisons inutilesTri rapide sans mémoire supplémentaire (en place)
Usage:
la source
if end is None:
va être vérifié plusieurs fois, et une seule foisTrue
. Vous devriez le mettre dans une fonction wrapper pour qu'il ne soit appelé qu'une seule fois.array[pivot], array[begin] = array[begin], array[pivot]
devrait remplacerbegin
parend
.Il existe une autre version concise et belle
Laissez-moi vous expliquer les codes ci-dessus pour plus de détails
choisissez le premier élément du tableau
arr[0]
comme pivot[arr[0]]
qsort
les éléments du tableau qui sont inférieurs à pivoter avecList Comprehension
qsort([x for x in arr[1:] if x < arr[0]])
qsort
les éléments du tableau qui sont plus grands que pivotent avecList Comprehension
qsort([x for x in arr[1:] if x >= arr[0]])
la source
sorted
, c'est clairement à des fins éducatives. Et il est lisible, plus lisible que la réponse acceptée.Cette réponse est un tri rapide sur place pour
Python 2.x
. Ma réponse est une interprétation de la solution en place de Rosetta Code qui fonctionnePython 3
aussi pour :Et si vous êtes prêt à renoncer à la propriété in-situ, voici une autre version qui illustre mieux les idées de base derrière le tri rapide. Outre la lisibilité, son autre avantage est qu'il est stable (les éléments égaux apparaissent dans la liste triée dans le même ordre qu'ils avaient dans la liste non triée). Cette propriété de stabilité ne tient pas avec l'implémentation sur place moins gourmande en mémoire présentée ci-dessus.
la source
Dans la vraie vie, nous devrions toujours utiliser le tri intégré fourni par Python. Cependant, comprendre l' algorithme de tri rapide est instructif.
Mon but ici est de décomposer le sujet de manière à ce qu'il soit facilement compris et reproductible par le lecteur sans avoir à revenir sur les matériaux de référence.
L'algorithme de tri rapide est essentiellement le suivant:
Si les données sont distribuées de manière aléatoire, la sélection du premier point de données comme pivot équivaut à une sélection aléatoire.
Exemple lisible:
Tout d'abord, regardons un exemple lisible qui utilise des commentaires et des noms de variables pour pointer vers des valeurs intermédiaires:
Pour reformuler l'algorithme et le code illustrés ici, nous déplaçons les valeurs au-dessus du pivot vers la droite et les valeurs sous le pivot vers la gauche, puis transmettons ces partitions à la même fonction pour être triées davantage.
Golfé:
Cela peut être joué à 88 caractères:
Pour voir comment nous y arrivons, prenez d'abord notre exemple lisible, supprimez les commentaires et les docstrings, et recherchez le pivot sur place:
Trouvez maintenant ci-dessous et ci-dessus, en place:
Maintenant, sachant que
and
renvoie l'élément précédent si faux, sinon s'il est vrai, il évalue et renvoie l'élément suivant, nous avons:Puisque les lambdas renvoient une seule expression, et que nous avons simplifié à une seule expression (même si elle devient de plus en plus illisible), nous pouvons maintenant utiliser un lambda:
Et pour réduire à notre exemple, raccourcissez les noms des fonctions et des variables à une lettre et éliminez les espaces qui ne sont pas nécessaires.
Notez que ce lambda, comme la plupart des jeux de code, est plutôt mauvais.
Tri rapide sur place, à l'aide du schéma de partitionnement Hoare
L'implémentation précédente crée beaucoup de listes supplémentaires inutiles. Si nous pouvons le faire sur place, nous éviterons de gaspiller de l'espace.
L'implémentation ci-dessous utilise le schéma de partitionnement Hoare, sur lequel vous pouvez en savoir plus sur wikipedia (mais nous avons apparemment supprimé jusqu'à 4 calculs redondants par
partition()
appel en utilisant la sémantique en boucle while au lieu de do-while et en déplaçant les étapes de réduction à la fin de la boucle while externe.).Je ne sais pas si je l'ai suffisamment testé:
Conclusion
Cet algorithme est fréquemment enseigné dans les cours d'informatique et demandé lors des entretiens d'embauche. Cela nous aide à penser à la récursivité et à diviser pour conquérir.
Quicksort n'est pas très pratique en Python car notre algorithme de tri temporel intégré est assez efficace et nous avons des limites de récursivité. Nous nous attendrions à trier les listes sur place avec
list.sort
ou à créer de nouvelles listes triées avecsorted
- les deux prenant un argumentkey
etreverse
.la source
partition
fonction semble pas fonctionner correctement pour:partition([5,4,3,2,1], 0, 4)
. L'indice de retour attendu est 4, alors qu'il renvoie 3.Il existe déjà de nombreuses réponses à cela, mais je pense que cette approche est la mise en œuvre la plus propre:
Vous pouvez bien sûr ignorer tout stocker dans des variables et les renvoyer immédiatement comme ceci:
la source
O(N!)
? En supposant que la liste imbriquée[lesser]
et qu'il[greater]
y ait des fautes de frappe, ne serait-ce pas une moyenneO(3N logN)
qui se réduirait à la moyenne prévueO(N logN)
? Certes, les 3 compositions de la liste font un travail inutile.Approche fonctionnelle:
la source
approche de programmation fonctionnelle
la source
Implémentation facile à partir d'algorithmes de grokking
la source
Je pense que les deux réponses ici fonctionnent bien pour la liste fournie (qui répondent à la question d'origine), mais se casseraient si un tableau contenant des valeurs non uniques est passé. Donc, pour être complet, je voudrais simplement souligner la petite erreur dans chacun et expliquer comment les corriger.
Par exemple, essayer de trier le tableau suivant [12,4,5,6,7,3,1,15,1] (notez que 1 apparaît deux fois) avec l' algorithme de Brionius .. à un moment donné, le tableau le moins vide sera et le tableau égal avec une paire de valeurs (1,1) qui ne peuvent pas être séparées dans l'itération suivante et le len ()> 1 ... donc vous vous retrouverez avec une boucle infinie
Vous pouvez le corriger en retournant un tableau si less est vide ou mieux en n'appelant pas sort dans votre tableau égal, comme dans zangw answer
La solution plus sophistiquée se brise également, mais pour une cause différente, il manque la clause de retour dans la ligne de récursivité, ce qui provoquera à un moment donné le renvoi None et une tentative de l'ajouter à une liste ...
Pour résoudre ce problème, ajoutez simplement un retour à cette ligne
la source
Ceci est une version du tri rapide utilisant le schéma de partition Hoare et avec moins de swaps et de variables locales
la source
Partition - Divisez un tableau par un pivot pour que les éléments plus petits se déplacent vers la gauche et les éléments plus grands se déplacent vers la droite ou vice versa. Un pivot peut être un élément aléatoire d'un tableau. Pour créer cet algorithme, nous devons savoir ce qu'est l'index de début et de fin d'un tableau et où se trouve un pivot. Ensuite, définissez deux pointeurs auxiliaires L, R.
Nous avons donc un utilisateur de tableau [..., begin, ..., end, ...]
La position de départ des pointeurs L et R
[..., begin, next, ..., end, ...]
R L
while L <end
1. Si un utilisateur [pivot]> user [L], déplacez R de un et permutez l'utilisateur [R] avec l'utilisateur [L]
2. déplacez L par un
Après un certain temps, permutez l'utilisateur [R] avec l'utilisateur [pivot]
Tri rapide - Utilisez l'algorithme de partition jusqu'à ce que chaque partie suivante de la division par un pivot ait un index de début supérieur ou égal à l'index de fin.
la source
Ou si vous préférez un one-liner qui illustre également l'équivalent Python des varags C / C ++, des expressions lambda et des expressions if:
la source
la source
Je sais que beaucoup de gens ont répondu correctement à cette question et j'ai aimé les lire. Ma réponse est presque la même que zangw mais je pense que les contributeurs précédents n'ont pas bien expliqué visuellement comment les choses fonctionnent réellement ... alors voici ma tentative d'aider les autres qui pourraient visiter cette question / réponses à l'avenir à propos d'un solution simple pour la mise en œuvre de tri rapide.
Comment ça marche ?
Voici un exemple avec visuel pour aller avec ... (pivot) 9,11,2,0
moyenne: n log de n
pire cas: n ^ 2
Le code:
items = [9,11,2,0] print (tri rapide (articles))
la source
la source
la source
Une implémentation «vraie» sur place [Algorithmes 8.9, 8.11 du livre de conception et d'applications d'algorithmes de Michael T. Goodrich et Roberto Tamassia]:
la source
L'algorithme comporte 4 étapes simples:
Code pour l'algorithme en python:
Continuez avec cet algorithme de manière récursive avec les parties gauche et droite.
la source
Une autre implémentation de tri rapide:
la source
Pour la version Python 3.x : un
operator
module utilisant de style fonctionnel , principalement pour améliorer la lisibilité.et est testé comme
la source
… complete my code?
. Utiliserlambda
pour définirsublist()
ne semble pas strictement nécessaire.sublist
on définir uniquement en utilisantfilter
? Est-ce que c'est possible?def
- je n'ai pas encore commencé à bricoler car j'essaie de déterminer s'il existe un moyen plus efficace de "distribuer" les éléments d'un itérable pour séparer les listes (ou, alternativement, une liste avec une " catégorie "après l'autre).)Voici une implémentation simple: -
la source
L'algorithme contient deux limites, l'une ayant des éléments inférieurs au pivot (suivi par l'index "j") et l'autre ayant des éléments supérieurs au pivot (suivi par l'index "i").
À chaque itération, un nouvel élément est traité en incrémentant j.
Invariant: -
Si l'invariant est violé, les ième et jième éléments sont permutés et i est incrémenté.
Une fois que tous les éléments ont été traités, et tout après le partitionnement du pivot, l'élément pivot est échangé avec le dernier élément plus petit que lui.
L'élément pivot sera maintenant à sa place correcte dans la séquence. Les éléments avant lui seront inférieurs à lui et ceux qui après lui seront supérieurs, et ils ne seront pas triés.
Sélection d'un pivot
Un "bon" pivot se traduira par deux sous-séquences à peu près de la même taille. De manière déterministe, un élément pivot peut être sélectionné soit de manière naïve, soit en calculant la médiane de la séquence.
Une implémentation naïve de la sélection d'un pivot sera le premier ou le dernier élément. Le pire des cas d'exécution dans ce cas sera lorsque la séquence d'entrée est déjà triée ou triée inversée, car l'une des sous-séquences sera vide, ce qui entraînera la suppression d'un seul élément par appel récursif.
Une répartition parfaitement équilibrée est obtenue lorsque le pivot est l'élément médian de la séquence. Il y a un nombre égal d'éléments supérieur à lui et inférieur à lui. Cette approche garantit une meilleure durée de fonctionnement globale, mais prend beaucoup plus de temps.
Une manière non déterministe / aléatoire de sélectionner le pivot serait de choisir un élément uniformément au hasard. Il s'agit d'une approche simple et légère qui minimisera le pire des cas et conduira également à une répartition à peu près équilibrée. Cela fournira également un équilibre entre l'approche naïve et l'approche médiane de sélection du pivot.
la source
Je joins le code ci-dessous! Ce tri rapide est un excellent outil d'apprentissage en raison de l' emplacement de la valeur pivot . Comme il est dans un endroit constant, vous pouvez le parcourir plusieurs fois et vraiment comprendre comment tout cela fonctionne. En pratique, il est préférable de randomiser le pivot pour éviter l'exécution O (N ^ 2).
la source
la source
Exemple complet avec des variables imprimées à l'étape de partition:
la source
la source
Cet algorithme n'utilise pas de fonctions récursives.
Soit
N
une liste de nombres aveclen(N) > 0
. DéfinissezK = [N]
et exécutez le programme suivant.Remarque: il s'agit d'un algorithme de tri stable .
la source
Probablement juste une chose de préférence, mais j'aime ajouter la validation en haut de mes fonctions.
la source
Ma réponse est très similaire à la grande de @alisianoi. Cependant, je pense qu'il y a une légère inefficacité dans son code (voir mon commentaire), que j'ai supprimé. De plus, j'ai ajouté plus d'explications et j'étais un peu plus précis sur le problème des valeurs en double (pivot).
la source