Quicksort: választott pivot

szavazat
94

Végrehajtása során a Quicksort, az egyik dolog, amit meg kell tennie, hogy válasszon egy pivot. De ha ránézek pszeudokódját, mint például az alábbi, nem világos, hogy hogyan kell kiválasztani a pivot. Első eleme listán? Valami más?

 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))

Tud valaki segíteni fogja a koncepció kiválasztása pivot-e vagy sem a különböző forgatókönyvek hívja a különböző stratégiák.

A kérdést 02/10/2008 20:37
a forrás felhasználó
Más nyelveken...                            


13 válasz

szavazat
72

Kiválasztása egy véletlen pivot minimalizálja az esély, hogy lesz találkozás legrosszabb O (n 2 ) teljesítmény (holott ez az első vagy az utolsó okozna legrosszabb teljesítmény közel válogatni vagy közel-fordított időrendi adatok). Kiválasztása a középső elem is elfogadható a legtöbb esetben.

Továbbá, ha végrehajtja ezt magad, vannak olyan változatai az algoritmus, hogy a munka-hely (vagyis anélkül, hogy a két új listákat, majd egybetoldjuk őket).

Válaszolt 02/10/2008 20:41
a forrás felhasználó

szavazat
47

Ez attól függ, az Ön igényeinek. Kiválasztása pivot véletlenszerűen megnehezíti, hogy hozzon létre egy adathalmaz, amely generál O (N ^ 2) teljesítményét. „Medián-of-három” (első, utolsó, középső) is ily módon elkerülhető problémák. Vigyázni kell, mert a relatív teljesítményének összehasonlítását, bár; ha az összehasonlítások költséges, akkor Mo3 nem több, mint összehasonlításokat választja (egyetlen pivot érték) véletlenszerűen. Adatbázisrekordok költséges lehet összehasonlítani.


Frissítés: Húz megjegyzéseket a választ.

mdkess kijelentette:

„Median 3” nem az első az utolsó közepén. Válassza ki a három random indexek, és megteszi a középső érték e. A lényeg az, hogy megbizonyosodjon arról, hogy a választott szelvények nem determinisztikus - ha így van, legrosszabb esetben az adatok is meglehetősen könnyen keletkezik.

Erre én válaszolt:

  • Elemzés A Hoare Ide algoritmus Medián-Of-Three Partition (1997) P Kirschenhofer, H Prodinger, C Martínez támogatja az állítását (hogy 'medián-of-három' három véletlenszerű elemek).

  • Van egy cikk leírt portal.acm.org amely mintegy 'The Worst Case permutáció Medián-of-Three Quicksort' Hannu Erkiö kiadású The Computer Journal, Vol 27, No 3, 1984 [Update 2012-02- 26: Megvan a szövegben a cikket . 2. szakasz „Az algoritmus” kezdődik: " Az a medián az első, középső és utolsó elemét A [L: R], hatékony partíciót rész nagyjából egyenlő méretű lehet elérni a legtöbb gyakorlati helyzetekben. "Ezért úgy beszélünk az első közép-múlt Mo3 megközelítés.]

  • Tovább rövid cikket, hogy az az érdekes, MD McIlroy, „A gyilkos Ellenség a Quicksort” kiadású szoftver-gyakorlat és a tapasztalat, Vol. 29 (0), 1-4 (0 1999). Ez magyarázza, hogyan lehet szinte bármilyen Quicksort viselkednek négyzetesen.

  • AT & T Bell Labs Tech Journal, Oct 1984 „elmélete és gyakorlata az építése Munka Küld rutin” kimondja „Hoare javasolt felosztás A medián körüli számos véletlenszerűen kiválasztott sorokat. Sedgewick [...] ajánlott választotta a medián az első [. ..] az utolsó [...] és a középső”. Ez azt jelzi, hogy a két technikát „medián-of-három” ismert a szakirodalomban. (Frissítés 2014/11/23: A cikk úgy tűnik, hogy elérhető az IEEE Xplore vagy Wiley - ha tagsági vagy készek megfizetni a díjat.)

  • „Engineering A rendezés funkció” JL Bentley és MD McIlroy kiadású szoftver gyakorlat és a tapasztalat, Vol 23 (11), 1993 novemberében életbe lépett egy kiterjedt vita a kérdéseket, és úgy döntöttek, adaptív particionáló algoritmus alapjául részben az mérete az adathalmaz. Van sok vita kompromisszumok különböző megközelítéseket.

  • A Google kereső a „medián-of-három” elég jól működik a további nyomon követése.

Köszönöm a tájékoztatást; Én csak találkozott a determinisztikus „medián-of-három” előtt.

Válaszolt 02/10/2008 20:42
a forrás felhasználó

szavazat
1

Ha válogatás véletlenszerű megközelíthető gyűjtőhelyen (mint egy tömb), ez általában a legjobb, hogy vegye a fizikai középső elemet. Ezzel, ha a tömb minden készen áll rendezve (vagy majdnem rendezés), a két partíció közel lesz még, és megkapod a legjobb sebességet.

Ha válogató valamit csak a lineáris kapcsolat (mint a kapcsolt lista), akkor ez a legjobb választani az első elemet, mert ez a leggyorsabb tételt hozzáférést. Itt azonban, ha a lista már rendezve van, te csavarozott - egy partíció mindig null, a másik mindent, termelő a legrosszabb időben.

Ahhoz azonban, hogy egy kapcsolt lista, szedés semmit mellett az első, majd csak ront a helyzeten. Ez felvenni a középső elemet egy felsorolt ​​listát, akkor azt kell lépni rajta keresztül minden megoszlási lépés - hozzáadásával O (N / 2) művelet, ami történik logN alkalommal így összesen O (1,5 N * log N) és ez, ha tudjuk, hogy milyen hosszú a lista, mielőtt elkezdjük - általában nem így azt kell lépni végig számolni őket, majd lépésről félúton, hogy megtalálják a középső, majd menj végig a harmadik alkalommal, ami a tényleges partíció: O (2,5 n * log N)

Válaszolt 02/10/2008 20:42
a forrás felhasználó

szavazat
1

Ez teljesen attól függ, hogy az adatok rendezve kezdeni. Ha úgy gondolja, ez lesz pszeudo-véletlenszám akkor a legjobb megoldás az, hogy vagy válasszon egy véletlenszerű kiválasztás vagy válasszon a közepén.

Válaszolt 02/10/2008 20:46
a forrás felhasználó

szavazat
16

Heh, én csak tanított ebben az osztályban.

Számos módja van.
Egyszerű: Pick az első vagy az utolsó eleme a tartományban. (rossz részlegesen kiválogatott input) Jobb: Pick az elemet a tartomány közepére. (jobb részlegesen szortírozott bemeneti)

Azonban, szedés tetszőleges elemét a kockázattal jár, gyengén partíciózását tömb n méretű két tömbök mérete 1 és n-1. Ha igen, hogy elég gyakran, a quicksort fennáll az a veszély egyre O (n ^ 2).

Az egyik fejlesztés Láttam, hogy vegye medián (első, utolsó, mid); A legrosszabb esetben, akkor még mindig megy a O (n ^ 2), de a véletlenszerűen, ez a ritka eset.

A legtöbb adat, felvette az első vagy utolsó elegendő. De, ha úgy találja, hogy már fut a legrosszabb forgatókönyveket gyakran (részben rendezve bemenet), az első lehetőség az lenne, hogy vegye a központi értéket (ami statisztikailag jó pivot részlegesen kiválogatott adatok).

Ha még mindig fut be a problémákat, akkor megy a medián útvonalon.

Válaszolt 02/10/2008 20:46
a forrás felhasználó

szavazat
8

Soha válasszon egy fix csap - ez lehet támadni kihasználni a algoritmus legrosszabb esetben O (n ^ 2) futásidejű, ami csak bajt. Gyorsrendezés legrosszabb esetben futásidejű akkor jelentkezik, ha particionálás eredménye egy tömb 1 elem, és egy tömb n-1 elemek. Tegyük fel, hogy úgy dönt, az első elem, mint a partíciót. Ha valaki táplálja tömb a algoritmust, amely szerint csökkenő sorrendben az első pivot lesz a legnagyobb, így minden mást a tömb mozog a bal oldalán. Aztán, ha rekurzív, az első elem lesz a legnagyobb újra, így még egyszer, hogy mindent a bal oldalon, és így tovább.

A jobb technika a medián-of-3 módszer, ahol felveheti a három elem véletlenszerűen, és válassza ki a közepén. Tudod, hogy az elem, amely úgy dönt, nem lesz az első vagy az utolsó, hanem a centrális határeloszlás-tétel, a forgalmazás, a középső elem lesz normális, ami azt jelenti, hogy akkor inkább a közepe felé (és ennélfogva , n lg n idő).

Ha feltétlenül garantálni akarjuk O (nlgn) futásidő az algoritmus, az oszlopok-of-5 módszer megtalálására a medián tömb lépésszáma O (n) idő alatt, ami azt jelenti, hogy a kiújulás egyenletet quicksort a legrosszabb esetben lesz lehet T (n) = O (n) (megtalálják a medián) + O (n) (partíció) + 2T (n / 2) (recurse balra és jobbra.) a mester tétel, ez O (n lg n) . Azonban az állandó tényező lesz nagy, és ha legrosszabb esetben a teljesítmény az elsődleges szempont, használjon merge sort helyett, amely csak egy kicsit lassabb, mint quicksort átlagosan és garantálja O (nlgn) idő (és sokkal gyorsabb lesz mint ez a béna medián quicksort).

Magyarázat a Medián a medián algoritmus

Válaszolt 25/10/2008 22:50
a forrás felhasználó

szavazat
5

Ne próbálja túl okos, és összekapcsolják elforduló stratégiákat. Ha kombinált átlagosan 3 véletlen pivot a szedés a medián az első, az utolsó és egy véletlen index a középső, majd akkor is ki lehet téve a sok eloszlás Levél átlagosan 3 másodfokú (így kissé rosszabb, mint sima véletlenszerű pivot)

Például egy orgona-eloszlás (1,2,3 ... N / 2..3,2,1) első és utolsó lesz egyaránt 1, és a véletlen index lesz néhány szám 1-nél nagyobb, figyelembe véve a medián ad 1 ( vagy az első vagy az utolsó), és akkor kap egy extermely kiegyensúlyozatlan particionálás.

Válaszolt 26/10/2008 04:54
a forrás felhasználó

szavazat
1

Könnyebb megtörni a quicksort három részre ezt

  1. Cserélik adatok elem funkciója
  2. A partíciós függvény
  3. Feldolgozása válaszfalak

Ez csak valamivel több, mint egy hosszú inefficent funkció, de egy csomó könnyebb megérteni.

Kód alábbiak szerint:

/* 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
  };
};
Válaszolt 10/03/2011 03:19
a forrás felhasználó

szavazat
0

Ideális esetben a pivot legyen a középső érték a teljes tömböt. Ez csökkenti az esélyek legrosszabb teljesítményt.

Válaszolt 17/04/2013 15:57
a forrás felhasználó

szavazat
-1

Egy igazán optimális végrehajtását, a módszert választja pivot függjön tömbméret - egy nagy tömb, hogy megéri több időt tölteni egy jó választás pivot. Anélkül, hogy egy teljes körű elemzést, azt hiszem „közepén O (log (n)) elemek” egy jó kezdet, és ez a hozzáadott bónusz, hogy nincs szükség semmilyen extra memória: A farok-felhívását a nagyobb partíciót és in- hely particionálás, használjuk ugyanazt O (log (n)) extra memória szinte minden szakaszában az algoritmust.

Válaszolt 08/10/2013 20:50
a forrás felhasználó

szavazat
0

Gyors rendezés összetettsége nagyban változik a kiválasztás pivot értéket. ha például mindig választhat első eleme egy pivot, algoritmus komplexitása válik a legrosszabb, mint O (n ^ 2). itt van egy okos módszert választani pivot eíem- 1. válassza az első, középső, utolsó eleme a tömb. 2. összehasonlítani a három szám, és megtalálja a szám, amely nagyobb, mint egy, és kisebb, mint más, azaz a medián. 3. az elem pivot elem.

választotta a pivot ezzel a módszerrel osztja a tömb közel két felét, és így a komplexitás csökkenti, hogy O (n kapcsolódás (n)).

Válaszolt 05/12/2013 06:05
a forrás felhasználó

szavazat
0

Az átlagos, átlagosan 3 jó kis n. Medián 5 egy kicsit jobb a nagyobb n. A ninther, amely a „medián három mediánjait három” még jobb nagyon nagy n.

Minél magasabbra megy mintavétel, annál jobb lesz, mint n növekszik, de a javulás drasztikusan lelassul, ahogy növeli a mintákat. És akkor merülnek fel a felsővezeték a mintavétel és rendezési mintákat.

Válaszolt 19/10/2016 10:04
a forrás felhasználó

szavazat
0

Azt ajánljuk, hogy a középső index, mivel a módszerrel könnyen.

Lehet számítani azt a kerekítés (array.length / 2).

Válaszolt 09/08/2017 01:29
a forrás felhasználó

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