Neden quicksort pratikte diğer sıralama algoritmalarından daha iyidir?


308

Standart bir algoritma dersinde, hızlı bağlantı noktasının ortalama olarak ve en kötü durumda ise olduğu öğrenilir. Aynı zamanda, diğer sıralama algoritmaları incelenmiştir hangi olan (gibi en kötü durumda MergeSort ve HizliSiralama ve (gibi iyi durumda bile lineer zamanı) BubbleSort ) ancak belleğin bazı ek ihtiyaçları olan.O ( n 2 ) O ( n log n )O(nlogn)O(n2)O(nlogn)

Bazı çalışma sürelerinde hızlıca bir bakıştan sonra , quicksort'un diğerleri kadar verimli olmaması gerektiğini söylemek doğaldır .

Ayrıca, öğrencilerin temel programlama derslerinde genel olarak derslerin özyinelemenin gerçekten iyi olmadığını, çünkü çok fazla bellek kullanabileceğini vb. Öğrendiklerini göz önünde bulundurun. gerçekten iyi çünkü özyinelemeli bir algoritma.

Öyleyse neden quicksort pratikte diğer sıralama algoritmalarından daha iyi performans gösteriyor? Gerçek dünya verilerinin yapısıyla mı ilgili? Bilgisayarlarda belleğin çalışma şekli ile mi ilgili olmalı? Bazı hatıraların diğerlerinden çok daha hızlı olduğunu biliyorum, ancak bu karşı-sezgisel performansın gerçek nedeni olup olmadığını bilmiyorum (teorik tahminlerle karşılaştırıldığında).


Güncelleme 1: kanonik bir cevap, ortalama davanın 'da yer alan sabitlerin diğer algoritmalarında yer alan sabitlerden daha küçük olduğunu söylüyor . Bununla birlikte, sadece sezgisel fikirler yerine kesin hesaplamalar yaparak, bunun doğru bir gerekçesini henüz görmedim.O ( n log n )O(nlogn)O(nlogn)

Her halükarda, bazı cevapların öne sürdüğü gibi, uygulamaların bilgisayarların iç yapısından yararlandığı bellek düzeyinde, örneğin önbellek RAM'in RAM'den daha hızlı olduğu gibi, gerçek fark oluşuyor gibi görünüyor. Tartışma çok ilginç, ama yine de cevabın bununla ilgisi olduğu anlaşıldığı için bellek yönetimi ile ilgili daha fazla ayrıntı görmek istiyorum .


2 güncelle: sıralama algoritmaları bir karşılaştırmasını sunan çeşitli web sayfaları vardır, (özellikle diğerlerinden daha meraklısı bazı sorting-algorithms.com ). Güzel bir görsel yardım sunmaktan başka, bu yaklaşım sorumu cevaplamıyor.


2
Birleştirme sıralaması en kötü durumda 'dir ve tamsayıların büyüklüğü üzerinde bilinen bir sınırın olduğu bir tamsayı dizisinin sıralanması, zamanında bir sayma sıralaması ile yapılabilir. O ( n )O(nlogn)O(n)
Carl Mummert

13
sort--algorithms.com , sıralama algoritmalarının oldukça kapsamlı bir karşılaştırmasına sahiptir.
Joe

2
Reklam Güncelleme 1: Titiz bir analiz veya gerçekçi varsayımlara sahip olabileceğinizi düşünüyorum . İkisini de görmedim. Örneğin, çoğu resmi analiz yalnızca karşılaştırmaları saymaktadır.
Raphael

9
Bu soru programcılar hakkında yeni bir yarışma kazandı .
Raphael

3
İlginç soru. Bir süre önce rastgele verilerle ve hızlı sıralama ve birleştirme işleminin saf bir uygulamasıyla bazı testler yaptım. Her iki algoritma da küçük veri kümeleri için oldukça iyi performans gösterdi (en fazla 100000 öğe), ancak bundan sonra birleştirme işleminin çok daha iyi olduğu ortaya çıktı. Bu, hızlı sıralamaların çok iyi olduğu ve hala bunun için bir açıklama bulamadığım varsayımına aykırı görünüyor. Ortaya çıkarabileceğim tek fikir normalde hızlı sıralama teriminin intro sıralama gibi daha karmaşık algoritmalar için kullanıldığı ve rasgele pivot ile hızlı sıralamanın saf uygulanmasının o kadar iyi olmadığıdır.
Giorgio

Yanıtlar:


215

Kısa cevap

Önbellek verimliliği argümanı zaten ayrıntılı olarak açıklanmıştır. Ek olarak, Quicksort'un neden hızlı olduğu konusunda kendine özgü bir argüman var. İki “geçiş işaretçisi” gibi uygulandığında, örneğin burada , iç döngüler çok küçük bir gövdeye sahiptir. Bu en sık uygulanan kod olduğundan, bu karşılığını verir.

Uzun cevap

Her şeyden önce,

Ortalama Vaka yok!

En iyi ve en kötü durum çoğu zaman pratikte nadiren aşırılıklar olduğu için, ortalama olay analizi yapılır. Fakat herhangi bir ortalama durum analizi girdilerin bir miktar dağılımını varsaymaktadır ! Sıralama için, tipik seçim rastgele permütasyon modelidir (tam olarak Wikipedia'da varsayılmıştır).

Neden Not?O

Algoritma analizindeki sabitlerin atılması tek bir nedenden dolayı yapılır: Kesin çalışma süreleriyle ilgileniyorsam, ilgili tüm temel işlemlerin ( göreceli) maliyetlerine ihtiyacım var ( yine de önbellekleme konularını görmezden geliyorum, modern işlemcilerde boru hattı ...). Matematiksel analiz, her bir komutun ne sıklıkta uygulandığını sayabilir , ancak tek komutların çalışma süreleri işlemci ayrıntılarına bağlıdır, örneğin 32 bit tam sayı çarpma işleminin ekleme kadar uzun sürüyor.

İki çıkış yolu var:

  1. Bazı makine modellerini düzelt.

    Bu, yazar tarafından icat edilen yapay “tipik” bir bilgisayar için Don Knuth'unBilgisayar Programlama Sanatı” adlı kitap serisinde yapıldı . 3. ciltte , birçok sıralama algoritması için kesin ortalama durum sonuçları bulabilirsiniz , örn.

    • Hızlı bağlantı:11.667(n+1)ln(n)1.74n18.74
    • Mergesort:12.5nln(n)
    • Yığın: 16nln(n)+0.01n
    • Ekleme: [ kaynak ]2.25n2+7.75n3ln(n) Birkaç sıralama algoritmasının çalışma zamanları

    Bu sonuçlar Quicksort'un en hızlı olduğunu göstermektedir. Ancak, yalnızca Knuth'un yapay makinesinde kanıtlandı, x86 PC'nizin söylenmesi için hiçbir şey ifade etmez. Ayrıca algoritmaların küçük girişler için farklı olduğunu unutmayın:
    Küçük girdiler için çeşitli sıralama algoritmaları
    [ kaynak ]

  2. Soyut temel işlemleri analiz eder .

    Karşılaştırma tabanlı sıralama için, bu genellikle takas ve anahtar karşılaştırmalardır . Robert Sedgewick'in kitaplarında, örneğin “Algoritmalar” da , bu yaklaşım izlenmektedir. Orada bul

    • Quicksort: karşılaştırmaları ve ortalama olarak12nln(n)13nln(n)
    • : karşılaştırmaları, ancak dizisine erişir (mergesort takas temelli değildir, bu yüzden bunu sayamayız).8.66 n ln ( n )1.44nln(n)8.66nln(n)
    • Ekleme: karşılaştırmaları ve ortalama olarak .114n214n2

    Gördüğünüz gibi, bu, kesin çalışma zamanı analizi olarak algoritmaların karşılaştırılmasına kolayca izin vermez, ancak sonuçlar makine detaylarından bağımsızdır.

Diğer girdi dağılımları

Yukarıda belirtildiği gibi, ortalama durumlar her zaman bazı girdi dağılımına göredir, bu nedenle rastgele permütasyonlar dışındakiler dikkate alınabilir. Örneğin, Quicksort için eşit elemanlarla araştırma yapıldı ve Java'daki standart sıralama işlevi üzerine güzel bir makale var.


8
Tip 2'nin sonuçları, makineye bağlı sabitlerin eklenmesiyle tip 1'in sonuçlarına dönüştürülebilir. Bu nedenle, savunacağım 2. üstün bir yaklaşım.
Raphael

2
@Raphael +1. Sanırım makineye bağımlı olduğunu da uygulamaya bağlı olduğunu varsayıyorsunuz , değil mi? Hızlı makine + kötü uygulama muhtemelen çok verimli değildir.
Janoma

2
@Janoma Analiz edilen algoritmanın çok ayrıntılı biçimde (analizin ayrıntılandırıldığı gibi) verilmesini ve uygulamanın mektubun olabildiğince çok olmasını kabul ettim. Ancak evet, uygulama da etkili olacaktır.
Raphael

3
Aslında, tip 2 analizi pratikte düşüktür. Gerçek dünya makineleri o kadar karmaşıktır ki, tip 2'den elde edilen sonuçlar fizibil bir şekilde tip 1'e çevrilemez. Tip 1 ile karşılaştırınız: deneysel çalışma sürelerinin çizilmesi 5 dakikalık bir çalışma gerektirir.
Jules

4
@Jules: "deneysel çalışma zamanını çizme" tip 1 değil ; resmi bir analiz değildir ve diğer makinelere aktarılamaz. Bu yüzden, resmi bir analiz yapıyoruz.
Raphael

78

Bu konuda yapılabilecek çok sayıda nokta var.

Quicksort genellikle hızlı

O(n2)

n1O(nlogn)

Quicksort genellikle çoğu türden daha hızlıdır

O(nlogn)O(n2)n

O(nlogn)O(nBlog(nB))B

Bu önbellek etkinliğinin nedeni, girişi doğrusal olarak taraması ve girişi doğrusal olarak bölümlendirmesidir. Bu, önbelleği değiştirmeden önce önbelleğe yüklediğimiz her sayıyı okurken yaptığımız her önbellek yükünden en iyi şekilde yararlanabileceğimiz anlamına gelir. Özellikle, algoritma önbellek bilgisizdir, bu da her önbellek seviyesi için iyi önbellek performansı verir; bu da başka bir kazançtır.

Önbellek verimliliği, ye daha da geliştirilebilirO(nBlogMB(nB))Mk

Quicksort genellikle Mergesort'tan daha hızlıdır

Bu karşılaştırma tamamen sabit faktörlerle ilgilidir (tipik durumu düşünürsek). Özellikle seçim, Quicksort için pivotun en düşük seçimi arasındadır ve Mergesort için tüm girişin kopyası (veya bu kopyalamayı önlemek için gereken algoritmanın karmaşıklığı) arasındadır. Birincisinin daha verimli olduğu ortaya çıktı: bunun arkasında hiçbir teori yok, daha hızlı oluyor.

nO(logn)O(n)

Son olarak, Quicksort'un doğru sırada olan girişe biraz duyarlı olduğunu unutmayın; bu durumda bazı takasları atlayabilir. Mergesort'ta, Quicksort'u Mergesort'a kıyasla biraz daha hızlı hale getiren bir optimizasyon yoktur.

İhtiyaçlarınıza uygun sıralama kullanın

Sonuç olarak: sıralama algoritması her zaman en uygunudur. Hangisinin sizin gereksinimlerinize uygun olduğunu seçin. Çoğu durumda en hızlı olan bir algoritmaya ihtiyacınız varsa ve nadir durumlarda biraz yavaş kalmasına neden olabilir ve sabit bir sıralama yapmanız gerekmiyorsa, Quicksort kullanın. Aksi halde, gereksinimlerinize daha iyi uyan algoritmayı kullanın.


3
Son sözün özellikle değerli. Bir meslektaşım şu anda farklı girdi dağıtımları altında Quicksort uygulamalarını analiz ediyor. Örneğin bazıları birçok kopya için parçalandı.
Raphael

4
O(n2)

8
“[T], bunun arkasında hiçbir teori yok, sadece daha hızlı olacak.” Bu ifade bilimsel açıdan son derece tatmin edici değildir. Newton'un "Kelebekler uçar, elmalar düşer: bunun arkasında teori yoktur, elmalar sadece düşmeye başlar" dediğinizi hayal edin.
David Richerby

2
@Alex ten Brink, "Özellikle, algoritma önbellek engelli" ile ne demek istiyorsun ?
Hibou57

4
@David Richerby, “Bu ifade, bilimsel bakış açısından oldukça tatmin edici değil”: onunla mutlu olmamız gerektiğini iddia etmeden sadece bir gerçeğe tanık olabilir. Bazı algoritma aileleri tam bir formalizasyon eksikliğinden muzdariptir; karma fonksiyonları örnek bir durumdur.
Hibou57

45

Üniversitemdeki programlama derslerinden birinde, öğrencilerden quicksort, mergesort, insert sort vs Python'un yerleşik list.sort ( Timsort olarak adlandırılan ) performansını karşılaştırmasını istedik . Yerleşik list. Bu nedenle, normal hızlı ticaret uygulamasının pratikte en iyisi olduğu sonucuna varmak erkendir. Ancak, quicksort uygulamasının çok daha iyi uygulandığından ya da bunun hibrit versiyonundan eminim.

Bu, David R. MacIver tarafından Timsort'u uyarlanabilir bir birleştirme biçimi olarak açıklayan güzel bir blog makalesidir .


17
@Raphael Bunu kısaca söylemek gerekirse, Timsort, asimptotikler için artı bir giriş ve kısa girişler için yerleştirme sıralama artı bazı sezgilerle zaman zaman sıralanmış veri bloğu (pratikte sık sık gerçekleşen) ile verimli bir şekilde başa çıkabilmektedir. Dai: algoritmaya ek olarak, list.sortprofesyoneller tarafından optimize edilmiş yerleşik bir fonksiyon olmaktan da faydalanabilirsiniz. Daha adil bir karşılaştırma, aynı fonksiyonda, aynı dilde yazılmış tüm fonksiyonlara sahip olacaktır.
Gilles

1
@Dai: En azından ne tür girdilerle (dağılımlarına göre) hangi koşullar altında (düşük RAM, bir uygulama paralel olarak, ...) sonuçlarınızı aldığınızı açıklayabilirsiniz.
Raphael

7
Rastgele sayılar listesinde test ettik ve kısmen sıralanmış, tamamen sıralanmış ve tersine sıralanmış. Bu bir giriş dersi 1. yıldı, bu yüzden derin bir deneysel çalışma değildi. Ancak artık resmi olarak Java SE 7 ve Android platformundaki dizileri sıralamak için kullanılmasının bir anlamı var.
Dai

3
Bu da burada tartışıldı: cstheory.stackexchange.com/a/927/74
Jukka Suomela

34

QuickSort'un diğer sıralama algoritmalarına göre bu kadar hızlı olmasının ana nedenlerinden birinin önbellek dostu olması olduğunu düşünüyorum. QS bir dizinin bir parçasını işlediğinde, parçanın başındaki ve sonundaki öğelere erişir ve parçanın ortasına doğru hareket eder.

Böylece, başlattığınızda, dizideki ilk öğeye erişirsiniz ve önbelleğe bir bellek parçası ("konum") yüklenir. Ve ikinci elemana erişmeye çalıştığınızda, (muhtemelen) önbellekte zaten var, bu yüzden çok hızlı.

Yığın noktası gibi diğer algoritmalar bu şekilde çalışmaz, diziye çok atlarlar ve bu da onları yavaşlatır.


5
Bu tartışılabilir bir açıklama: mergesort da önbellek dostu.
Dmytro Korduban

2
Bu cevap temelde doğru olduğunu düşünüyorum, ama burada bazı detaylar var youtube.com/watch?v=aMnn0Jq0J-E
rgrig

3
muhtemelen hızlı sıralamanın ortalama vaka zaman karmaşıklığı için çarpımsal sabiti de daha iyidir (bahsettiğiniz önbellek faktöründen bağımsız olarak).
Kaveh

1
Bahsettiğiniz nokta, hızlı sıralama diğer iyi özellikleri ile karşılaştırıldığında, o kadar önemli değil.
MMS

1
@Kaveh: "Hızlı sıralamanın ortalama vaka zaman karmaşıklığı için çarpma sabiti de daha iyidir" Bu konuda herhangi bir bilginiz var mı?
Giorgio,

29

Diğerleri , Quicksort'un asimptotik ortalama çalışma zamanının (sabit olarak) diğer sıralama algoritmalarından (belirli ayarlarda) daha iyi olduğunu söylemiştir.

O(nlogn)

Birçok Quicksort çeşidi bulunduğuna dikkat edin (bkz. Sedgewick'in tezi). Farklı girdi dağılımlarında farklı şekilde performans gösterirler (düzgün, neredeyse sıralanmış, neredeyse ters olarak sıralanmış, birçok yinelenen, ...) ve diğer algoritmalar bazıları için daha iyi olabilir.

k10


20

O(nlgn)

ps: Kesin olmak, diğer algoritmalardan daha iyi olmak göreve bağlıdır. Bazı görevler için diğer sıralama algoritmalarını kullanmak daha iyi olabilir.

Ayrıca bakınız:


3
@Janoma, hangi dili ve derleyiciyi kullandığınızla ilgilidir. Neredeyse tüm işlevsel diller (ML, Lisp, Haskell) yığının büyümesini engelleyen optimizasyonlar yapabilir ve zorunlu diller için daha akıllı derleyiciler de aynı şeyi yapabilir (GCC, G ++ ve MSVC'nin hepsinin bunu yaptığına inanıyorum). Dikkate değer bir istisna, bu optimizasyonu hiçbir zaman yapmayacak olan Java'dır, bu nedenle Java'yı özyinelemenizi yineleme olarak yeniden yazmak mantıklıdır.
Rafe Kettler

4
@JD, quicksort ile kuyruk çağrısı optimizasyonunu kullanamazsınız (en azından tamamen değil), çünkü kendisini iki defa çağırır. İkinci aramayı en iyi duruma getirebilirsiniz ancak ilk aramayı optimize edebilirsiniz.
svick

1
@Janoma, özyinelemeli uygulamaya gerçekten ihtiyacınız yok. Örneğin, C'deki qsort işlevinin uygulanmasına bakarsanız, özyinelemeli çağrıları kullanmaz ve bu nedenle uygulama çok daha hızlı hale gelir.
Kaveh

1
Heapsort da yerinde, neden QS genellikle daha hızlı?
Kevin

6
23240

16

Θ(n2)Θ(nlogn)

İkinci sebep ise in-placesıralama yapması ve sanal bellek ortamlarında çok iyi çalışması.

GÜNCELLEME:: (Janoma ve Svick'in yorumlarından sonra)

Bunu daha iyi göstermek için Merge Sort'u kullanarak bir örnek vermeme izin verin (çünkü Merge sort, hızlı sıralamadan sonra bir sonraki yaygın olarak kabul edilen sıralama algoritmasıdır, ve sanırım) ve size ekstra sabitlerin nereden geldiğini (bildiğim kadarıyla ve neden düşündüğümü söyleyeyim) Hızlı sıralama daha iyidir):

Aşağıdaki sırayı düşünün:

12,30,21,8,6,9,1,7. The merge sort algorithm works as follows:

(a) 12,30,21,8    6,9,1,7  //divide stage
(b) 12,30   21,8   6,9   1,7   //divide stage
(c) 12   30   21   8   6   9   1   7   //Final divide stage
(d) 12,30   8,21   6,9   1,7   //Merge Stage
(e) 8,12,21,30   .....     // Analyze this stage

Son aşamada nasıl göründüğüne tam olarak bakarsanız, ilk 12 8 ve 8 ile karşılaştırıldığında daha küçüktür, ilk önce o olur. Şimdi 12, TEKRAR 21 ve 12 ile devam eder ve böyle devam eder. Son birleştirme yani 4 öğeyi 4 öğeyle birlikte alırsanız, Hızlı Sıralamada OLMAYAN sabitler olarak birçok EKSTRA karşılaştırması yapılır. Hızlı sıralama tercih edilmesinin nedeni budur.


1
Ancak sabitleri bu kadar küçük yapan nedir?
svick

1
@svick Sıralandıkları için, in-placeyani fazladan bellek gerekmez.
0x0

Θ(nlgn)

15

Gerçek dünya verileriyle çalışma deneyimim, hızlı erişimin kötü bir seçim olduğudur . Quicksort rastgele verilerle iyi çalışır, ancak gerçek dünya verileri çoğunlukla rastgele değildir.

2008'de bir quicksort kullanımıyla ilgili bir asılı yazılım hatasını izledim. Bir süre sonra, ekleme sıralama, hızlı sıralama, yığın sıralama ve birleştirme sıralaması gibi basit ifadeler yazdım ve bunları test ettim. Birleştirme sıralama, büyük veri kümeleri üzerinde çalışırken diğerlerinden daha iyi performans gösterdi.

O zamandan beri, birleştirme sıralama benim seçim algoritmasıdır. Bu zarif. Uygulaması basittir. Bu istikrarlı bir tür. Quicksort'un yaptığı gibi kuadratik davranışlara dejenere olmaz. Küçük dizileri sıralamak için ekleme düzenine geçiyorum.

Birçok durumda, belirli bir uygulamanın sadece hızlı destek olmadığını anlamak için hızlı destek için şaşırtıcı derecede iyi çalıştığını düşündüğümü kendi kendime öğrendim. Bazen uygulama quicksort ve başka bir algoritma arasında geçiş yapar ve bazen quicksort kullanmaz. Örnek olarak, GLibc'in qsort () işlevleri aslında birleştirme sıralamasını kullanır. Yalnızca çalışma alanı tahsis edilmezse, bir kod yorumunun "yavaş algoritma" olarak adlandırdığı yerinde hızlı bağlantı noktasına geri döner .

Düzenleme: Java, Python ve Perl gibi programlama dilleri aynı zamanda birleştirme sıralamasını veya daha kesin olarak Timsort gibi bir türev kullanır veya büyük kümeler için birleştirme sıralamasını ve küçük kümeler için ekleme düzenini kullanır. (Java ayrıca düz hızlı bağlantı noktasından daha hızlı olan çift eksenli hızlı bağlantı noktası kullanır.)


Buna benzer bir şey görmüştüm, çünkü zaten sıralanan verilerden oluşan bir gruba eklemek için sürekli ekliyorduk. Rastgele bir hızlı bağlantı noktası kullanarak ortalama olarak çalışabilirsiniz (ve nadir ve rastgele bir şekilde yavaş sıralananlar tarafından şaşırırsınız) veya bitirmek için asla şaşırtıcı bir zaman almayan her zaman daha yavaş bir sıralamayı tolere edebilirsiniz. Bazen sıralama dengesini de gerektirir. Java, birleştirme sıralamasını kullanarak bir quicksort varyantına gitti.
Rob

@Rob Bu doğru değil. Java, bugün için hala bir çeşit mergesort (Timsort) kullanıyor. Bir quicksort varyantı da kullanıyor (dual-pivot quicksort).
Erwan Legrand

14

1 - Hızlı sıralama yerinde (sabit bir miktar dışında, ek bir hatıra gerektirmez.)

2 - Hızlı sıralama, diğer verimli sıralama algoritmalarına göre daha kolaydır.

3 - Hızlı sıralama, çalışma süresinde diğer verimli sıralama algoritmalarından daha küçük sabit faktörlere sahiptir.

Güncelleme: Birleştirme sıralaması için, birleştirmeden önce verileri depolamak için fazladan dizi (ler) gerektiren bazı "birleştirme" yapmanız gerekir; ama hızlı sıralamada, yapmazsın. Bu yüzden hızlı sıralama yerinde. Ayrıca birleştirme için yapılan ve birleştirme düzeninde sabit faktörleri artıran bazı ekstra karşılaştırmalar da vardır.


3
Gelişmiş yerinde, yinelemeli Quicksort uygulamalarını gördünüz mü ? Onlar birçok şey ama "kolay" değil.
Raphael

2
2 numara yok değil hiç soruma cevap ve sayılar 1 ve 3 bence doğru bir gerekçe lazım.
Janoma

@Raphael: Onlar kolay. İşaretçiler yerine, bir diziyi kullanarak hızlı sıralama yerine uygulama yapmak çok daha kolaydır. Ve yerinde olması için yinelemeli olması gerekmez.
MMS,

Birleşmenin dizileri o kadar da kötü değil. Bir öğeyi bir kaynak yığından hedef yığına taşıdığınızda, artık orada olması gerekmez. Dinamik dizileri kullanıyorsanız, birleştirme sırasında sabit ek yük vardır.
Oskar Skog

@ 1 Mergesort da yerinde olabilir. @ 2 Verimli ne tanımlar? Ben birleştirme türlerini severim çünkü bence çok basit ve etkili. @ 3 Büyük miktarda veri sıraladığınızda ilgisizdir ve algoritmanın verimli bir şekilde uygulanmasını gerektirir.
Oskar Skog

11

Hangi koşullar altında, belirli bir sıralama algoritması aslında en hızlı olanıdır?

Θ(log(n)2)Θ(nlog(n)2)

Θ(nk)Θ(nm)k=2#number_of_Possible_valuesm=#maximum_length_of_keys

3) Temel veri yapısı bağlantılı elemanlardan mı oluşuyor? Evet -> daima birleştirme sıralamasında kullanın. Bağlantılı veri yapıları için sabit boyutta veya uyarlamalı (aka doğal) aşağıdan yukarıya yerleştirme uygulaması, bağlantılı veri yapıları için bir çok farklı ariteyi birleştirir ve her adımda tüm verilerin kopyalanmasını gerektirmediklerinden ve hiçbir zaman tekrarlama gerektirmediklerinden, diğer genel karşılaştırma tabanlı türlerden daha hızlı, hızlı sıralamadan daha hızlı.

Θ(n)

5) Temel verilerin boyutu küçük ila orta boyuta bağlanabilir mi? Örn: n <10.000 ... 100.000.000 (temel mimariye ve veri yapısına bağlı olarak) mı? Evet -> bitonik sıralama veya Dozer tek / çift birleştirme alanı kullanın. Goto 1)

Θ(n)Θ(n2)Θ(nlog(n)2)Durumda en kötü çalışma süresi biliniyor, ya da belki tarak sıralama deneyin. Uygulamada kabuk sıralama veya tarak sıralama işlemlerinin oldukça iyi sonuç vereceğinden emin değilim.

Θ(log(n))Θ(n)Θ(n)Θ(log(n))Θ(n2)Θ(n)Θ(n)Θ(log(n))Θ(nlog(n))

Θ(nlog(n))

Quicksort için uygulama ipuçları:

Θ(n)Θ(log(n))Θ(nlogk(k1))

2) Quicksort'un aşağıdan yukarıya, yinelemeli varyantları var, ancak AFAIK, aşağıdan yukarıya doğru olanlarla aynı asimptotik alan ve zaman sınırlarına sahipler, ek aşağı tarafların uygulanması zor (örneğin bir sıranın açıkça yönetilmesi gibi). Benim deneyimim, pratik amaçlarla, bunların asla göz önünde bulundurulmayacaklarıdır.

Mergesort için uygulama ipuçları:

1) bottum-up mergesort, yineleme çağrıları gerektirmediğinden yukarıdan aşağı mergesorttan her zaman daha hızlıdır.

2) çok saf mervesort, bir çift tampon kullanılarak hızlandırılabilir ve her adımdan sonra verileri geçici diziden geri kopyalamak yerine tamponu değiştirebilir.

3) Gerçek dünyadaki birçok veri için, adaptif mergesort, sabit boyutlu mergesorttan çok daha hızlıdır.

Θ(k)Θ(log(k))Θ(1)Θ(n)

Yazdıklarımdan, aşağıdaki koşulların geçerli olduğu durumlar haricinde, quicksort'un genellikle en hızlı algoritma olmadığı açıktır:

1) "az" olası değerden daha fazlası var

2) temel veri yapısı bağlantılı değildir

3) istikrarlı bir sipariş gerekmez

4) veriler, bir bitonik sıralayıcının veya Batcher'in tek başına birleşmiş mergesort'un hafif alt optimal asimptotik çalışma zamanının başladığı kadar büyüktür.

5) veri neredeyse sıralanmamış ve daha önceden sınıflandırılmış daha büyük bölümlerden oluşmuyor

6) veri sırasına aynı anda birden fazla yerden erişebiliriz

Θ(log(n))Θ(n)

ps: Birinin bana metnin biçimlendirilmesinde yardım etmesi gerekiyor.


(5): Apple'ın sıralama uygulaması, önce dizinin başında ve sonunda bir koşuyu artan veya azalan sırada denetler. Bu kadar çok eleman yoksa, bu çok hızlıdır ve bunlardan n / ln'den daha fazlası varsa, bu elemanları çok etkili bir şekilde ele alabilir. İki sıralı diziyi birleştirin ve sonucu sıralayın; böylece bir birleşme elde edin
gnasher729

8

Sıralama yöntemlerinin çoğu kısa adımlarla verileri hareket ettirmek zorundadır (örneğin, birleştirme sıralaması yerelde değişiklikler yapar, sonra bu küçük veri parçasını birleştirir, daha sonra daha büyük olanı birleştirir.). Sonuç olarak, veriler hedefinden uzaktaysa birçok veri hareketine ihtiyacınız vardır.

ab


5
Quicksort vs merge sort argümanınız su tutmuyor. Quicksort büyük bir hareketle başlar, daha sonra daha küçük ve daha küçük hareketler yapar (her adımda yaklaşık yarısı kadar büyük). Birleştirme sıralaması küçük bir hareketle başlar, daha sonra daha büyük ve daha büyük hareketler yapar (her adımda yaklaşık iki kat daha büyük). Bu, birinin diğerinden daha verimli olduğunu göstermez.
Gilles,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.