Quicksort: Die Wahl der Dreh

stimmen
94

Wenn Quicksort Umsetzung eines der Dinge, die Sie tun müssen, ist eine Pivot zu wählen. Aber wenn ich an Pseudo-Code so aussehen wie unten, ist es nicht klar, wie ich die Pivot wählen soll. Das erste Element der Liste? Etwas anderes?

 function quicksort(array)
     var list less, greater
     if length(array) ≤ 1  
         return array  
     select and remove a pivot value pivot from array
     for each x in array
         if x ≤ pivot then append x to less
         else append x to greater
     return concatenate(quicksort(less), pivot, quicksort(greater))

Kann mir jemand helfen, das Konzept der Wahl eines Dreh zu erfassen und ob verschiedene Szenarien erfordern unterschiedliche Strategien.

Veröffentlicht am 02/10/2008 um 20:37
quelle vom benutzer
In anderen Sprachen...                            


13 antworten

stimmen
72

Eine zufällige Pivot - Wahl die Möglichkeit minimiert , dass Sie Worst-Case - O begegnen (n 2 ) Leistung (immer die Wahl zuerst oder zuletzt für fast sortierten oder nahezu Reverse-sortierten Daten Worst-Case - Leistung verursachen würde). Das mittlere Element der Wahl würde auch in der Mehrzahl der Fälle akzeptabel sein.

Auch, wenn Sie diese selbst implementieren, gibt es Versionen des Algorithmus, der an Ort und Stelle arbeiten (dh ohne zwei neue Listen zu erstellen und dann verketten sie).

Beantwortet am 02/10/2008 um 20:41
quelle vom benutzer

stimmen
47

Es hängt von Ihren Anforderungen. eine Pivot zufällig Wahl macht es schwieriger, einen Datensatz zu erzeugen, die O (N ^ 2) Leistung erzeugt. 'Median-of-three' (erster, letzter, Mitte) ist auch ein Weg, um Probleme zu vermeiden. Hüten Sie sich vor der relativen Performance von Vergleichen, obwohl; wenn Ihre Vergleiche teuer sind, dann tut Mo3 mehr Vergleiche als Auswahl (einen einzelnen Wert Pivot) nach dem Zufallsprinzip. Datenbankeinträge können teuer vergleichen sein.


Update: Ziehen Kommentare in Antwort.

mdkess behauptet:

‚Median von 3‘ ist nicht erst letzte Mitte. Wählen Sie drei zufällige Indizes und nehmen Sie den mittleren Wert dieser. Der springende Punkt ist, um sicherzustellen, dass Ihre Wahl schwenkt nicht deterministisch ist - wenn es ist, kann schlimmsten Fall Daten ganz leicht werden, erzeugt.

Worauf ich antwortete:

  • Analyse von Hoares Suche - Algorithmus mit Median-Of-Three - Partition (1997) von P Kirschenhofer, H Prodinger, unterstützt C Martínez Ihre Behauptung (die Median-of-three "ist drei zufällige Elemente).

  • Es gibt einen Artikel zu beschrieben portal.acm.org , die im Begriff ist , 'The Worst Case Permutation für Median-of-Three Quicksort' von Hannu Erkiö, veröffentlicht in The Computer Journal, Vol 27, No 3, 1984 [Update 2012-02- 26: Haben Sie den Text für den Artikel . Abschnitt 2 ‚Der Algorithmus‘ beginnt: " Durch die Verwendung der Median der ersten, mittleren und letzten Elemente von A [L: R], effiziente Trennwände in Teilen ziemlich gleicher Größe kann in den meisten praktischen Situationen erreicht werden. "So ist es der Erörterung der ersten Mittel letzten Mo3 Ansatz.]

  • Ein weiterer kurzer Artikel, der interessant ist , ist durch MD McIlroy, „A Killer - Widersacher für Quicksort“ , veröffentlicht in der Software-Praxis und Erfahrung, Vol. 29 (0), 1-4 (0 1999). Es wird erläutert , wie fast jede Quicksort machen quadratisch verhalten.

  • AT & T Bell Labs Tech Journal, Oktober 1984 „Theorie und Praxis in der Konstruktion eines Arbeits Sortieren Routine“ , sagt „Hoare vorgeschlagene Partitionierung um den Median von mehreren zufällig ausgewählten Linien. Sedgewick [...] empfahl die Wahl der Median der ersten [. ..] letzte [...] und Mitte“. Dies zeigt , dass beide Techniken für ‚Median-of-drei‘ sind in der Literatur bekannt. (Update 2014.11.23: Der Artikel erscheint in verfügbar sein IEEE Xplore oder von Wiley - wenn Sie Mitgliedschaft haben oder bereit sind , eine Gebühr zu zahlen.)

  • ‚Eine Sortierfunktion Engineering‘ von JL Bentley und MD McIlroy, veröffentlicht in Software Praxis und Erfahrung, Band 23 (11), November 1993 geht in eine ausführliche Diskussion über die Fragen, und sie wählten eine adaptive Partitionierung Algorithmus basiert teilweise auf der Größe des Datensatzes. Es gibt viele Diskussionen von Kompromissen für verschiedene Ansätze.

  • Eine Google-Suche nach ‚Median-of-three‘ funktioniert recht gut für die weitere Verfolgung.

Danke für die Information; Ich hatte nur den deterministischen ‚Median-of-three‘ angetroffen vor.

Beantwortet am 02/10/2008 um 20:42
quelle vom benutzer

stimmen
1

Wenn Sie eine zufällige zugängliche Sammlung sind Sortierung (wie ein Array), ist es allgemein üblich, am besten das physische mittlere Element auszuwählen. Damit, wenn das Array ist alles fertig sortiert (oder fast sortiert) werden die beiden Partitionen nah an sogar, und Sie werden die beste Geschwindigkeit.

Wenn Sie etwas mit nur linearem Zugriff sind Sortierung (wie eine verknüpfte Liste), dann ist es am besten auf das erste Element zu wählen, weil es der schnellste Punkt ist zu erreichen. Hier aber, wenn die Liste bereits sortiert ist, sind Sie verschraubt - eine Partition immer null sein wird, und die andere alles haben, die schlimmste Zeit produzieren.

Doch für eine verknüpfte Liste, nichts außer dem ersten Kommissionierung, wird nur noch schlimmer machen. Es nehmen Sie den mittleren Punkt in einer aufgelistet Liste, würden Sie durch sie auf jeder Partition Schritt für Schritt müssen - das Hinzufügen eines O (N / 2) Operation, die log N mal die insgesamt O (1,5 N · log N) durchgeführt wird und das ist, wenn wir wissen, wie lange die Liste ist, bevor wir beginnen - in der Regel haben wir nicht so würden wir müssen den ganzen Weg Schritt für Schritt durch, sie zu zählen, dann wird der Schritt auf halbem Weg durch die Mitte zu finden, dann wird der Schritt durch eine O (2,5 N · log N): zum dritten Mal die tatsächliche Partition zu tun

Beantwortet am 02/10/2008 um 20:42
quelle vom benutzer

stimmen
1

Es ist völlig davon abhängig, wie Ihre Daten sortiert werden zu beginnen. Wenn Sie denken, wird es pseudo-zufällig dann Ihre beste Wette ist, um entweder eine zufällige Auswahl zu wählen oder die Mitte wählen.

Beantwortet am 02/10/2008 um 20:46
quelle vom benutzer

stimmen
16

Heh, lehrte ich nur diese Klasse.

Es gibt mehrere Optionen.
Ganz einfach: Wählen Sie das erste oder das letzte Element des Bereichs. (schlecht in teilweise sortierten Eingang) Besser: Wählen Sie das Element in der Mitte des Bereichs. (besser auf teilweise sortierten Eingang)

Jedoch kann jedes beliebiges Element Kommissionierung läuft Gefahr von schlecht Partitionieren des Array der Größe n in zwei Reihen von der Größe 1 und n-1. Wenn man das oft genug tun, läuft Ihr quicksort das Risiko O des Werdens (n ​​^ 2).

Eine Verbesserung, die ich gesehen habe, ist Median Pick (erste, letzte, Mitte); Im schlimmsten Fall kann es zu O geht noch (n ^ 2), aber probabilistically, ist dies ein seltener Fall.

Für die meisten Daten, Kommissionierung das erste oder letzte ist ausreichend. Aber, wenn Sie feststellen, dass Sie in der schlimmsten Fall laufen oft (teilweise sortierte Eingang), die erste Möglichkeit wäre, den zentralen Wert wählen (die eine statistisch gute Dreh für teilweise sortierten Daten ist).

Wenn Sie immer noch Probleme laufen, dann die mittlere Strecke gehen.

Beantwortet am 02/10/2008 um 20:46
quelle vom benutzer

stimmen
8

Nie einen festen Dreh wählen - diese angegriffen werden können Ihren Algorithmus schlimmsten Fall O (n ^ 2) Laufzeit zu nutzen, die nur Ärger bitten. Quicksort schlimmste Fall tritt auf, wenn die Laufzeit Ergebnisse Partitionierung in einer Reihe von 1-Elemente, und einer Anordnung von n-1 Elemente. Angenommen, Sie das erste Element als Partition auswählen. Wenn jemand ein Array an Ihren Algorithmus-Feeds, die in absteigender Reihenfolge ist, wird Ihre erste Dreh die größte sein, so alles in der Reihe wird auf der linken Seite verschieben. Dann, wenn Sie Rekursion, wird das erste Element die größte wieder sein, so einmal mehr Sie alles links von mir ausdrückte, und so weiter.

Eine bessere Technik ist das Median-of-3-Verfahren, in dem Sie drei Elemente zufällig wählen, und in die Mitte wählen. Sie wissen, dass das Element, das Sie nicht das der erste oder der letzte, sondern auch durch den zentralen Grenzwertsatz wählen sein, die Verteilung des mittleren Element wird normal sein, was bedeutet, dass Sie in Richtung der Mitte neigen wird (und damit , n lg n-Zeit).

Wenn Sie unbedingt wollen O (NLGN) Laufzeit für den Algorithmus zu gewährleisten, die Spalten-of-5-Methode des Median eines Arrays für die Suche läuft in O (n) Zeit, was bedeutet, dass die Rekursionsgleichung für quicksort im schlimmsten Fall wird werden T (n) = O (n) (den Median finden) + O (n) (Partition) + 2T (n / 2) (recurse links und rechts.) Nach dem Master-Theorem, das ist O (n lg n) . Allerdings wird der konstante Faktor sehr groß sein, und wenn schlimmste Fall Leistung das primäre Anliegen ist, verwenden Sie eine Mergesort statt, die nur ein wenig langsamer als Quicksort im Durchschnitt ist und garantiert O (NLGN) Zeit (und wird viel schneller als dieser lahm Median quicksort).

Erklärung des Median des Mediane Algorithm

Beantwortet am 25/10/2008 um 22:50
quelle vom benutzer

stimmen
5

Seien Sie nicht zu klug versuchen und erhalten und Schwenk Strategien kombinieren. Wenn Sie Median von 3 mit zufälliger Dreh kombiniert durch den Median des ersten, letzten und ein zufälligen Index in der Mitte sammeln, dann werden Sie noch viele der Verteilungen anfällig sein, die mittleren von drei quadratischen senden (so seine wirklich schlechter als Klarzufallsschwenk)

ZB ein Rohr Organverteilung (1,2,3 ... N / 2..3,2,1) erste und die letzte sein wird sowohl 1 als auch die Zufallsindex wird eine Zahl größer als 1 ist, wobei der Median gibt 1 ( entweder die erste oder letzte) und Sie erhalten eine extermely unausgeglichen Partitionierung.

Beantwortet am 26/10/2008 um 04:54
quelle vom benutzer

stimmen
1

Es ist einfacher, den quicksort in drei Abschnitte dies zu tun zu brechen

  1. Exchange oder Swap-Datenelement Funktion
  2. Die Partitionsfunktion
  3. Die Verarbeitung der Partitionen

Es ist nur etwas mehr als eine ineffiziente lange Funktion, ist aber viel einfacher zu verstehen.

Code folgt:

/* This selects what the data type in the array to be sorted is */

#define DATATYPE long

/* This is the swap function .. your job is to swap data in x & y .. how depends on
data type .. the example works for normal numerical data types .. like long I chose
above */

void swap (DATATYPE *x, DATATYPE *y){  
  DATATYPE Temp;

  Temp = *x;        // Hold current x value
  *x = *y;          // Transfer y to x
  *y = Temp;        // Set y to the held old x value
};


/* This is the partition code */

int partition (DATATYPE list[], int l, int h){

  int i;
  int p;          // pivot element index
  int firsthigh;  // divider position for pivot element

  // Random pivot example shown for median   p = (l+h)/2 would be used
  p = l + (short)(rand() % (int)(h - l + 1)); // Random partition point

  swap(&list[p], &list[h]);                   // Swap the values
  firsthigh = l;                                  // Hold first high value
  for (i = l; i < h; i++)
    if(list[i] < list[h]) {                 // Value at i is less than h
      swap(&list[i], &list[firsthigh]);   // So swap the value
      firsthigh++;                        // Incement first high
    }
  swap(&list[h], &list[firsthigh]);           // Swap h and first high values
  return(firsthigh);                          // Return first high
};



/* Finally the body sort */

void quicksort(DATATYPE list[], int l, int h){

  int p;                                      // index of partition 
  if ((h - l) > 0) {
    p = partition(list, l, h);              // Partition list 
    quicksort(list, l, p - 1);        // Sort lower partion
    quicksort(list, p + 1, h);              // Sort upper partition
  };
};
Beantwortet am 10/03/2011 um 03:19
quelle vom benutzer

stimmen
0

Im Idealfall sollte der Schwenk der mittlere Wert in der gesamten Array sein. Dadurch werden die Chancen auf Worst-Case-Leistung reduzieren.

Beantwortet am 17/04/2013 um 15:57
quelle vom benutzer

stimmen
-1

In einer wirklich optimierte Implementierung sollte das Verfahren für die Wahl Pivot auf der Array-Größe abhängen - für ein großes Array, es lohnt sich mehr Zeit zu verbringen, ein gutes Dreh wählen. Ohne eine vollständige Analyse zu tun, würde ich „Mitte O (log (n)) Elemente“ erraten ist ein guter Anfang, und dies hat den zusätzlichen Bonus von nicht erfordert keine zusätzlichen Speicher: Die Verwendung Tail-Call auf die größere Partition und IN- Ort Partitionierungs, verwenden wir die gleiche O (log (n)) zusätzlichen Speicher an fast jeder Stufe des Algorithmus.

Beantwortet am 08/10/2013 um 20:50
quelle vom benutzer

stimmen
0

Kurze Art der Komplexität variiert stark mit der Auswahl des Drehwertes. zum Beispiel, wenn Sie immer Komplexität erstes Element, das als Drehpunkt, Algorithmus wird als worst als O (n ^ 2) wählen. hier ist ein intelligentes Verfahren zur Auswahl Schwenk Element- 1. Das erste, mid, letzte Element des Arrays auszuwählen. 2. Vergleichen Sie diese drei Zahlen und die Zahl finden, die größer als eins ist und kleiner als andere, dh Median. 3. machen dieses Element als Pivotelement.

Durch dieses Verfahren der Auswahl der Dreh teilt das Array in nahezu zwei Halb und damit die Komplexität reduziert sich auf O (nlog (n)).

Beantwortet am 05/12/2013 um 06:05
quelle vom benutzer

stimmen
0

Im Durchschnitt Median von 3 ist für kleine n gut. Median von 5 ist ein wenig besser für größere n. Die ninther, die der „Median von drei Mediane von drei“ ist noch besser für sehr große n.

Je höher gehen Sie mit Abtasten desto besser werden Sie, wenn n zunimmt, aber die Verbesserung dramatisch verlangsamt, wie Sie die Proben erhöhen. Und Sie entstehen den Aufwand für das Abtasten und Sortieren von Proben.

Beantwortet am 19/10/2016 um 10:04
quelle vom benutzer

stimmen
0

Ich empfehle den mittleren Index verwenden, da es leicht berechnet werden kann.

Sie können es berechnen durch Runden (array.length / 2).

Beantwortet am 09/08/2017 um 01:29
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more