Quicksort neden birleşmeden daha iyi?


355

Bir röportaj sırasında bu soru soruldu. İkisi de O (nlogn) ve yine de çoğu kişi Mergesort yerine Quicksort kullanıyor. Neden?


91
Bu çok iyi bir röportaj sorusu değil. Gerçek dünya verileri karıştırılmaz: çoğu zaman akıllı bir sıralamada kullanılabilecek çok sayıda düzen içerir ve algoritmaların hiçbiri bunu otomatik olarak yapmazken, bunu yapmak için bir sıralama türünü bir hızlı sıralamadan daha kolay kesmek daha kolaydır. GNU libc'ler qsort, Python'lar list.sortve Array.prototype.sortFirefox'taki JavaScript'in tümü çorbalanmış birleştirme türleridir. (GNU STL sortbunun yerine Introsort'u kullanır, ancak bunun nedeni C ++ 'da, kopyalamanın potansiyel olarak kopyalamaya göre büyük kazanmasıdır.)
Jason Orendorff

3
@Jason Orendorff: Neden öyle "easier to hack a mergesort to do it than a quicksort"? Alıntı yapabileceğiniz belirli bir örnek var mı?
Lazer

16
@ eSKay Bir birleştirme sıralaması, ilk verileri sıralı alt diziler halinde gruplayarak başlar. Dizi başlangıçta zaten sıralanmış bazı bölgeler içeriyorsa, başlamadan önce orada olduklarını tespit ederek çok zaman kazanabilirsiniz. Ve bunu O (n) zamanda yapabilirsiniz. Özel örnekler için bahsettiğim üç projenin kaynak koduna bakın! En iyi örnek, burada ayrıntılı olarak açıklanan Python'un Timsort'u olabilir: svn.python.org/view/python/trunk/Objects/… ve svn.python.org/view/python/trunk/Objects/… .
Jason Orendorff

4
@JasonOrendorff: Birleştirme işleminin zaten sıralanmış bölümlerden yararlanmak için daha kolay değiştirilebileceği iddiasını aldığımdan emin değilim. Hızlı sıralamanın bölümleme adımı, daha sonra her iki bölümün sıralanıp sıralanmadığını kontrol etmek ve eğer varsa tekrarlamayı durdurmak için önemsiz bir şekilde değiştirilebilir. Bu potansiyel olarak karşılaştırma sayısını ikiye katlar, ancak bu adımın O (n) zaman karmaşıklığını değiştirmez.
j_random_hacker

3
@j_random_hacker: doğru, bunu ima ediyordum. Ancak şunu düşünün: {10, 2, 3, 4, 5, 6, 7, 8, 1, 9} Neredeyse tamamen sıralanmış olmasına rağmen, bölümün onu bulamayacağından önce ne de sonra kontrol edin. Ve sonraki aramalar bunu kontrol etmeden önce bölüm onu ​​vidalar. Bu arada, herhangi bir taşınır önce birleştirme sıralar bölünme adımlarla sıralı diziler kontrol edin ve akıllı olanları özellikle bölünme adımı sırasında böyle çalışır arayacaktır (bkz: Tim Sıralama)
mölemeye Duck

Yanıtlar:


276

Quicksort, O ( n 2 ) en kötü durum çalışma zamanına ve O ( n log n ) ortalama vaka çalışma süresine sahiptir. Bununla birlikte, birçok senaryoda sıralamayı birleştirmek daha üstündür çünkü birçok faktör bir algoritmanın çalışma zamanını etkiler ve hepsini bir araya getirirken hızlı sıralama kazanır.

Özellikle, sık sık alıntılanan sıralama algoritmalarının çalışma zamanı, karşılaştırmaların sayısını veya verileri sıralamak için gereken takasların sayısını ifade eder. Bu, özellikle de temel donanım tasarımından bağımsız olduğu için, performansın gerçekten iyi bir ölçüsüdür. Bununla birlikte, referans konumu gibi (diğer bir deyişle önbellekte olan birçok öğeyi okuyor muyuz?) Diğer şeyler de mevcut donanım üzerinde önemli bir rol oynamaktadır. Özellikle Quicksort çok az ek alan gerektirir ve iyi önbellek yeri gösterir ve bu birçok durumda sıralamayı birleştirmekten daha hızlı hale getirir.

Buna ek olarak, hemen hemen pivotun uygun bir seçimini kullanarak (yani mükemmel bir stratejidir) quicksort'un en kötü çalışma O ( n 2 ) çalışma süresinden kaçınmak çok kolaydır .

Uygulamada, birçok hızlı quicksort uygulaması (özellikle libstdc ++ 'lar std::sort) aslında teorik olarak en kötü durumu O ( n log n ) olan birleştirme sıralamasıyla introsorttur . Bunu, özyineleme derinliğini sınırlandırarak ve log n'yi aştığında farklı bir algoritmaya ( heapsort ) geçerek başarır .


4
Wikipedia makalesi, birleştirme değil yığın yığınına geçtiğini belirtiyor ... sadece FYI.
Sev

3
@Sev:… orijinal kağıtta olduğu gibi. Hatayı belirttiğiniz için teşekkürler. - Asemptotik çalışma süreleri aynı olduğu için gerçekten önemli değil.
Konrad Rudolph

110
bu neden doğru cevap olarak seçilmiş? Açıkladığı tek şey, problemlerin ne kadar hızlı çözüleceğidir. Hala hızlı sıralama neden diğerlerinden daha fazla kullanıldığını söylemiyor? "Hızlı sıralama diğerlerinden daha fazla kullanılır mı? Çünkü bir derinlikten sonra yığınlara geçebilirsiniz" mi? .. neden ilk etapta heatsort kullanmıyorsunuz? .. sadece anlamaya çalışıyor ...
codeObserver

16
@ p1 Güzel soru. Gerçek cevap, ortalama olarak, ortalama veriler için hızlı sıralamanın birleştirme sıralamasından (ve bu konu için yığın sıralamasından) daha hızlı olması ve en hızlı hızlı sıralamanın birleştirme sıralamasından daha yavaş olmasına rağmen, bu en kötü durum çok kolay bir şekilde azaltılabilir (dolayısıyla cevabım).
Konrad Rudolph

4
Quicksort, bellek açısından da daha iyidir.
Shashwat

287

Birçok kişinin belirttiği gibi, quicksort için ortalama vaka performansı birleşmeden daha hızlıdır. Ancak bu, talep üzerine herhangi bir belleğe erişmek için sürekli zaman ayırdığınız zaman geçerlidir.

RAM'de bu varsayım genellikle çok kötü değildir (önbellekler nedeniyle her zaman doğru değildir, ancak çok kötü değildir). Ancak veri yapınız diskte yaşayacak kadar büyükse , ortalama diskinizin saniyede 200 rastgele arama gibi bir şey yapması nedeniyle hızlı sıralama ölür . Ancak aynı diskin saniyede megabayt veri sıralı olarak okunması veya yazılmasında sorun yoktur. Birleştirme işleminin yaptığı tam olarak budur.

Bu nedenle, verilerin diskte sıralanması gerekiyorsa, gerçekten, birleştirme üzerinde bazı varyasyonlar kullanmak istersiniz. (Genellikle alt listeleri hızlıca sıralarsınız, ardından bunları bir boyut eşiğinin üzerinde birleştirmeye başlarsınız.)

Ayrıca , bu boyuttaki veri kümeleriyle herhangi bir şey yapmanız gerekiyorsa, disk aramayı nasıl önleyeceğinizi düşünün. Örneğin, veritabanlarında büyük veri yüklemeleri yapmadan önce dizinleri bırakmanız ve daha sonra dizini daha sonra yeniden oluşturmanızın nedeni budur. Yük sırasında dizinin korunması, sürekli olarak disk aramak anlamına gelir. Buna karşılık, dizinleri bırakırsanız, veritabanı önce ele alınacak bilgileri sıralayarak (elbette bir birleşim kullanarak!) Ve ardından dizin için BTREE veri yapısına yükleyerek dizini yeniden oluşturabilir. (BTREE'ler doğal olarak sırayla tutulur, böylece sıralı bir veri kümesinden diske birkaç arama yaparak bir tane yükleyebilirsiniz.)

Disk aramalarından nasıl kaçınacağımı anlamanın, veri işleme işlerini günler veya haftalar yerine saatler sürdürebilmeme izin verdiği çeşitli durumlar olmuştur.


1
Çok güzel, veri yapısına erişmek için yapılan varsayımlar hakkında düşünmemiştim. İyi fikir :)
chutsu

2
"Disk aramak" ile ne demek istediğinizi açıklayabilir misiniz, veriler diskte saklandığında tek bir değer aramak anlamına mı gelir?
James Wierzba

8
@JamesWierzba "Diskte bir yer aramak" anlamına gelen bağlamdan alıyorum. Dönen bir disk aygıtında "arama", okuma kafasını alıp kötü bir şekilde yavaş bir işlem olan yeni bir mutlak adrese taşıma anlamına gelir. Verilere kaydedildiği sırayla eriştiğinizde, disk donanımı aramak zorunda kalmaz, sadece öğeleri yüksek hızda sürerek öğeleri sırayla okur.
nclark

1
Bazıları bunu biraz daha açıklayabilir mi? Ben böyle görüyorum: Quicksort: Eğer rastgele pivot ile gidiyoruz, çağrı yığını rastgele bir şekilde bölümlenmiş dizi parçaları vardır. Bu rastgele erişim gerektirir. Ancak, yığındaki her çağrı için hem sol hem de sağ işaretçiler sırayla hareket eder. Bunların önbellekte saklanacağını varsayıyorum. Takaslar, önbellekteki (ve sonunda Disk'e yazılan) bilgiler üzerinde yeniden yapılan işlemlerdir. (bir sonraki
sam

1
Maliyetli disk okuma / yazma ek yükünü önleyen bir katkı : Disk erişimi gerektiren çok büyük verileri sıralarken, her geçiş için sıralama yönünü değiştirmek avantajlıdır. Yani, döngünün en üst seviyesinde, bir kez 0doğru gittiğinizde nve bir sonraki ngidişinizde 0. Bu, bellekte (önbellek) zaten mevcut olan veri bloklarını yeniden kaplama (sıralama) ve yalnızca bir disk erişimi için iki kez saldırma avantajı getirir. Bence çoğu DBMS bu optimizasyon tekniğini kullanıyor.
SSD

89

Aslında, QuickSort O (n 2 ) 'dir. Onun ortalama vaka çalışma süresi O (nlog (n)), ama onun kötü durum O (n 2 Eğer birkaç benzersiz öğeleri içeren bir liste üzerinde çalıştırdığınızda oluşur). Rasgeleleştirme O (n) alır. Tabii ki, bu en kötü durumunu değiştirmez, sadece kötü niyetli bir kullanıcının sıralamanızı uzun sürmesini önler.

QuickSort daha popülerdir çünkü:

  1. Yerinde (MergeSort, sıralanacak öğe sayısına doğrusal ilave bellek gerektirir).
  2. Küçük bir gizli sabiti vardır.

4
Aslında, en kötü durumda O (n ^ 2) değil, O (n * log (n)) olan QuickSort uygulaması vardır.
jfs

12
Aynı zamanda bilgisayar mimarisine de bağlıdır. Quicksort önbellekten yararlanırken MergeSort kullanmaz.
Cristian Ciupitu

4
@JF Sebastian: Bunlar büyük olasılıkla introsort uygulamalarıdır, hızlı sıralama değildir (introsort hızlı sıralama olarak başlar ve n * log (n) olmayı bırakmak üzereyse yığın kümesine geçer).
CesarB

44
Bir birleşimi yerinde uygulayabilirsiniz.
Marcin

6
Birleştirme sıralaması yalnızca O (1) fazladan depolama alanı gerektiren bir şekilde uygulanabilir, ancak bu uygulamaların çoğu performans açısından büyük ölçüde acı çeker.
Daha net

29

"ve yine de çoğu kişi Mergesort yerine Quicksort kullanıyor. Neden böyle?"

Verilmemiş bir psikolojik neden, basitçe Quicksort'un daha akıllıca adlandırılmış olmasıdır. yani iyi pazarlama.

Evet, üçlü ayrıştırma ile Quicksort muhtemelen en iyi genel amaçlı sıralama algoritmalarından biridir, ancak "Hızlı" sıralama "Birleştirme" sıralamasından çok daha güçlü geliyor.


3
Hangisinin daha iyi olduğu sorusuna cevap vermez. Hangisinin daha iyi olduğunu belirlemede algoritmanın adı önemsizdir.
Nick Gallimore

18

Diğerlerinin de belirttiği gibi, Quicksort'un en kötü durumu O (n ^ 2), birleşme ve yığın ise O'da (nlogn) kalır. Bununla birlikte, ortalama durumda, her üçü de O (nlogn); bu yüzden karşılaştırılabilir vakaların büyük çoğunluğu içindir.

Quicksort'u ortalama olarak daha iyi yapan şey, iç döngünün birkaç değeri tek bir değerle karşılaştırmayı ima etmesidir, diğer ikisinde ise her iki terim her karşılaştırma için farklıdır. Başka bir deyişle, Quicksort diğer iki algoritmanın yarısı kadar okur. Modern CPU'larda performans, erişim sürelerine büyük ölçüde hakimdir, bu nedenle Quicksort sonunda harika bir ilk seçenek haline gelir.


9

Şimdiye kadar bahsi geçen üç algoritmanın (mergesort, quicksort ve yığın sıralaması) sadece mergesort'un kararlı olduğunu eklemek istiyorum. Yani, aynı anahtara sahip olan değerlerin sırası değişmez. Bazı durumlarda bu arzu edilir.

Ancak, gerçeği söylemek gerekirse, pratik durumlarda çoğu insan sadece iyi bir ortalama performansa ihtiyaç duyar ve hızlı sıralama ... hızlı =)

Tüm sıralama algoritmalarının iniş çıkışları vardır. İyi bir genel bakış için algoritmaları sıralama hakkında Wikipedia makalesine bakın .


7

Gönderen Quicksort Wikipedia girişi :

Quicksort ayrıca başka bir özyinelemeli sıralama algoritması olan mergesort ile rekabet eder, ancak en kötü durum Θ (nlogn) çalışma süresinin avantajı ile. Mergesort, hızlı sıralama ve yığından farklı olarak kararlı bir sıralamadır ve bağlantılı listelerde ve disk depolama veya ağa bağlı depolama gibi erişimi yavaş ortamlarda depolanan çok büyük listelerde çalışacak şekilde kolayca uyarlanabilir. Hızlı sıralama bağlantılı listelerde çalışacak şekilde yazılabilse de, genellikle rastgele erişim olmadan zayıf pivot seçeneklerinden muzdarip olacaktır. Birleştirmenin ana dezavantajı, diziler üzerinde çalışırken, en iyi durumda Θ (n) yardımcı alan gerektirmesidir, oysa yerinde bölümleme ve kuyruk özyineleme ile çabuk sıralama varyantında sadece Θ (logn) alan kullanılır. (Bağlantılı listelerde çalışırken, birleştirme işleminin yalnızca küçük ve sabit miktarda yardımcı depolama alanı gerektirdiğini unutmayın.)


7

Mu! Quicksort daha iyi değildir, mergesorttan farklı bir uygulama türü için uygundur.

Mergesort, hızın temelde olup olmadığını, en kötü durum performansının tolere edilemediğini ve fazladan alanın mevcut olup olmadığını düşünmeye değer. 1

“İkisi de O (nlogn) […]» olduklarını söylediniz. Bu yanlış. «Quicksort en kötü durumda yaklaşık n ^ 2/2 karşılaştırması kullanıyor.» 1 .

Ancak tecrübelerime göre en önemli özellik, programlama dillerini zorunlu paradigma ile kullanırken sıralamada kullanabileceğiniz sıralı erişimin kolay uygulanmasıdır.

1 Sedgewick, Algoritmalar


Mergesort, ek alana ihtiyaç duymayacak şekilde yerinde uygulanabilir. Örneğin, çift bağlantılı bir listeyle: stackoverflow.com/questions/2938495/…
lanoxx

6

Quicksort, pratikte en hızlı sıralama algoritmasıdır, ancak O (n2) kadar kötü performans göstermesini sağlayan bir takım patolojik vakalara sahiptir.

Yığın dizisinin O (n * ln (n)) cinsinden çalışması garanti edilir ve yalnızca sınırlı ek depolama gerektirir. Ancak, yığınların ortalama olarak hızlı sıralamadan önemli ölçüde daha yavaş olduğunu gösteren gerçek dünya testlerinin birçok alıntısı vardır.


5

Wikipedia'nın açıklaması:

Tipik olarak, hızlı sıralama uygulamada diğer n (nlogn) algoritmalarından önemli ölçüde daha hızlıdır, çünkü iç döngüsü çoğu mimaride etkili bir şekilde uygulanabilir ve gerçek dünyadaki verilerin çoğunda, ikinci dereceden zaman gerektirme olasılığını en aza indiren tasarım seçimleri yapmak mümkündür .

Hızlı sıralama

mergesort

Ben de çabuk uygulamaların sahip olmadığı Mergesort (Ω (n)) için gereken depolama miktarı ile ilgili sorunlar olduğunu düşünüyorum. En kötü durumda, bunlar aynı miktarda algoritmik süredir, ancak birleştirme daha fazla depolama gerektirir.


En hızlı quicksort durumu O (n), mergesort O (n log n) - bu yüzden orada büyük bir fark var.
paul23

1
En kötü durum quicksort O (n ^ 2) - önceki
yorumumu

@ paul23 yorum silinebilir. Ayrıca, cevap zaten sizin açınızdan değinmiştir: "Çoğu gerçek dünya verilerinde, ikinci dereceden zaman gerektirme olasılığını en aza indiren tasarım seçimleri yapmak mümkündür"
Jim Balter

5

Mevcut harika cevaplara QuickSort'un en iyi durumdan ayrılırken nasıl performans gösterdiğine ve bunun ne kadar olası olduğuna dair bazı matematik eklemek istiyorum, umarım insanların O (n ^ 2) durumunun neden gerçek olmadığını biraz daha iyi anlamalarına yardımcı olur. QuickSort'un daha karmaşık uygulamalarıyla ilgileniyor.

Rasgele erişim sorunlarının dışında, QuickSort'un performansını etkileyebilecek iki ana faktör vardır ve bunların her ikisi de, pivotun sıralanan verilerle nasıl karşılaştırıldığıyla ilgilidir.

1) Verilerdeki az sayıda anahtar. Aynı değerin tüm veri kümesi, pivot konumu dışındaki tüm değerlerin her seferinde bir tarafa yerleştirildiği için vanilya 2 bölümlü QuickSort'ta n ^ 2 kez sıralanır. Modern uygulamalar bunu 3 bölümlü sıralama gibi yöntemlerle ele alır. Bu yöntemler, O (n) zamanında aynı değere sahip bir veri kümesinde yürütülür. Yani böyle bir uygulamanın kullanılması, az sayıda tuşa sahip bir girdinin aslında performans süresini geliştirdiği ve artık endişe verici olmadığı anlamına gelir.

2) Son derece kötü pivot seçimi en kötü durum performansına neden olabilir. İdeal bir durumda, pivot her zaman verilerin% 50'si daha küçük ve% 50'si daha büyük olacak şekilde olacaktır, böylece giriş her yineleme sırasında yarıya bölünecektir. Bu bize O (n * logn) süresi için n karşılaştırmaları ve takas süreleri log-2 (n) özyineleme sağlar.

İdeal olmayan pivot seçimi yürütme süresini ne kadar etkiler?

Pivotun, verilerin% 75'inin pivotun bir tarafında olacağı şekilde sürekli olarak seçildiği bir durumu ele alalım. Hala O (n * logn) ama şimdi kütüğün tabanı 1 / 0.75 veya 1.33 olarak değişti. Tabanı değiştirirken performans ilişkisi her zaman log (2) / log (newBase) ile temsil edilen bir sabittir. Bu durumda, bu sabit 2.4'tür. Bu nedenle, bu pivot kalitesi kalitesi idealden 2.4 kat daha uzun sürer.

Bu ne kadar hızlı kötüleşiyor?

Pivot seçimi (sürekli olarak) çok kötü olana kadar çok hızlı değil:

  • Bir tarafta% 50: (ideal durum)
  • Bir tarafta% 75: 2.4 kat daha uzun
  • Bir tarafta% 90: 6.6 kat daha uzun
  • Bir tarafta% 95: 13,5 kat daha uzun
  • Bir tarafta% 99: 69 kat daha uzun

Bir tarafta% 100'e yaklaştıkça, yürütmenin log kısmı n'ye yaklaşır ve yürütmenin tamamı asimptotik olarak O (n ^ 2) 'ye yaklaşır.

QuickSort'un naif bir uygulamasında, sıralı dizi (1. öğe pivotu için) veya ters sıralı dizi (son öğe pivotu için) gibi durumlar en kötü durum O (n ^ 2) yürütme süresini güvenilir bir şekilde üretir. Ayrıca, öngörülebilir bir pivot seçimine sahip uygulamalar, en kötü durum yürütmesi üretmek için tasarlanan verilerle DoS saldırısına maruz kalabilir. Modern uygulamalar bunu, sıralamadan önce verileri rastgele seçmek, rastgele seçilen 3 indeksin medyanını seçmek gibi çeşitli yöntemlerle önler. Karışımdaki bu randomizasyon ile 2 vakamız var:

  • Küçük veri kümesi. En kötü durum makul olabilir ancak O (n ^ 2) felaket değildir çünkü n, n ^ 2'nin de küçük olacağı kadar küçüktür.
  • Büyük veri kümesi. En kötü durum teoride mümkündür ancak pratikte mümkün değildir.

Korkunç performans görme ihtimalimiz nedir?

Şansları kayboluyor . Bir çeşit 5.000 değeri ele alalım:

Varsayımsal uygulamamız, rastgele seçilen 3 endeksin medyanını kullanarak bir pivot seçecektir. % 25 -% 75 aralığında olan pivotları "iyi" ve% 0 -% 25 veya% 75 -% 100 aralığında olan pivotları "kötü" olarak değerlendireceğiz. 3 rastgele indeksin medyanını kullanarak olasılık dağılımına bakarsanız, her özyinelemenin 11/16 iyi bir pivot ile sonuçlanma şansı vardır. Matematiği basitleştirmek için 2 muhafazakar (ve yanlış) varsayım yapalım:

  1. İyi pivotlar her zaman tam olarak% 25 /% 75 oranındadır ve 2.4 * ideal durumda çalışır. 25/75'ten daha iyi bir bölünme veya bölünme elde edemeyiz.

  2. Kötü pivotlar her zaman en kötü durumdur ve özünde çözüme hiçbir şey katmazlar.

QuickSort uygulamamız n = 10'da duracak ve bir ekleme türüne geçecek, bu nedenle 5.000 değer girişini o ana kadar kırmak için 22% 25 /% 75 pivot bölümlere ihtiyacımız var. (10 * 1.333333 ^ 22> 5000) Veya 4990 en kötü durum pivotuna ihtiyacımız var. Herhangi bir noktada 22 iyi pivot biriktirirsek, türün tamamlanacağını, en kötü durumun veya yakınındaki herhangi bir şeyin son derece kötü şans gerektirdiğini unutmayın . Eğer n = 10 olarak sıralamak için gerekli 22 iyi pivotu elde etmek 88 özyinelememizi alırsa, bu 4 * 2.4 * ideal vaka veya ideal vakanın yürütme süresinin yaklaşık 10 katı olacaktır. Nasıl olasılıkla biz olduğunu ifade değil 88 recursions sonra gerekli 22 iyi pivotlar ulaşmak?

Binom olasılık dağılımları buna cevap verebilir ve cevap yaklaşık 10 ^ -18'dir. Kullanıcı 5.000 öğe sıralama çalıştırmanızı görme olasılığının daha yüksek o onlardan daha [SIRALAMA] tıkla alır ikinci 1'de yıldırım çarptı edilecek yaklaşık bin kat (n 88, k, s 0,6875 olan 21'dir) herhangi bir kötü 10'dan fazla * ideal durum. Veri kümesi büyüdükçe bu şans azalır. İşte bazı dizi boyutları ve 10 * idealden daha uzun çalışma şansları:

  • 640 öğeden oluşan dizi: 10 ^ -13 (60 denemeden 15 iyi pivot noktası gerektirir)
  • 5.000 öğeden oluşan dizi: 10 ^ -18 (88 denemeden 22 iyi pivot gerektirir)
  • 40.000 öğeden oluşan dizi: 10 ^ -23 (116 üzerinden 29 iyi pivot gerektirir)

Bunun, gerçeklikten daha kötü olan 2 muhafazakar varsayımla olduğunu unutmayın. Yani gerçek performans henüz daha iyi ve kalan olasılık dengesi ideale yakın değil.

Son olarak, diğerlerinin de belirttiği gibi, bu saçma sapan olası durumlar bile, özyineleme yığını çok derine inerse bir yığın türüne geçerek ortadan kaldırılabilir. Yani TLDR, QuickSort'un iyi uygulamaları için en kötü durumun gerçekte mevcut olmaması, çünkü tasarlanması ve yürütmenin O (n * logn) zamanında tamamlanmasıdır.


1
"mevcut büyük cevaplar" - bunlar hangileri? Onları bulamıyorum.
Jim Balter

Hızlı Sıralama varyasyonları, bölümler hakkında karşılaştırma işlevini, anahtarın önemli bir bölümünün bölümdeki tüm öğeler için aynı olacağı durumlardan yararlanmasına izin verecek şekilde bildirir mi?
supercat

4

Quicksort neden iyidir?

  • QuickSort en kötü durumda N ^ 2 ve ortalama NlogN durumundadır. En kötü durum veri sıralandığında ortaya çıkar. Bu, sıralama başlamadan önce rastgele karıştırma ile azaltılabilir.
  • QuickSort, birleştirme sıralaması tarafından alınan fazladan bellek almaz.
  • Veri kümesi büyükse ve aynı öğeler varsa, Quicksort'un karmaşıklığı 3 yollu bölüm kullanarak azalır. Daha fazla özdeş öğe daha iyi sıralama. Tüm öğeler özdeş ise, doğrusal zamana göre sıralar. [Bu, çoğu kütüphanedeki varsayılan uygulamadır]

Quicksort her zaman Mergesort'tan daha mı iyidir?

Pek sayılmaz.

  • Mergesort sabit, ancak Quicksort sabit değil. Dolayısıyla, çıktıda kararlılığa ihtiyacınız varsa Mergesort'u kullanırsınız. Birçok pratik uygulamada stabilite gereklidir.
  • Bellek günümüzde ucuz. Dolayısıyla, Mergesort tarafından kullanılan fazladan bellek uygulamanız için kritik değilse, Mergesort'u kullanmanın bir zararı yoktur.

Not: Java'da, Arrays.sort () işlevi, ilkel veri türleri için Quicksort'u ve nesne veri türleri için Mergesort'u kullanır. Nesneler bellek yükü tükettiğinden, Mergesort için biraz ek yük eklendiğinde, performans açısından herhangi bir sorun olmayabilir.

Referans : Coursera'daki Princeton Algoritmalar Kursu 3. Hafta QuickSort videolarını izleyin


"Bu sıralama başlamadan önce rastgele shuffle tarafından hafifletilebilir." - er, hayır, bu pahalı olurdu. Bunun yerine rasgele pivotlar kullanın.
Jim Balter

4

Quicksort birleşmeden daha iyi DEĞİLDİR. O (n ^ 2) ile (nadiren gerçekleşen en kötü durum), hızlı sıralama, birleştirme sıralamasının O (nlogn) değerinden çok daha yavaştır. Quicksort'un daha az yükü vardır, bu nedenle küçük n ve yavaş bilgisayarlarda daha iyidir. Ancak bilgisayarlar bugün o kadar hızlı ki, bir birleşmenin ek yükü ihmal edilebilir ve çok yavaş bir çabuk sıralama riski çoğu durumda bir birleşmenin önemsiz yükünden çok daha ağır basmaktadır.

Ek olarak, bir birleştirme, aynı anahtarlara sahip öğeleri orijinal sıralarında, kullanışlı bir özellik olarak bırakır.


2
İkinci cümleniz "... mergesort potansiyel olarak ... mergesort'tan çok daha yavaş" diyor. İlk referans büyük olasılıkla hızlı sıralama olmalıdır.
Jonathan Leffler

Birleştirme sıralaması yalnızca birleştirme algoritması kararlıysa sabittir; bu garanti edilmez.
Daha net

@Clearer Bunun <=yerine karşılaştırma için kullanılıp kullanılmadığı garanti edilir <ve yapılmaması için bir neden yoktur.
Jim Balter

@JimBalter Kararsız birleştirme algoritmasıyla kolayca karşılaşabilirim (örneğin, quicksort bu role hizmet eder). Hızlı sıralamanın birçok durumda birleştirme sıralamasından daha hızlı olmasının nedeni, genel giderlerin azalmasından değil , hızlı sıralamanın verilere nasıl erişmesinden kaynaklanmaktadır, bu da standart bir birleştirme işleminden çok daha önbellek dostudur.
Daha

@Clearer quicksort bir birleştirme türü değildir ... Yanıt verdiğim 21 Aralık 14'teki ifadeniz kesinlikle birleştirme sıralaması ve kararlı olup olmadığıyla ilgiliydi. quicksort ve hangisinin daha hızlı olduğu, yorumunuz veya yanıtımla hiç alakalı değil. Tartışmanın sonu benim için ... defalarca.
Jim Balter

3

Cevap, ilkel değerler için DualPivotQuickSort ile getirilen değişikliklere hafifçe doğru hızlı bir şekilde eğilir. Java.util.Arrays sıralamak için JAVA 7 kullanılır.

It is proved that for the Dual-Pivot Quicksort the average number of
comparisons is 2*n*ln(n), the average number of swaps is 0.8*n*ln(n),
whereas classical Quicksort algorithm has 2*n*ln(n) and 1*n*ln(n)
respectively. Full mathematical proof see in attached proof.txt
and proof_add.txt files. Theoretical results are also confirmed
by experimental counting of the operations.

JAVA7 uygulamasını burada bulabilirsiniz - http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/util/Arrays.java

DualPivotQuickSort ile ilgili daha fazla Harika Okuma - http://permalink.gmane.org/gmane.comp.java.openjdk.core-libs.devel/2628


3

Birleştirme sıralamasında genel algoritma:

  1. Sol alt diziyi sıralama
  2. Doğru alt diziyi sıralama
  3. Sıralanmış 2 alt diziyi birleştir

En üst düzeyde, 2 sıralı alt diziyi birleştirmek, N elemanları ile uğraşmayı içerir.

Bunun altında bir seviye, 3. adımdaki her yineleme, N / 2 elementleri ile uğraşmayı içerir, ancak bu işlemi iki kez tekrarlamanız gerekir. Yani hala 2 * N / 2 == N elementi ile uğraşıyorsun.

Bunun altında bir seviye, 4 * N / 4 == N öğelerini birleştiriyorsunuz vb. Özyinelemeli yığındaki her derinlik, bu derinlik için yapılan tüm çağrılarda aynı sayıda öğenin birleştirilmesini içerir.

Bunun yerine hızlı sıralama algoritmasını düşünün:

  1. Bir pivot noktası seçin
  2. Pivot noktasını, tüm küçük öğeler solda ve daha büyük öğeler sağda olacak şekilde dizideki doğru yere yerleştirin
  3. Sol alt diziyi sıralama
  4. Sağ alt diziyi sıralama

En üst düzeyde, N boyutunda bir dizi ile uğraşıyorsunuz. Sonra bir pivot noktası seçiyorsunuz, doğru pozisyonuna koyuyorsunuz ve daha sonra algoritmanın geri kalanı için tamamen görmezden gelebiliyorsunuz.

Bunun altında bir seviye, kombine boyutu N-1 olan 2 alt dizi ile uğraşıyorsunuz (yani, önceki pivot noktasını çıkartın). Her alt dizi için 2 ek pivot noktasına kadar gelen bir pivot noktası seçersiniz.

Bunun altında bir seviye, yukarıdakiyle aynı nedenlerle kombine N-3 boyutlu 4 alt dizi ile uğraşıyorsunuz.

Sonra N-7 ... Sonra N-15 ... Sonra N-32 ...

Özyinelemeli yığının derinliği yaklaşık olarak aynı kalır (logN). Birleştirme sıralamasıyla, yinelemeli yığının her düzeyinde her zaman bir N öğesi birleştirme ile uğraşırsınız. Bununla birlikte, hızlı sıralama ile, yığının altına inerken uğraştığınız öğelerin sayısı azalır. Örneğin, özyinelemeli yığının ortasındaki derinliğe bakarsanız, uğraştığınız öğelerin sayısı N - 2 ^ ((logN) / 2)) == N - sqrt (N) olur.

Feragatname: Birleştirme sıralamasında, diziyi her seferinde tam olarak eşit 2 parçaya böldüğünüz için, yinelemeli derinlik tam olarak logN'dir. Hızlı sıralamada, pivot noktanızın tam olarak dizinin ortasında olması mümkün olmadığından, özyinelemeli yığının derinliği logN'den biraz daha büyük olabilir. Bu faktörün ve yukarıda açıklanan faktörün aslında algoritmanın karmaşıklığında ne kadar büyük bir rol oynadığını görmek için matematik yapmadım.


Pivotların bir sonraki seviyedeki türlerin bir parçası olmaması, QS'nin daha performanslı olmasının nedeni değildir. Ek bilgi için diğer yanıtlara bakın.
Jim Balter

@JimBalter Hangi "diğer cevaplara" atıfta bulunuyorsunuz? Üst yanıt sadece QS'nin "az ek alan gerektirdiğini ve iyi bir önbellek yeri sergilediğini" söylüyor ancak bunun neden olduğu veya herhangi bir alıntı sağlamadığı konusunda hiçbir açıklama yapmadı. 2. cevap basitçe birleştirme-sıralamanın daha büyük veri setleri için daha iyi olduğunu söylüyor
RvPr

Kale direklerini, QS'nin neden daha performans gösterdiğinden, nasıl çalıştığı hakkında temel gerçekleri açıklamaya taşıyorsunuz. Diğer soruların cevapları bunu yapar: stackoverflow.com/questions/9444714/… ... Umarım bu sizin için yeterlidir; Daha fazla cevap vermeyeceğim.
Jim Balter

3

Birleştirme Sıralamasının aksine Hızlı Sıralama yardımcı bir alan kullanmaz. Oysa Merge Sort yardımcı alanı O (n) kullanır. Ancak Birleştirme Sıralaması O (nlogn) en kötü durum karmaşıklığına sahipken, Hızlı Sıralama en kötü durum karmaşıklığı O (n ^ 2) 'dir ve dizi zaten sıralandığında gerçekleşir.


Hayır, pivot olarak ilk veya son öğeyi kullanmadığınız sürece dizi zaten sıralandığında QuickSort'un en kötü durumu gerçekleşmez, ancak kimse bunu yapmaz.
Jim Balter

2

Quicksort daha iyi bir ortalama kasa karmaşıklığına sahiptir, ancak bazı uygulamalarda yanlış seçimdir. Quicksort, hizmet reddi saldırılarına karşı savunmasızdır. Bir saldırgan sıralanacak girdiyi seçebilirse, o (n ^ 2) 'nin en kötü zaman karmaşıklığını alan bir kümeyi kolayca oluşturabilir.

Mergesort'un ortalama vaka karmaşıklığı ve en kötü vaka karmaşıklığı aynıdır ve bu nedenle aynı problemi yaşamaz. Birleştirme sıralamasının bu özelliği, onu gerçek zamanlı sistemler için üstün bir seçim haline getirir - tam da çok daha yavaş çalışmasına neden olan patolojik durumlar olmadığı için.

Mergesort'un Quicksort'tan daha büyük bir hayranıyım, bu nedenlerden dolayı.


2
Quicksort'un ortalama vaka karmaşıklığı nasıl daha iyi? İkisi de O (nlgn). Saldırganın herhangi bir sıralama algoritmasına girdi sağlamayacağını iddia ediyorum ... ama belirsizliği güvenlik altına almamak için yapabileceğini varsayalım. N ^ 2 çalışma süresi nlgn'den daha kötü olsa da, bir web sunucusunun tek bir saldırıya göre çökmesi yeterince kötü değildir. Aslında, DOS argümanı hemen hemen boştur, çünkü herhangi bir web sunucusu bir DDOS saldırısına karşı savunmasızdır ve bir saldırganın dağıtılmış bir ana bilgisayar ağını, tüm TCP SYN selini kullanması daha olasıdır.
CaTalyst.X

"Quicksort daha iyi bir ortalama kasa karmaşıklığına sahiptir" - hayır değildir.
Jim Balter

2

Bunu söylemek zor. MergeSort'un en kötüsü, n (log2n) -n + 1'dir, bu da n 2 ^ k'ye eşitse (bunu zaten kanıtladım). Ve herhangi bir n için, (n lg n - n + 1) ve (n lg n + n + O (lg n)). Ancak quickSort için en iyisi nlog2n (ayrıca n eşittir 2 ^ k). Mergesort'u quickSort'a böldüğünüzde, n sonsuz olduğunda bire eşittir. MergeSort'un en kötü vakası QuickSort'un en iyi vakasından daha iyidir, neden quicksort kullanıyoruz? Ama unutmayın, MergeSort yerinde değil, 2n memeroy alanı gerektirir.Ve MergeSort'un da birçok dizi kopyası yapması gerekiyor. Bir kelimede, MergeSort, theroy'daki quicksort'tan gerçekten daha cezbedicidir, ancak gerçekte memeory alanını, dizi kopyasının maliyetini, birleşme hızlı sıralamadan daha yavaştır. rastgele sınıf tarafından java 1000000 basamak verildi deney,ve mergesort ile 2610ms, çabuksort ile 1370ms aldı.


2

Hızlı sıralama en kötü durum O (n ^ 2) olmakla birlikte, ortalama durum sürekli olarak birleştirme sıralaması gerçekleştirir. Her algoritma O (nlogn) 'dur, ancak Büyük O hakkında konuşurken daha düşük karmaşıklık faktörlerini bıraktığımızı hatırlamanız gerekir. Hızlı sıralama, sabit faktörler söz konusu olduğunda, birleştirme sıralamasında önemli gelişmeler gösterir.

Birleştirme sıralaması ayrıca O (2n) bellek gerektirirken hızlı sıralama yapılabilir (yalnızca O (n) gerektirir). Bu, hızlı sıralamanın genellikle birleştirme sıralamasına göre tercih edilmesinin bir başka nedenidir.

Fazladan bilgi:

En hızlı hızlı sıralama durumu, pivot kötü seçildiğinde ortaya çıkar. Aşağıdaki örneği düşünün:

[5, 4, 3, 2, 1]

Pivot gruptaki en küçük veya en büyük sayı olarak seçilirse, hızlı sıralama O (n ^ 2) olarak çalışır. Listenin en büyük veya en küçük% 25'inde bulunan öğeyi seçme olasılığı 0.5'tir. Bu algoritmaya iyi bir pivot olma 0.5 şansı verir. Tipik bir pivot seçme algoritması kullanırsak (rastgele bir eleman seçerek), pivotun her seçimi için iyi bir pivot seçme 0.5 şansımız vardır. Büyük boyutlu koleksiyonlar için her zaman kötü bir pivot seçme olasılığı 0.5 * n'dir. Bu olasılığı temel alarak hızlı sıralama ortalama (ve tipik) durum için etkilidir.


O (2n) == O (n). Doğru ifade, Mergesort'un O (n) ek belleğe ihtiyaç duymasıdır (daha spesifik olarak n / 2 yardımcı belleğe ihtiyaç duyar). Ve bu bağlantılı listeler için geçerli değil.
Jim Balter

@JimBalter Efendim, sorunun cevabı olarak performanslarıyla ilgili parlak ve değerli fikirlerinizi bizimle paylaşır mısınız? Şimdiden teşekkürler.
snr

2

Bu oldukça eski bir soru, ama son zamanlarda burada ele aldığımdan beri benim 2c:

Birleştirme sıralama ortalama ~ N log N karşılaştırmaları gerekir. Zaten (neredeyse) sıralanmış diziler için bu 1/2 N log N'ye iner, çünkü birleştirme sırasında (neredeyse) her zaman "sol" kısmı 1/2 N kez seçeriz ve sonra sadece sağ 1/2 N elemanlarını kopyalarız. Buna ek olarak, zaten sıralanmış girdinin işlemcinin dal tahmincisinin parlamasını sağladığını, ancak neredeyse tüm dalları doğru tahmin ettiğini ve böylelikle boru hattı duraklarını önlediğini tahmin edebilirim.

Ortalama hızlı sıralama için ~ 1.38 N log N karşılaştırması gerekir. Karşılaştırmalar açısından zaten sıralanmış diziden çok fazla fayda sağlamaz (ancak swaplar ve muhtemelen CPU içindeki şube tahminleri açısından).

Oldukça modern işlemcideki kriterlerim şunları gösteriyor:

Karşılaştırma işlevi bir geri çağırma işlevi olduğunda (qsort () libc uygulamasında olduğu gibi) hızlı sıralama, birleştirme işleminden rastgele girişte% 15 ve 64 bit tamsayılar için zaten sıralanmış dizi için% 30 daha yavaştır.

Öte yandan, karşılaştırma bir geri arama değilse, deneyimlerim, quicksort'un% 25'e kadar birleştirme performansından daha iyi performans göstermesidir.

Ancak (büyük) dizinizin çok az benzersiz değeri varsa, birleştirme sıralaması her durumda quicksort üzerinden kazanmaya başlar.

Yani belki de sonuç şu: eğer karşılaştırma pahalıysa (örneğin geri arama fonksiyonu, dizeleri karşılaştırma, bir yapının birçok parçasını karşılaştırmak çoğunlukla fark yaratmak için "if" ise "ikinci" bir üçüncü-dördüncü) - şansınız daha iyi olmanızdır birleştirme sıralama ile. Daha basit görevler için hızlı sıralama daha hızlı olacaktır.

Daha önce söylenenlerin hepsi doğrudur: - Quicksort N ^ 2 olabilir, ancak Sedgewick iyi bir rastgele uygulamanın N ^ 2'den ziyade yıldırım çarpması gibi bir bilgisayar yapma şansının daha yüksek olduğunu iddia ediyor - Mergesort ekstra alan gerektiriyor


Karşılaştırma ucuzsa qsort sıralı girdiler için bile birleştirme yapar mı?
Eonil

2

Her iki sıralama algoritmasını da denediğimde, yinelemeli çağrıların sayısını sayarak, quicksort sürekli olarak birleştirme işleminden daha az yinelemeli çağrılara sahiptir. Bunun nedeni, quicksort'un pivotları olması ve pivotların bir sonraki özyinelemeli çağrılara dahil edilmemesidir. Bu şekilde quicksort, yinelemeli temel duruma birleştirme işleminden daha hızlı ulaşabilir.


Pivotların QS'nin neden daha az yinelemeli çağrıya sahip olduğu ile ilgisi yoktur ... QS'nin özyinelemesinin yarısının ortadan kaldırılabilen kuyruk özyineleme olmasıdır.
Jim Balter

2

Bu, görüşmelerde, birleştirme sıralamasının en kötü durum performansına rağmen, çabuk sıralamanın birleştirme sıralamasından daha iyi olduğu, özellikle de büyük bir girdi için sorulan yaygın bir sorudur. Quicksort'un daha iyi olmasının belirli nedenleri vardır:

1- Yardımcı Alan: Hızlı sıralama, yerinde bir sıralama algoritmasıdır. Yerinde sıralama, sıralama için ek depolama alanı gerekmediği anlamına gelir. Öte yandan birleştirme sıralaması, sıralanan dizileri birleştirmek için geçici bir dizi gerektirir ve bu nedenle yerinde değildir.

2- En kötü durum: En hızlı quicksort durumu O(n^2)randomize quicksort kullanılarak önlenebilir. Doğru pivot seçilerek yüksek olasılıkla kolayca önlenebilir. Doğru pivot öğesini seçerek ortalama bir vaka davranışı elde etmek, performansı iyileştirmeyi ve Birleştirme sıralaması kadar verimli olmasını sağlar.

3- Referans yeri: Özellikle Quicksort, önbellek yerleşiminin iyi olduğunu gösterir ve bu, sanal bellek ortamında olduğu gibi birçok durumda birleştirme işleminden daha hızlı olmasını sağlar.

4- Kuyruk özyineleme: Birleştirme sıralaması yapılmazken QuickSort kuyruk özyinelemelidir. Kuyruk özyinelemeli işlev, özyinelemeli çağrının işlev tarafından yürütülen son şey olduğu bir işlevdir. Kuyruk özyinelemeli fonksiyonlar kuyruk özyinelemeli fonksiyonlardan daha iyi kabul edilir, çünkü kuyruk özyineleme derleyici tarafından optimize edilebilir.


1

İkisi de aynı karmaşıklık sınıfında olsalar da, her ikisinin de aynı çalışma süresine sahip oldukları anlamına gelmez. Quicksort genellikle sıkı bir uygulamadan daha hızlıdır, çünkü sıkı bir uygulamayı kodlamak daha kolaydır ve yaptığı işlemler daha hızlı olabilir. Çünkü hızlı sıralama, insanların birleştirme yerine onu kullanması genellikle daha hızlıdır.

Ancak! Şahsen ben quicksort kötü olduğunda birleştirme veya ayrıştırma için degrade olan bir quicksort varyant kullanacağım. Hatırlamak. Quicksort sadece O (n log) üzerinde ortalama . En kötü durum O (n ^ 2)! Birleştirme her zaman O (n log n) olur. Gerçek zamanlı performansın veya yanıt vermenin bir zorunluluk olduğu ve giriş verilerinizin kötü amaçlı bir kaynaktan gelebileceği durumlarda, düz hızlı sıralama kullanmamalısınız.


1

Her şey eşit olduğunda, çoğu insanın en uygun olanı kullanmasını beklerdim ve bu da qsort olma eğilimindedir (3). Bunun dışında quicksort'un dizilerde çok hızlı olduğu bilinmektedir, tıpkı birleştirme için listeler için ortak seçimdir.

Merak ettiğim şey, neden yarıçap veya kepçe türünü görmek için bu kadar nadir olduğu . O (n), en azından bağlantılı listelerde ve tek yapmanız gereken anahtarı sıra numarasına dönüştürmek için bir yöntem. (teller ve şamandıralar iyi çalışır.)

Bunun nedeninin bilgisayar biliminin öğretilmesiyle ilgili olduğunu düşünüyorum. Algoritma analizinde öğretim üyeme bile O (n log (n)) 'dan daha hızlı sıralamanın mümkün olduğunu göstermek zorunda kaldım. (O kanıt vardı can not karşılaştırma sıralama daha hızlı doğrudur O (n log ()), daha.)

Diğer yandan şamandıralar tamsayı olarak sıralanabilir, ancak daha sonra negatif sayıları çevirmeniz gerekir.

Düzenleme: Aslında, tamsayı olarak kayan nokta sıralamak için daha da kısır bir yoludur: http://www.stereopsis.com/radix.html . Bit sayma numarasının, hangi sıralama algoritmasını kullandığınızdan bağımsız olarak kullanılabileceğini unutmayın ...


1
Yarıçap türlerinden payımı gördüm. Ancak kullanımı oldukça zordur çünkü doğru analiz edilirse, çalışma zamanı giriş elemanlarının sayısından daha fazlasına bağlı olduğu için O (n) değildir . Genel olarak, sayı tabanı sıralamasının girdi hakkında verimli olması gerektiği gibi güçlü tahminler yapmak çok zordur.
Konrad Rudolph

Bu bir O (n), burada n , toplam elemanların boyutu da dahil olmak üzere, bir giriş boyutu. Uygulayabileceğiniz doğrudur, bu nedenle çok fazla sıfır ile doldurmanız gerekir, ancak karşılaştırma için zayıf bir uygulama kullanmak saçmadır. (Bu, uygulamanın zor olabileceğini söyledi, ymmv.)
Anders Eurenius

GNU libc kullanıyorsanız qsort, bir birleştirme türü olduğunu unutmayın.
Jason Orendorff

Er, kesin olarak, gerekli geçici bellek tahsis edilemediği sürece bir birleştirme sıralamasıdır. cvs.savannah.gnu.org/viewvc/libc/stdlib/…
Jason Orendorff

1

Hızlı ve birleştirme türlerine küçük eklemeler.

Ayrıca tür sıralama öğeleri bağlı olabilir. Öğelere, takas ve karşılaştırmalara erişim, düzlem belleğindeki tamsayıları karşılaştırmak gibi basit işlemler değilse, birleştirme sıralaması tercih edilen algoritma olabilir.

Örneğin, öğeleri uzak sunucudaki ağ protokolünü kullanarak sıralarız.

Ayrıca, "bağlantılı liste" gibi özel kaplarda, hızlı sıralama avantajı yoktur.
1. Bağlantılı listede birleştirme sıralaması, ek bellek gerekmez. 2. Hızlı sıralamadaki öğelere erişim sıralı değildir (bellekte)


0

Hızlı sıralama, yerinde bir sıralama algoritmasıdır, bu nedenle diziler için daha uygundur. Öte yandan birleştirme sıralaması O (N) 'nin fazladan depolanmasını gerektirir ve bağlantılı listeler için daha uygundur.

Dizilerden farklı olarak, sevilenler listesine ortadaki öğeleri O (1) boşluk ve O (1) süre ile ekleyebiliriz, bu nedenle birleştirme sıralamasında birleştirme işlemi fazladan boşluk olmadan uygulanabilir. Bununla birlikte, diziler için fazladan alan ayırma ve ayırma, birleştirme sıralamasının çalışma süresi üzerinde olumsuz bir etkiye sahiptir. Birleştirme sıralaması, verilere rasgele bellek erişimi olmadan sıralı olarak erişildiğinden bağlantılı listeyi de tercih eder.

Öte yandan hızlı sıralama çok fazla rastgele bellek erişimi gerektirir ve bir dizi ile bağlantılı listelerin gerektirdiği şekilde herhangi bir geçiş yapmadan doğrudan belleğe erişebiliriz. Ayrıca diziler için kullanıldığında hızlı sıralama, diziler bitişik olarak bellekte saklandığından iyi bir referans mevkisine sahiptir.

Her iki sıralama algoritması ortalama karmaşıklığı O (NlogN) olmasına rağmen, genellikle sıradan görevler için insanlar depolama için bir dizi kullanır ve bu nedenle hızlı sıralama tercih edilen algoritma olmalıdır.

EDIT: Ben sadece birleştirme sıralama en kötü / en iyi / avg durumda her zaman nlogn olduğunu, ancak hızlı sıralama n2 (öğeler zaten sıralanmış en kötü durumda) nlogn (avg / en iyi durumda pivot diziyi her zaman ikiye böldüğünden farklı olabilir yarılar).


0

Her ikisini de zaman ve mekan karmaşıklığını düşünün. Birleştirme sıralaması için: Zaman karmaşıklığı: O (nlogn), Uzay karmaşıklığı: O (nlogn)

Hızlı sıralama için: Zaman karmaşıklığı: O (n ^ 2), Alan karmaşıklığı: O (n)

Şimdi, her ikisi de birer sahnede kazanıyor. Ancak, rastgele bir pivot kullanarak, Hızlı sıralama Zaman karmaşıklığını neredeyse her zaman O (nlogn) olarak azaltabilirsiniz.

Bu nedenle, Hızlı sıralama, Birleştirme sıralaması yerine birçok uygulamada tercih edilir.


-1

C / c ++ topraklarında, stl kapları kullanılmadığında, birleştirme sıra değilken, çalışma süresine dahil olduğu için quicksort kullanma eğilimindeyim.

Bu yüzden birçok durumda, bunun sadece en az direniş yolu olduğuna inanıyorum.

Ayrıca, tüm veri kümesinin çalışma setine uymadığı durumlarda hızlı sıralama ile performans çok daha yüksek olabilir.


3
Aslında, bahsettiğiniz qsort () kitaplığı işlevi ise, quicksort olarak uygulanabilir veya uygulanmayabilir.
Thomas Padron-McCarthy

3
Konrad, bu konuda biraz anal olduğum için üzgünüm, ama bu garantiyi nerede buluyorsun? ISO C standardında veya C ++ standardında bulamıyorum.
Thomas Padron-McCarthy

2
GNU libc's qsort, öğelerin sayısı gerçekten devasa veya geçici bellek tahsis edilemediği sürece bir birleştirme türüdür. cvs.savannah.gnu.org/viewvc/libc/stdlib/…
Jason Orendorff

-3

Sebeplerden biri daha felsefi. Quicksort, Top-> Down felsefesidir. Sıralanacak n öğeyle n var! olasılık. M & nm'nin birbirini dışlayan 2 bölümü ile, olasılıkların sayısı birkaç büyüklükte azalır. m! * (nm)! n'den birkaç sipariş daha küçüktür! tek başına. 5 hayal et! 3'e karşı! * 2 !. 5! her biri 2 & 3'lük 2 bölümden 10 kat daha fazla olanak sunar. ve 900 milyona karşı 1 milyon faktöriyete ekstrapole edin! * 100K! Bu nedenle, bir aralık veya bölüm içinde herhangi bir düzen oluşturma konusunda endişelenmek yerine, bölümlerde daha geniş bir düzeyde düzen oluşturun ve bölüm içindeki olasılıkları azaltın. Bir aralık içinde daha önce belirlenen herhangi bir sipariş, bölümler birbirini karşılıklı olarak dışlamazsa, daha sonra bozulacaktır.

Birleştirme sıralaması veya yığın sıralaması gibi herhangi bir aşağıdan yukarıya yaklaşım yaklaşımı, bir çalışanın veya çalışanın mikroskobik düzeyde erken karşılaştırmaya başladığı bir yaklaşıma benzer. Ancak bu düzen, aralarında bir unsur daha sonra bulunur bulunmaz kaybolmak zorundadır. Bu yaklaşımlar çok kararlı ve son derece öngörülebilirdir, ancak belirli bir miktar ekstra iş yaparlar.

Hızlı Sıralama, herhangi bir siparişle ilgili olarak başlangıçta endişe duyulmayan, yalnızca Siparişe saygı yok ile geniş bir kriteri karşılama konusunda Yönetsel yaklaşım gibidir. Ardından, sıralı bir küme elde edilene kadar bölümler daraltılır. Quicksort'taki asıl zorluk, sıralanacak unsurlar hakkında hiçbir şey bilmediğinizde karanlıkta bir bölüm veya kriter bulmaktır. Bu yüzden ya bir ortanca değer bulmak için biraz çaba harcamamız ya da rastgele ya da keyfi "Yönetsel" bir yaklaşımla 1'i seçmemiz gerekir. Mükemmel bir medyan bulmak önemli ölçüde çaba harcayabilir ve tekrar aptal bir aşağıdan yukarıya yaklaşıma yol açabilir. Bu yüzden Quicksort sadece rastgele bir pivot seç ve ortada bir yerde olacağını veya daha iyi bir medyan bulmak için 3, 5 veya daha fazla medyan bulmak için biraz iş yapacağını umuyor ama mükemmel olmayı planlamıyor ' t İlk siparişte zaman kaybetmeyin. Eğer şanslıysanız ya da bir medyan almadığınızda bazen sadece bir şansınız olduğunda n ^ 2'ye düşer. Herhangi bir şekilde veri rastgele. sağ. Bu yüzden hızlı - üst mantıksal mantıksal yaklaşımın üst mantıksal yaklaşımına daha fazla katılıyorum ve daha önce kaydettiği pivot seçimi ve karşılaştırmaları ile ilgili şansın, herhangi bir titiz ve kapsamlı istikrarlı alttan daha iyi çalıştığı görülüyor -> yukarı yaklaşım birleştirme sıralaması. Fakat daha önce kaydettiği karşılaştırmalar, birleştirme sıralaması gibi titiz ve kapsamlı sabit dip -> yaklaşımından daha iyi çalışıyor gibi görünüyor. Fakat daha önce kaydettiği karşılaştırmalar, birleştirme sıralaması gibi titiz ve kapsamlı sabit dip -> yaklaşımından daha iyi çalışıyor gibi görünüyor. Fakat


quicksort, pivot seçiminin rasgeleliğinden yararlanır. Rastgele pivot doğal olarak 50:50 bölünmeye eğilimlidir ve sürekli olarak aşırı uçlardan birine doğru olma olasılığı düşüktür. Nlogn sabit faktörü, ortalama bölümleme 60-40 olana kadar ve hatta 70-30'a kadar oldukça düşüktür.
Kış Kavun

Bu tam bir saçmalık. quicksort "felsefe" değil performansı nedeniyle kullanılır ... "düzen kaybolmak zorundadır" iddiaları yanlıştır.
Jim Balter
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.