Quicksort: pivotu Seçimi

oy
94

Quicksort uygularken, yapmanız gereken şeylerden biri bir pivot seçmektir. Ben aşağıdaki gibi pseudocode baktığımızda Ancak, ben pivotu seçmeliyim nasıl açık değildir. Listenin ilk elemanı? Başka bir şey?

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

Birisi bana bir pivot seçme kavramını kavramak ve olsun veya olmasın farklı senaryolar farklı stratejiler için çağrı yardımcı olabilir.

Oluştur 02/10/2008 saat 20:37
kaynak kullanıcı
Diğer dillerde...                            


13 cevaplar

oy
72

Rastgele pivotu seçmek, en kötü durum O (n karşılaşacak olasılığını en aza indirir 2 ) performansı (her zaman ilk veya son neredeyse-sıralanabilir veya neredeyse-ters-ayrılmış veriler için en kötü durum performansına sebep olur seçerek). Orta eleman seçilmesi de çoğu durumda kabul edilebilir.

Bu kendini uyguladıklarını, ayrıca, (yani onları birleştirerek sonra iki yeni listeleri oluşturarak ve olmadan) yerinde çalışmak algoritmasının versiyonları vardır.

Cevap 02/10/2008 saat 20:41
kaynak kullanıcı

oy
47

Bu sizin gereksinimlerine bağlıdır. rastgele bir pivot seçimi zor O (N ^ 2) performansını üreten bir veri seti oluşturmak için yapar. 'Medyan-of-üç' (ilk, son, orta) da sorunlara kaçınmanın bir yoludur. gerçi karşılaştırmalar, göreceli performansı dikkat; senin karşılaştırmalar masraflı ise, o zaman MO3 rastgele (tek bir eksen değeri) seçerek daha karşılaştırmaları yapar. Veritabanı kayıtları karşılaştırmak pahalıya mal olabilir.


Güncelleme: cevap içine yorum Çekme.

mdkess iddia:

'3 Medyan' ilk olarak geçen orta DEĞİLDİR. Üç rastgele dizinleri seçin ve bu orta değerini alır. Eğer öyleyse, en kötü durum veri oldukça kolay üretilebilir - bütün mesele pivotlar seçiminiz deterministik olmadığından emin kılmaktır.

hangi için ben cevap verdi:

  • Medyan-Of-Üç Bölümü ile Hoare'nın Bul Algoritma Analizi P Kirschenhofer H PRODINGER tarafından (1997), C Martínez ( 'medyan-of-üç' üç rastgele ürün olduğunu) senin çekişme destekler.

  • Adresinde açıklanan bir makale var portal.acm.org Bilgisayar Dergisi, Cilt 27, Sayı 3, 1984 [Güncelleme yayınlanan Hannu Erkiö tarafından 'En kötü durum Permütasyon için Medyan-of-Üç Quicksort' hakkındadır, 2012-02- 26: metnini Got maddeye . ': Bölüm 2 'Algoritma' başlar bir [L: R] birinci, orta ve son elemanların medyan kullanarak oldukça eşit büyüklükte parçalar halinde, etkili bölmeler en pratik durumlarda elde edilebilir. 'Bu durumda, birinci orta geçen MO3 yaklaşımı ele almaktadır.]

  • Ilginç bir başka kısa makale MD McIlroy gereğidir "Quicksort A Killer düşman" Yazılım-Uygulama ve Deneyim, Cilt yayımlanan. 29 (0), 1-4 (0 1999). Neredeyse her Quicksort quadratically davranması yapmak açıklar.

  • AT & T Bell Labs Teknik Dergisi, Ekim Hoare birkaç rasgele seçilen çizgilerin medyan çevresinde bölünmesini önerdi" belirtiyor. Sedgewick'e 1984 "Bir sırala Rutin Çalışma İnşaat Kuram ve Uygulama"[...] İlk [ortancasını seçerek tavsiye etmişti. ..] son [...] ve orta". Bu 'ortanca-of-üç' için iki teknik literatürde bilinmektedir olduğunu gösterir. (Güncelleme 2014/11/23: makale mevcut gibi görünen IEEE Xplore ya dan Wiley - Eğer üyelik ya da bir ücret ödemeye hazır olup olmadığını.)

  • 'Bir Sıralama İşlevi Mühendislik' Yazılım Uygulama ve Deneyim, Cilt 23 (11), Kasım 1993 yılında yayınlanan JL Bentley ve MD McIlroy, konuların geniş bir tartışma gider ve onlar kısmen dayanarak uyarlamalı bölümleme algoritması seçti veri kümesinin boyutu. Çeşitli yaklaşımlara olan değiş tokuş bir çok tartışma vardır.

  • 'Ortanca-of-üç' için bir Google araması daha fazla izleme için oldukça iyi çalışıyor.

Bilgi için teşekkürler; Ben sadece deterministik 'medyan-of-üç', karşılaştığımız.

Cevap 02/10/2008 saat 20:42
kaynak kullanıcı

oy
1

Eğer (bir dizi gibi) rastgele erişimli koleksiyonunu sıralama iseniz, fiziksel orta öğeyi almak için en iyi general. Dizi ise bu, tüm sıralanmış (veya hemen hemen sıralı) hazır, iki bölüm bile yakın olacak ve en iyi hız elde edersiniz.

Eğer (bir bağlantılı liste gibi) sadece lineer erişimi olan bir şey sıralama ise en hızlı öğe erişmeye çünkü, o zaman ilk öğeyi seçmek en iyisidir. bir bölüm her zaman boş olacak ve diğer kötü zaman üreten, her şey var - İşte liste zaten sıralanır eğer, ancak, mahvoluruz.

Ancak, bağlantılı liste için, ilk dışında bir şey toplama, sadece Daha da kötüsü olacak. Bu bir listede listesindeki orta öğe seçmek, her bölüm adım içinden adım olurdu - toplam süre O yapım logn kez yapılır bir O ekleyerek (N / 2) işlemi (1.5 N * N log) genellikle biz bu yüzden adım adım sonra, orta bulmak için içinden yarı yolda adım sonra, onları saymak için tüm yol boyunca adım olurdu yoktur - biz başlamadan önce liste ne kadar süre biliyorsanız ve işte üçüncü kez gerçek bölümü yapmak için: O (2.5N * log N)

Cevap 02/10/2008 saat 20:42
kaynak kullanıcı

oy
1

Bu veri ile başlamak nasıl sıralandığını tamamen bağlıdır. Eğer sözde rasgele olacağını düşünüyorum, o zaman en iyi bahis Rastgele seçilmiş almak veya orta seçmek ya olduğunu.

Cevap 02/10/2008 saat 20:46
kaynak kullanıcı

oy
16

Heh, ben sadece bu sınıfı öğretti.

Çeşitli seçenekler vardır.
Basit: aralığın ilk veya son öğeyi seçin. (kısmen sıralı girişinde kötü) Daha iyi: aralığının ortasında öğeyi seçin. (kısmen sıralı girdi daha iyi)

Ancak, herhangi bir keyfi elemanı toplama kötü büyüklüğü 1 ve n-1 İki dizinin içine büyüklüğünün dizi n bölünmesi riskini taşır. Bunu yeterince sık yaparsanız, quicksort (n ^ 2) O olma riskini taşır.

Gördüğüm Bir gelişme medyan (ilk, son, orta) almak olduğunu; En kötü durumda, hala O (n ^ 2) gidebilirsiniz ama olasılıksal, bu nadir bir durumdur.

En veriler için, ilk toplama veya son yeterlidir. Eğer kötü durum senaryoları genellikle (kısmen sıralanmış giriş) içine çalıştıran fark ettiğimiz takdirde Fakat, ilk seçenek (kısmen sıralı veriler için istatistiksel iyi pivot olan) merkez değerini almak olacaktır.

Hala sorunlarla çalıştırıyorsanız, daha sonra medyan rota gidin.

Cevap 02/10/2008 saat 20:46
kaynak kullanıcı

oy
8

Asla sabit bir pivotu seçmek - bu algoritmanın en kötü durum O sadece sorun istiyor (n ^ 2) çalışma zamanı, yararlanmak için saldırıya edilebilir. 1 elemanın bir dizi, ve n-1 elemanlarının bir dizi sonuçları bölümleme zaman Quicksort en kötü durum çalışma zamanı ortaya çıkar. Eğer bölüm olarak ilk öğesini seçmek varsayalım. Birisi azalan bulunduğuna dair algoritmaya bir dizi besleniyorsa dizideki her şey için solundaki hareket edecek, böylece birinci pivot, en büyüğü olacak. Eğer Recurse Sonra, birinci eleman böylece bir kez daha bu kadar üzerinde kendisine solundaki şeyi koymak ve yine büyük olacak.

Daha iyi bir teknik, rastgele üç unsuru seçmek ve orta seçim medyan-of-3 yöntem vardır. Seçtiğiniz öğesi ortasına doğru eğiliminde olacaktır, yani ilk veya son değil, aynı zamanda, merkezi limit teoremi ile orta elemanın dağılımı normal olacağını olmayacağını biliyorum (ve dolayısıyla n, lg n saat).

kesinlikle algoritması için O (nlgn) çalışma zamanını garanti etmek istiyorsanız, bir dizi ortancasını bulmak için sütunları-of-5 yöntem anlamına gelen O (n) zaman içinde çalıştığını kötü durumda quicksort için tekrarlama denklemi olacak T (n) = O (n) (orta değerlerini bulmak) + O (n) (bölme) + 2T (n / 2) (sol ve sağ rECURSE.) olmak ana teoremi olarak, bu O (n lg n) . Ancak, sabit faktör büyük olacak ve en kötü durum performans birincil endişe ise, zaman ortalama quicksort daha sadece biraz daha yavaş olduğunu ve O (nlgn) garanti sıralama metodu yerine birleştirme kullanmak (ve çok daha hızlı olacak Bu topal medyan quicksort yerine).

Ortanca Algoritmanın Median'ın açıklanması

Cevap 25/10/2008 saat 22:50
kaynak kullanıcı

oy
5

denemek ve çok zeki olsun ve döner stratejisini birleştirmek etmeyin. Eğer ortada, ilk olarak geçen ve rastgele indeksi ortancasını seçerek rastgele pivot ile 3 ortancasını kombine, o zaman hala daha kuadratik 3 (böylece onun aslında kötü ortancasını göndermek dağılımları birçok savunmasız olacak düz rastgele eksen)

(Örneğin, bir boru organ dağılımı (1,2,3 ... N / 2..3,2,1) ilk ve son ikisi de 1 olacak ve rasgele indeks medyan alarak 1 verir, 1 'den bir sayı daha fazla olacaktır ilk veya son) ve ya bir extermely dengesiz bölümleme olsun.

Cevap 26/10/2008 saat 04:54
kaynak kullanıcı

oy
1

Üç bölüm Bunu yaparken içine quicksort kırmak kolaydır

  1. Değişim veya takas veri elemanı işlevi
  2. bölümleme işlevi
  3. bölümleri işleniyor

Sadece biraz daha inefficent bir uzun işlevinden daha ama anlamak çok kolaydır.

Kod aşağıdaki gibidir:

/* 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
  };
};
Cevap 10/03/2011 saat 03:19
kaynak kullanıcı

oy
0

İdeal olarak, pivot tüm dizi orta değer olmalıdır. Bu kötü durum performansı alma şansını azaltacaktır.

Cevap 17/04/2013 saat 15:57
kaynak kullanıcı

oy
-1

gerçekten optimize uygulamada, pivotu seçme yöntemi dizisi büyüklüğüne bağlı olmalıdır - Geniş dizisi için, iyi bir pivotu seçerken fazla vakit geçirmek için işe yarar. Daha büyük bölümü ve in- üzerinde kuyruk çağrıyı kullanma: tam bir analiz yapmadan, ben iyi bir başlangıç ​​olduğunu ve bu ekstra bellek gerektirmeyen avantaj vardır "(log (n)) elemanları O ortasında" Tahmin ediyorum yer bölümleme, aynı O (log (n)) ekstra bellek algoritmasının hemen her kademesindeki kullanın.

Cevap 08/10/2013 saat 20:50
kaynak kullanıcı

oy
0

Hızlı sıralama karmaşıklığı dönme değerinin seçimi ile büyük ölçüde değişir. Örneğin her zaman bir eksen olarak ilk öğesini seçerseniz, algoritmanın karmaşıklığı olarak kötü O olarak (n ^ 2) olur. Burada mil elementi-1 dizinin ilk, orta, son öğe seçmek seçmek için bir akıllı yöntemdir. 2. Bu üç sayı karşılaştırmak ve medyan yani diğerinden daha birden büyük ve küçük numarayı bulmak. 3. mil elemanı olarak bu eleman olun.

Bu yöntemle bir pivot seçme yaklaşık iki devre, bir dizi böler ve dolayısıyla karmaşıklık O (nlog (n)) için azaltır.

Cevap 05/12/2013 saat 06:05
kaynak kullanıcı

oy
0

Ortalama olarak, 3 Medyan küçük n için iyidir. 5 Medyan büyük n için biraz daha iyidir. "Üçte üç medyan medyan" dir ninther, çok büyük n için daha iyi.

Daha yüksek sizi daha iyi n arttıkça olsun örnekleme ile gitmek, ancak örnekleri artırmak olarak iyileşme önemli ölçüde yavaşlar. Ve örnekleme ve örnekleri sıralama yükü tabi.

Cevap 19/10/2016 saat 10:04
kaynak kullanıcı

oy
0

o kolayca hesaplanabilir gibi ben orta dizini kullanarak öneriyoruz.

Sen (Array.length / 2) yuvarlama bunu hesaplayabilir.

Cevap 09/08/2017 saat 01:29
kaynak kullanıcı

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