Her bir sıralama algoritması ne zaman kullanılır? [kapalı]


170

Belirli bir sıralama algoritmasının diğerlerine göre tercih edilmesi durumunda kullanım durumları nelerdir - merge sort vs QuickSort vs heapsort vs 'intro sort' vs.

Bunların boyutu, veri yapısı türü, kullanılabilir bellek ve önbellek ve CPU performansına göre kullanılması için önerilen bir kılavuz var mı?


Farklı veri ve algoritma türleri için bir dizi animasyon <a href=" sorting-algorithms.com/"> sorting-algorithms.com </ a > adresinde bulunabilir
Chip Uni

2
Bu şey için bigocheatsheet.com gibi bir rehber greaaaat
K - SO Zehirliliği artıyor.

@ChipUni İşte sabit bağlantı: toptal.com/developers/sorting-algorithms
eric

2
Bu soru neden kapalı !?
Arvand

Yanıtlar:


316

Birincisi, bir tanım, çünkü oldukça önemli: Kararlı bir sıralama , öğeleri aynı anahtarlarla yeniden düzenlememeyi garanti eden bir sıralamadır.

öneriler:

Hızlı sıralama: Sabit bir sıralama ve ortalama vaka performansına ihtiyacınız olmadığında, en kötü vaka performansından daha önemlidir. Hızlı sıralama ortalama O (N log N), en kötü durumda O (N ^ 2) 'dir. İyi bir uygulama, özyineleme için yığın alanı şeklinde O (log N) yardımcı depolamayı kullanır.

Birleştirme sıralaması: Kararlı bir O (N log N) sıralamasına ihtiyacınız olduğunda, bu tek seçeneğinizle ilgilidir. Bunun tek dezavantajı, O (N) yardımcı alanı kullanması ve hızlı bir sıralamadan biraz daha büyük bir sabite sahip olmasıdır. Bazı yerinde birleştirme türleri vardır, ancak AFAIK bunların hepsi O (N log N) 'den daha kararlı veya daha kötü değildir. Yerinde sıralanan O (N log N) bile, düz eski birleştirme türünden çok daha büyük bir sabite sahiptir ve kullanışlı algoritmalardan daha teorik meraklardır.

Yığın sıralaması: Sabit bir sıralamaya ihtiyacınız olmadığında ve ortalama durum performansından daha kötü durum performansına daha fazla önem verdiğinizde. O (N log N) olması garanti edilir ve O (1) yardımcı alan kullanır, yani çok büyük girişlerde beklenmedik bir şekilde yığın veya yığın alanınız tükenmez.

Introsort: Bu, hızlı sıralamanın O (N ^ 2) en kötü durumunda dolaşmak için belirli bir özyineleme derinliğinden sonra yığın sıralamasına geçen hızlı bir sıralamadır. Garantili O (N log N) performansı ile ortalama hızlı bir sıralama elde ettiğiniz için, neredeyse her zaman sade eski bir hızlı sıralamadan daha iyidir. Muhtemelen bunun yerine bir yığın sıralaması kullanmanın tek nedeni, O (log N) yığın alanının pratik olarak önemli olduğu ciddi şekilde bellek kısıtlı sistemlerde olmasıdır.

Ekleme sıralaması : Hızlı sıralama veya birleştirme sıralamasının temel durumu da dahil olmak üzere N'nin küçük olacağı garanti edildiğinde. Bu O (N ^ 2) olsa da, çok küçük bir sabiti vardır ve kararlı bir çeşittir.

Kabarcık sıralaması, seçim sıralaması : Hızlı ve kirli bir şey yaptığınızda ve bir nedenden dolayı standart kütüphanenin sıralama algoritmasını kullanamazsınız. Bunların aşırı yerleştirme türüne sahip olmasının tek avantajı uygulanması biraz daha kolay olmasıdır.


Karşılaştırılmayan türler: Bazı oldukça sınırlı koşullar altında O (N log N) bariyerini kırmak ve O (N) cinsinden sıralamak mümkündür. İşte denemeye değer bazı durumlar:

Sayma sıralaması: Sınırlı bir aralığa sahip tam sayıları sıralarken.

Radix sıralaması: Log (N) K'den önemli ölçüde daha büyük olduğunda, burada K sayı tabanı basamak sayısıdır.

Kepçe sıralaması: Girişinizin yaklaşık olarak eşit olarak dağıtıldığını garanti edebildiğinizde.


1
Hatırladığım gibi, yığın sıralaması da aynı boyutta farklı girdiler arasında çok az değişiklik olması nedeniyle çok öngörülebilir bir çalışma süresine sahiptir, ancak bu, sabit alan bağlı olandan daha az ilgi çekicidir. Ben de n ^ 2 tür uygulamak için en kolay ekleme sıralama bulabilirsiniz, ama belki bu sadece benim. Son olarak, yerleştirme sıralaması gibi uygulanması neredeyse basit olan ancak yine de n log n olmasa da daha iyi performansa sahip olan Shell sıralamasından da bahsetmek isteyebilirsiniz.
JaakkoK

29
Bogosort'u unutma ! ;-)
Alex Brasetvik

2
+1 Çok ilginç. "Nasıl ... yaklaşık olarak eşit olarak dağıtıldığını" nasıl garanti edebileceğinizi açıklamak ister misiniz? Bucket Sort için mi?
Sam Overton

2
Introsort neden hızlı sıralamadan önemli ölçüde daha yavaş olur? Tek ek yük, ihmal edilebilir olması gereken özyineleme derinliğini saymaktır. Sadece özyineleme, iyi bir hızlı sıralama durumunda olması gerekenden çok daha derin olduktan sonra değişir.
dsimcha

2
En iyi kabarcık türünün O (n) olduğunu söyleyemezsiniz!
Tara

33

Quicksort genellikle ortalama olarak en hızlıdır , ancak bazı kötü kötü durum davranışları vardır. Bu nedenle, size kötü verilerin verilmediğini garanti O(N^2)etmeniz gerekiyorsa, bundan kaçınmalısınız.

Birleştirme sıralaması fazladan bellek kullanır, ancak özellikle harici sıralamaya (örn. Belleğe sığmayan büyük dosyalar) uygundur.

Yığın sıralama yerinde sıralanabilir ve en kötü durumda ikinci dereceden davranışa sahip değildir, ancak çoğu durumda ortalama olarak hızlı sıralamadan daha yavaştır.

Yalnızca sınırlı bir aralıktaki tamsayıların yer aldığı yerlerde, onu çok hızlı yapmak için bir tür sayı tabanı sıralaması kullanabilirsiniz.

Vakaların% 99'unda, genellikle hızlı sıralamaya dayanan kütüphane türlerinde iyi olacaksınız.


6
+1: "Vakaların% 99'unda, genellikle hızlı sıralamaya dayanan kütüphane türlerinde sorun yaşarsınız".
Jim

Rastgele döndürme, Quicksort'a tüm pratik amaçlar için kötü verilerle ilgili herhangi bir garanti vermeden O (nlogn) çalışma zamanı verir. Gerçekten kimsenin herhangi bir üretim kodu için O (n ^ 2) quicksort uyguladığını sanmıyorum.
MAK

2
MAK, C standart kütüphanesi qsort hariç? ( google.com/codesearch/… ) - "üretim kodu"
nun çoğunun

Kütüphane sıralaması genellikle hızlı sıralamaya dayanmaz, çünkü kararlı değildir. Hemen hemen tüm yüksek diller (C için bekliyoruz) istikrarlı bir sıralama sağlar. Çoğu durumda kararlı ya da en azından deterministik bir çeşit gerektiğini biliyorum.
12431234123412341234123


3

Karşılaştırmalar / animasyonlar için sağlanan bağlantıların dikkate almadığı şey, veri miktarının kullanılabilir belleği aşması --- bu noktada verilerin üzerinden geçiş sayısının, yani G / Ç maliyetlerinin çalışma zamanına hakim olmasıdır. Bunu yapmanız gerekiyorsa, genellikle birleştirme ve yığın çeşitlerini kapsayan "dış sıralama" konusunu okuyun.

http://corte.si/posts/code/visualisingsorting/index.html ve http://corte.si/posts/code/timsort/index.html ayrıca çeşitli sıralama algoritmalarını karşılaştıran harika görüntülere sahiptir.


0

@dsimcha şunu yazdı: Sayma sıralaması: Sınırlı bir aralığa sahip tamsayıları sıralarken

Bunu şu şekilde değiştirirdim:

Sayma sıralaması: Pozitif tamsayıları sıraladığınızda (0 - Pigeonhole nedeniyle tamsayı.MAX_VALUE-2).

Maksimum ve minimum değerleri her zaman doğrusal zamanda da sezgisel bir verimlilik olarak elde edebilirsiniz.
Ayrıca ara dizi için en az n fazladan alana ihtiyacınız var ve açıkça kararlı.

/**
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

(aslında MAX_VALUE-2'ye izin verse de) bkz: Java dizilerinin maksimum boyutu var mı?

Ayrıca kelime boyutu w tamsayıları n anahtarları için sayı tabanı sıralama karmaşıklığı O (wn) olduğunu açıklamak istiyorum. Bazen w sabit bir değer olarak sunulur, bu da sayı dizisini sıralamak için O (n log n) karşılaştırmaları yapan en iyi karşılaştırma tabanlı sıralama algoritmalarından daha fazla (yeterince büyük n için) sayı tabanı sıralaması yapar. Bununla birlikte, genel olarak w bir sabit olarak kabul edilemez: eğer tüm n anahtarları farklıysa, rasgele erişimli bir makinenin bellekte depolayabilmesi için w en azından log n olmalıdır, bu da en iyi zaman karmaşıklığını O sağlar. (n günlüğü n). (wikipedia'dan)

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.