Ich bin völlig neu in Python und ich versuche, Quicksort darin zu implementieren. Könnte mir bitte jemand helfen, meinen Code zu vervollständigen?
Ich weiß nicht, wie ich die drei Arrays verketten und drucken soll.
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 + ...
. Oder packen Sie Listen in eine neue Liste ausmy_list = [*list1, *list2]
Antworten:
quelle
if
s in der for-Schleife mitelif
else
Schnelle Sortierung ohne zusätzlichen Speicher (vorhanden)
Verwendung:
quelle
if end is None:
wird oft überprüft, und nur einmal wird es seinTrue
. Sie sollten dies in eine Wrapper-Funktion einfügen, damit es nur einmal aufgerufen wird.array[pivot], array[begin] = array[begin], array[pivot]
sollte ersetzenbegin
mitend
.Es gibt eine andere prägnante und schöne Version
Lassen Sie mich die obigen Codes für Details erklären
Wählen Sie das erste Element des Arrays
arr[0]
als Drehpunkt[arr[0]]
qsort
die Elemente des Arrays, mit denen weniger als geschwenkt wirdList Comprehension
qsort([x for x in arr[1:] if x < arr[0]])
qsort
die Elemente des Arrays, die größer sind als Pivot mitList Comprehension
qsort([x for x in arr[1:] if x >= arr[0]])
quelle
sorted
diese eindeutig zu Bildungszwecken. Und es ist lesbar, besser lesbar als die akzeptierte Antwort.Diese Antwort ist ein In-Place-QuickSort für
Python 2.x
. Meine Antwort ist eine Interpretation der In-Place-Lösung von Rosetta Code, die auch funktioniertPython 3
:Und wenn Sie bereit sind, auf die In-Place-Eigenschaft zu verzichten, finden Sie unten eine weitere Version, die die Grundideen von Quicksort besser veranschaulicht. Abgesehen von der Lesbarkeit besteht der andere Vorteil darin, dass es stabil ist (gleiche Elemente werden in der sortierten Liste in derselben Reihenfolge angezeigt, die sie früher in der unsortierten Liste hatten). Diese Stabilitätseigenschaft gilt nicht für die oben dargestellte weniger speicherhungrige In-Place-Implementierung.
quelle
Im wirklichen Leben sollten wir immer die von Python bereitgestellte integrierte Sortierung verwenden. Das Verständnis des Quicksort- Algorithmus ist jedoch aufschlussreich.
Mein Ziel hier ist es, das Thema so aufzuschlüsseln, dass es für den Leser leicht verständlich und reproduzierbar ist, ohne auf Referenzmaterialien zurückgreifen zu müssen.
Der Quicksort-Algorithmus ist im Wesentlichen der folgende:
Wenn die Daten zufällig verteilt sind, entspricht die Auswahl des ersten Datenpunkts als Drehpunkt einer zufälligen Auswahl.
Lesbares Beispiel:
Schauen wir uns zunächst ein lesbares Beispiel an, in dem Kommentare und Variablennamen verwendet werden, um auf Zwischenwerte zu verweisen:
Um den hier gezeigten Algorithmus und Code neu zu formulieren, verschieben wir Werte über dem Drehpunkt nach rechts und Werte unter dem Drehpunkt nach links und übergeben diese Partitionen dann an dieselbe Funktion, um sie weiter zu sortieren.
Golf:
Dies kann auf 88 Zeichen gespielt werden:
Um zu sehen, wie wir dorthin gelangen, nehmen Sie zuerst unser lesbares Beispiel, entfernen Sie Kommentare und Dokumentzeichenfolgen und suchen Sie den Drehpunkt an Ort und Stelle:
Finden Sie jetzt unten und oben vor Ort:
and
Wenn wir nun wissen, dass das vorherige Element zurückgegeben wird, wenn es falsch ist, oder wenn es wahr ist, wertet es das folgende Element aus und gibt es zurück:Da Lambdas einen einzelnen Ausdruck zurückgeben und wir zu einem einzelnen Ausdruck vereinfacht haben (obwohl er unleserlicher wird), können wir jetzt ein Lambda verwenden:
Um auf unser Beispiel zu reduzieren, kürzen Sie die Funktions- und Variablennamen auf einen Buchstaben und entfernen Sie das nicht erforderliche Leerzeichen.
Beachten Sie, dass dieses Lambda, wie die meisten Code-Golfer, ein ziemlich schlechter Stil ist.
In-Place-Quicksort mithilfe des Hoare-Partitionierungsschemas
Die vorherige Implementierung erstellt viele unnötige zusätzliche Listen. Wenn wir dies vor Ort tun können, vermeiden wir Platzverschwendung.
Die folgende Implementierung verwendet das Hoare-Partitionierungsschema, über das Sie auf Wikipedia mehr lesen können (aber wir haben anscheinend bis zu 4 redundante Berechnungen pro
partition()
Aufruf entfernt, indem wir die while-Schleifensemantik anstelle von do-while verwendet und die Verengungsschritte an das Ende von verschoben haben die äußere while-Schleife.).Ich bin mir nicht sicher, ob ich es gründlich genug getestet habe:
Fazit
Dieser Algorithmus wird häufig in Informatikkursen gelehrt und in Vorstellungsgesprächen nachgefragt. Es hilft uns, über Rekursion und Teilen und Erobern nachzudenken.
Quicksort ist in Python nicht sehr praktisch, da unser integrierter Timsort- Algorithmus sehr effizient ist und wir Rekursionsgrenzen haben. Wir würden erwarten, Listen an Ort und Stelle zu sortieren
list.sort
oder neue sortierte Listen mit zu erstellensorted
- beide nehmen einkey
und einreverse
Argument an.quelle
partition
Funktion scheint nicht richtig zu funktionieren für :partition([5,4,3,2,1], 0, 4)
. Der erwartete Rückgabeindex ist 4, während er 3 zurückgibt.Es gibt bereits viele Antworten darauf, aber ich denke, dieser Ansatz ist die sauberste Implementierung:
Sie können natürlich das Speichern von allem in Variablen überspringen und diese sofort wie folgt zurückgeben:
quelle
O(N!)
? Wenn die verschachtelte Liste angenommen wird[lesser]
und[greater]
Tippfehler vorliegen, wäre es nicht ein Durchschnitt,O(3N logN)
der sich auf den erwarteten Durchschnitt reduzieren würdeO(N logN)
? Zugegeben, die 3 Listen-Comps machen unnötige Arbeit.funktionaler Ansatz:
quelle
funktionaler Programmieransatz
quelle
Einfache Implementierung durch Grokking-Algorithmen
quelle
Ich denke, dass beide Antworten hier für die bereitgestellte Liste (die die ursprüngliche Frage beantwortet) in Ordnung sind, aber brechen würden, wenn ein Array mit nicht eindeutigen Werten übergeben wird. Der Vollständigkeit halber möchte ich nur auf den kleinen Fehler in jedem einzelnen hinweisen und erklären, wie man ihn behebt.
Wenn Sie beispielsweise versuchen, das folgende Array [12,4,5,6,7,3,1,15,1] (Beachten Sie, dass 1 zweimal erscheint) mit dem Brionius- Algorithmus zu sortieren, wird irgendwann weniger Array leer sein und das gleiche Array mit einem Wertepaar (1,1), das in der nächsten Iteration nicht getrennt werden kann, und len ()> 1 ... daher erhalten Sie eine Endlosschleife
Sie können das Problem beheben, indem Sie entweder ein Array zurückgeben, wenn weniger leer ist, oder besser, indem Sie nicht sort in Ihrem gleichen Array aufrufen, wie in zangw answer
Die schickere Lösung funktioniert ebenfalls nicht, aber aus einem anderen Grund fehlt die return- Klausel in der Rekursionszeile, die irgendwann dazu führt, dass None zurückgegeben wird und versucht wird, sie an eine Liste anzuhängen.
Um dies zu beheben, fügen Sie dieser Zeile einfach eine Rückkehr hinzu
quelle
Dies ist eine Version des Quicksort mit Hoare-Partitionsschema und mit weniger Swaps und lokalen Variablen
quelle
Partition - Teilen Sie ein Array durch einen Drehpunkt, bei dem sich kleinere Elemente nach links und größere Elemente nach rechts bewegen oder umgekehrt. Ein Pivot kann ein zufälliges Element aus einem Array sein. Um diesen Algorithmus zu erstellen, müssen wir wissen, was der Anfangs- und Endindex eines Arrays ist und wo sich ein Pivot befindet. Dann setzen Sie zwei Hilfszeiger L, R.
Wir haben also einen Array-Benutzer [..., begin, ..., end, ...]
Die Startposition der L- und R-Zeiger
[..., begin, next, ..., end, ...]
R L.
während L <Ende
1. Wenn ein Benutzer [Pivot]> Benutzer [L], dann R um eins verschieben und Benutzer [R] mit Benutzer [L] tauschen.
2. L um eins verschieben
Nach dem Austausch von Benutzer [R] mit Benutzer [Pivot]
Schnelle Sortierung - Verwenden Sie den Partitionsalgorithmus, bis jeder nächste Teil der Teilung durch einen Pivot einen Anfangsindex aufweist, der größer oder gleich dem Endindex ist.
quelle
Oder wenn Sie einen Einzeiler bevorzugen, der auch das Python-Äquivalent von C / C ++ - Varags, Lambda-Ausdrücken und if-Ausdrücken veranschaulicht:
quelle
quelle
Ich weiß, dass viele Leute diese Frage richtig beantwortet haben und ich habe es genossen, sie zu lesen. Meine Antwort ist fast die gleiche wie die von zangw, aber ich denke, die vorherigen Mitwirkenden haben nicht gut visuell erklärt, wie die Dinge tatsächlich funktionieren. Hier ist mein Versuch, anderen zu helfen, die diese Frage / Antwort in Zukunft zu einem Thema besuchen könnten einfache Lösung für die QuickSort-Implementierung.
Wie funktioniert es ?
Hier ist ein Beispiel zusammen mit Visual dazu ... (Pivot) 9,11,2,0
Durchschnitt: n log von n
schlimmster Fall: n ^ 2
Der Code:
items = [9,11,2,0] print (Quicksort (Artikel))
quelle
quelle
quelle
Eine "echte" In-Place-Implementierung [Algorithmen 8.9, 8.11 aus dem Algorithm Design and Applications Book von Michael T. Goodrich und Roberto Tamassia]:
quelle
Der Algorithmus besteht aus 4 einfachen Schritten:
Code für den Algorithmus in Python:
Fahren Sie mit diesem Algorithmus rekursiv mit dem linken und rechten Teil fort.
quelle
Eine weitere QuickSort-Implementierung:
quelle
Für Version Python 3.x : Ein Funktionsmodul
operator
, das hauptsächlich zur Verbesserung der Lesbarkeit verwendet wird.und wird getestet als
quelle
… complete my code?
. Die Verwendunglambda
zum Definierensublist()
ist nicht unbedingt erforderlich.sublist
auch nur mit definiert werdenfilter
? Ist das überhaupt möglich?def
- haben Sie noch nicht angefangen zu basteln, da ich herausfinden möchte , ob es eine effizientere Möglichkeit gibt, die Elemente einer iterierbaren Datei auf separate Listen zu verteilen (oder alternativ eine Liste mit einer). Kategorie "nach dem anderen).)Hier ist eine einfache Implementierung: -
quelle
Der Algorithmus enthält zwei Grenzen, von denen eine Elemente kleiner als der Drehpunkt (verfolgt durch den Index "j") und die andere Elemente größer als der Drehpunkt (verfolgt durch den Index "i") hat.
In jeder Iteration wird ein neues Element durch Inkrementieren von j verarbeitet.
Invariante: -
Wenn die Invariante verletzt wird, werden das i-te und das j-te Element vertauscht und i wird inkrementiert.
Nachdem alle Elemente verarbeitet wurden und alles, nachdem der Pivot partitioniert wurde, wird das Pivot-Element gegen das letzte kleinere Element ausgetauscht.
Das Pivot-Element befindet sich nun an der richtigen Stelle in der Sequenz. Die Elemente davor sind kleiner als sie und die Elemente danach sind größer als sie und sie sind unsortiert.
Pivot auswählen
Ein "guter" Pivot führt zu zwei Teilsequenzen von ungefähr derselben Größe. Deterministisch kann ein Pivot-Element entweder auf naive Weise oder durch Berechnung des Medians der Sequenz ausgewählt werden.
Eine naive Implementierung der Auswahl eines Pivots ist das erste oder letzte Element. Die Laufzeit im ungünstigsten Fall ist in diesem Fall, wenn die Eingabesequenz bereits sortiert oder umgekehrt sortiert ist, da eine der Teilsequenzen leer ist und nur ein Element pro rekursivem Aufruf entfernt wird.
Eine perfekt ausbalancierte Aufteilung wird erreicht, wenn der Drehpunkt das Medianelement der Sequenz ist. Es gibt eine gleiche Anzahl von Elementen, die größer als es und kleiner als es sind. Dieser Ansatz garantiert eine bessere Gesamtlaufzeit, ist jedoch viel zeitaufwändiger.
Eine nicht deterministische / zufällige Art der Auswahl des Drehpunkts wäre die gleichmäßige zufällige Auswahl eines Elements. Dies ist ein einfacher und leichter Ansatz, der das Worst-Case-Szenario minimiert und auch zu einer grob ausgewogenen Aufteilung führt. Dies wird auch ein Gleichgewicht zwischen dem naiven Ansatz und dem mittleren Ansatz bei der Auswahl des Pivots herstellen.
quelle
Ich füge den Code unten hinzu! Diese Quicksortierung ist aufgrund der Position des Pivot-Werts ein großartiges Lernwerkzeug . Da es sich an einem konstanten Ort befindet, können Sie es mehrmals durchlaufen und sich ein Bild davon machen, wie alles funktioniert. In der Praxis ist es am besten, den Pivot zufällig zu sortieren, um eine O (N ^ 2) -Laufzeit zu vermeiden.
quelle
quelle
Vollständiges Beispiel mit gedruckten Variablen im Partitionsschritt:
quelle
quelle
Dieser Algorithmus verwendet keine rekursiven Funktionen.
Sei
N
eine beliebige Liste von Zahlen mitlen(N) > 0
. SetK = [N]
und das folgende Programm ausführen.Hinweis: Dies ist ein stabiler Sortieralgorithmus.
quelle
Wahrscheinlich nur eine Präferenzsache, aber ich möchte die Validierung an die Spitze meiner Funktionen setzen.
quelle
Meine Antwort ist der großen von @alisianoi sehr ähnlich. Ich glaube jedoch, dass sein Code eine leichte Ineffizienz aufweist (siehe meinen Kommentar), den ich entfernt habe. Darüber hinaus habe ich weitere Erklärungen hinzugefügt und war etwas spezifischer in Bezug auf das Problem doppelter (Pivot-) Werte.
quelle