Radix Sort neden daha sık kullanılmıyor?


31

Kararlı ve O (n) 'nin zaman karmaşıklığına sahip. Quicksort ve Mergesort gibi algoritmalardan daha hızlı olması gerekirdi;


2
Buraya bakın: en.wikipedia.org/wiki/Radix_sort#Efficiency Verimlilik O (kn) 'dir ve O (n * log (n))' den daha iyi olmayabilir.
SinirliFormsDesigner ile

2
Radix sıralama, oyunlar gibi yumuşak gerçek zamanlı sistemlerde sıklıkla kullanılır. Bir algoritmanın başka birinden daha iyi performans
gösterip göstermemesi

@FrustratedWithFormsDesigner Belki de wiki değişti? `N log (n) artık referansı göremiyorum , FWIW ...
rogerdpack

Boost'un bir (varyantı) çeşidi var: boost.org/doc/libs/1_62_0/libs/sort/doc/html/sort/sort_hpp.html ama evet, insanların var olduğunu bilmediklerini düşünüyorum ... ya o ya da hepsi sadece, “yaratıcı” sıralama algoritmasını kullanırlar, hangi nedenle olursa olsun, çerçeve oluşturucuları hala verimli olmayan “jenerik” türleri yeniden kullanma eğilimindedirler. genellikle, daha nadir bir kullanım durumunda olduğundan?
rogerdpack

Yanıtlar:


38

Radix sıralamadan farklı olarak, quicksort evrenseldir, radix sıralama ise yalnızca uzunluk uzunluğu tamsayı tuşları için kullanışlıdır.

Ayrıca, O (f (n)) gerçekten K * f (n) sırasının anlamını anlamalısınız, ki burada K bir keyfi sabittir. Yarıçapı sıralama için bu K oldukça büyük olur (sıralanan tamsayılardaki en az bit sayısı sırası), diğer yandan hızlı bağlantı noktası tüm sıralama algoritmaları ve n * log (n) 'nin ortalama karmaşıklığı arasında en düşük K değerine sahiptir. Böylece gerçek hayatta senaryoda quicksort, radix sıralamadan çok daha hızlı olacaktır.


Belirtilen karmaşıklığa dikkat edin: (LSD) Radix türünün O (n * K) karmaşıklığına sahip olmasına rağmen, bu sabit genellikle küçüktür, tipik olarak (2 ^ (W / K)) * C, L 'ye sığacak şekilde seçilir, burada C Sayacın bayt cinsinden büyüklüğüdür, W sıralanan anahtarın büyüklüğüdür. Çoğu uygulama, x86'daki 32 bit sözcükler için K = [3,4] öğesini seçer. K ayrıca, her bir yarıçap ayrı ayrı sıralandığı için, zamansal tutarlılıktan yararlanmak için uyarlanabilir (yakın sıralama).
awdz9nld

11
Evrensellik hakkında not: Radix sıralama, değişken uzunluklu tamsayı tuşlarının yanı sıra kayan noktalı tuşlar üzerinde de tam olarak çalışabilir
awdz9nld

20

Çoğu sıralama algoritması genel amaçlıdır. Bir karşılaştırma işlevi verildiğinde, herhangi bir şey üzerinde çalışırlar ve Quicksort ve Heapsort gibi algoritmalar O (1) ekstra bellek ile sıralanır.

Radix sıralama daha özeldir. Sözlük sırasına göre belirli bir anahtara ihtiyacınız var. Anahtardaki olası her sembol için bir kovaya ihtiyacınız vardır ve kovaların çok fazla kayıt tutması gerekir. (Alternatif olarak, mümkün olan her anahtar değeri tutacak büyük bir kova dizisine ihtiyacınız vardır.) Radix sıralaması yapmak için daha fazla hafızaya ihtiyacınız olacak ve rastgele kullanacaksınız. Bunların hiçbiri modern bilgisayarlar için iyi değildir, çünkü Quicksort gibi sayfa hataları alırsınız, önbellek hataları olur.

Son olarak, insanlar genel olarak artık kendi sıralama algoritmalarını yazmıyorlar. Çoğu dilde, sıralama yapmak için kütüphane olanakları bulunur ve yapılacak doğru şey normal olarak bunları kullanmaktır. Radix sıralama evrensel olarak uygulanabilir olmadığından, tipik olarak fiili kullanıma göre uyarlanmalı ve çok fazladan fazla bellek kullanması gerektiğinden, onu bir kütüphane işlevine veya şablona koymak zordur.


Aslında, hızlı bağlantı , sol ve sağ bölümlerdeki özyinelemeli çağrılar O(n^2)nedeniyle en kötü durumda bellek gerektirir n. Uygulama kuyruk özyineleme optimizasyonu kullanıyorsa O(n), doğru bölüme yapılan çağrılar için fazladan alan gerektirmeyeceği için düşürülebilir . ( en.wikipedia.org/wiki/Quicksort#Space_complexity )
Kaosun

Yalnızca S(n) \in O(n)sayı tabanı ile sıralama yapmak için boşluğa ihtiyacınız var , yani yığın veya hızlı sıralama için olduğu gibi.
Velda

@SplinterofChaos wiki belki de değişti? n^2Artık quicksort için bahsetmiyor gibi görünüyor , ama O(log n)...
rogerdpack

Sanırım "çok" daha fazla hafıza, belki 2 * n (Tamam, bu çok daha fazla ama belki imkansız değil)? Ve kovalar o kadar küçüktür (baytlara ayırdığınızı ve tekrarlayacağınızı varsayarak) önbelleğe sığabileceğini mi düşünüyorsunuz?
rogerdpack

5

Sıraladığınız anahtarların bilinen, seyrek bir aralıktaki tamsayılar olması oldukça nadirdir. Genelde karşılaştırmalı olmayan sıralamaları destekleyecek gibi görünen alfabetik alanlara sahipsiniz , ancak gerçek dünya dizeleri alfabeye eşit dağılmadığından, teoride olması gerektiği gibi çalışmaz.

Diğer zamanlarda, ölçüt yalnızca operasyonel olarak tanımlanır (iki kayıt verildiğinde hangisinin önce geleceğine karar verebilirsiniz, ancak izole edilmiş bir kaydın ölçeğinin ne kadar “aşağı” olduğunu değerlendiremezsiniz). Bu nedenle yöntem genellikle uygulanabilir değildir, inandığınızdan daha az uygulanabilir veya O (n * log (n)) 'den daha hızlı değildir.


Bunlar bir seyrek aralıkta FWIW olmak zorunda kalmamak için basamağa göre sıralama ... yinelemeli "bir anda bir byte" bunları sıralayarak herhangi aralığında tamsayılar (veya dizeleri) işleyebilir
rogerdpack

4

Ben her zaman, aslında karşılaştırmaya dayalı çeşitlerden daha fazla kullanıyorum, ama kuşkusuz sayısız şeyle her şeyden daha çok işe yarayan bir tuhaflık yapıyorum (neredeyse hiç dizelerle çalışıyorum, ve eğer genellikle eğer bu noktada yarıçapı Sıralama tekrarları filtrelemek ve küme kesişimlerini hesaplamak için tekrar yararlı olabilir; pratik olarak asla sözlükbilimsel karşılaştırmalar yapmam).

Temel bir örnek, arama veya medyan bölünmenin bir parçası olarak belirli bir boyuta göre radix sıralama noktaları veya çakışan noktaları, derinlik sıralama fragmanlarını tespit etmek için hızlı bir yol veya daha fazla önbellek dostu erişim sağlamak için birden fazla döngüde kullanılan bir indeks dizisini sıralamadır. modeller (yalnızca tekrar geri gitmek ve aynı belleği bir önbellek satırına yeniden yüklemek için bellekte ileri ve geri gitmiyor). En azından benim alanımda (bilgisayar grafikleri) sadece sabit boyutlu 32 bit ve 64 bit sayısal tuşları sıralamak için çok geniş bir uygulama var.

İçeri girmek ve söylemek istediğim şeylerden biri, radix diziliminin kayan nokta sayıları ve negatifleri üzerinde çalışabileceği, ancak olabildiğince taşınabilir bir FP sürümü yazmak zor. Ayrıca, O (n * K) iken, K, yalnızca anahtar boyutunun bayt sayısı olmalıdır (örn: bir milyon 32 bit tam sayı, kovada 2 ^ 8 giriş varsa, genellikle 4 bayt boyutlu geçişler alırdı). ). Hafıza erişim modeli aynı zamanda tipik olarak paralel bir diziye ve küçük bir kepçe dizisine ihtiyaç duymasına rağmen hızlı ikincilere göre önbellek dostu olma eğilimindedir (ikincisi genellikle yığına tam olarak sığabilir). QS, sporadik rasgele erişim düzenleriyle bir milyon tam sayı dizisini sıralamak için 50 milyon takas yapabilir. Radix sıralaması bunu 4 doğrusal olarak yapabilir, önbellek dostu veri üzerinden geçer.

Bununla birlikte, bunu küçük bir K ile yapamayacağımızın farkında olmama eksikliği, kayan nokta ile birlikte negatif sayılarla, sayı tabanı türlerinin popülaritesinin olmamasına önemli ölçüde katkıda bulunabilir.

İnsanların neden daha sık kullanmadıklarına dair fikrim gelince, genellikle sayıları sıralama veya arama anahtarı olarak kullanma gereksinimi olmayan birçok alanla ilgili olabilir. Bununla birlikte, sadece kişisel tecrübelerime dayanarak, eski meslektaşlarımın çoğu, mükemmel şekilde uygun olduğu durumlarda kısmen kullandılar ve kısmen de AP ve negatifler üzerinde çalışabileceğini bilmiyorlardı. Bu nedenle, yalnızca sayısal türler üzerinde çalışmanın yanı sıra, genellikle olduğundan daha az genel olarak uygulanabilir olduğu düşünülmektedir . Kayan nokta sayıları ve negatif tamsayılar üzerinde çalışmadığını düşünürsem, ben de onu pek kullanmazdım.

Bazı kriterler:

Sorting 10000000 elements 3 times...

mt_sort_int: {0.135 secs}
-- small result: [ 12 17 17 22 52 55 67 73 75 87 ]

mt_radix_sort: {0.228 secs}
-- small result: [ 12 17 17 22 52 55 67 73 75 87 ]

std::sort: {1.697 secs}
-- small result: [ 12 17 17 22 52 55 67 73 75 87 ]

qsort: {2.610 secs}
-- small result: [ 12 17 17 22 52 55 67 73 75 87 ]

Ve bu sadece naif uygulamamla ilgili ( mt_sort_intaynı zamanda sayı tabanı sıralama ancak anahtarın bir tamsayı olduğu varsayılabilir. Uzmanlar tarafından yazılmış standart bir uygulamanın ne kadar hızlı olabileceğini bir düşünün.

Ben radix bulunan tek vaka sıralamak gerçekten çok hızlı karşılaştırma tabanlı s 'C ++ çok daha kötü gibi std::sorthangi inanıyorum point, 32 say, elementlerin gerçekten küçük bir sayı için oldu std::sorttürlü kullanarak başlar daha iyi heapsorts ya da benzeri elemanların en küçük sayı için uygundur ekleme bu tür, ancak bu noktada benim uygulama sadece kullanır std::sort.


1
Alanında deneyime sahip kişilerin görüşlerini duymak her zaman güzel.
Frank Hileman

MT_ çoklu iş parçacıklı uygulamalara sahip görünüyor: softwareengineering.stackexchange.com/a/362097/65606
rogerdpack

1

Bir neden daha: Bugünlerde sıralama genellikle derleyici tarafından sağlanan sıralama mantığına eklenmiş, kullanıcı tarafından sağlanan sıralama yordamıyla uygulanır. Bir radix sıralama ile bu oldukça karmaşık olacaktır ve sıralama rutini değişken uzunluktaki birden fazla tuşa etki ettiğinde daha da kötüleşir. (Söyleyin, isim ve doğum tarihi.)

Gerçek dünyada, aslında bir zamanlar radix sıralama uygulamıştım.. Bu, hafızanın sınırlı olduğu eski günlerde, tüm verilerimi aynı anda hafızaya alamadım. Bu, verilere erişim sayısının O (n) ve O (n log n) 'den çok daha önemli olduğu anlamına geliyordu. Her kaydı bir kutuya tahsis eden veriler arasında bir geçiş yaptım (kayıtların hangi kutuların olduğu, aslında hiçbir şeyi taşımadığı bir listeye göre). Her boş olmayan kutu için (sıralama anahtarım metindi, boş kutular) Verileri gerçekten belleğe getirip getiremediğimi kontrol ettim - evet ise, getirip quicksort kullanın. Hayır ise, yalnızca kutudaki öğeleri içeren geçici bir dosya oluşturun ve rutini tekrar tekrar çağırın. (Uygulamada birkaç kutu taşar.) Bu iki tam okumaya ve bir tanesi ağ deposuna tam yazma ve bunun% 10'u gibi bir şeyin yerel depolamaya neden olmasına neden oldu.

Bugünlerde bu kadar büyük veri sorunlarıyla karşılaşmak çok zor, muhtemelen bir daha asla böyle bir şey yazmam. (Bugünlerde aynı verilerle karşılaşmış olsaydım, sadece 64-bit işletim sistemi belirtirdim, o editörde thifhing yaparsanız RAM ekleyin.)


Bazen belirtilen radix türüne değinilen dezavantajlardan biri göz önüne alındığında büyüleyici, "daha fazla yer kaplar". Hala kafamı
buralara

1
@ rogerdpack Yaklaşımım daha az yer kullanmıyordu, verilere daha az erişim kullanıyordu. Kod ve 64kb'lik bir yapı sınırı da dahil olmak üzere toplam 16 MB bellek kullanan bir bitin derleyici sınırına (bu, DOS korumalı mod değil, Windows)) işlem yaparken bir gigabayt civarında olan bir dosyayı sıralıyordum.
Loren Pechtel

-1

Tüm parametrelerinizin tümü tam sayıysa ve 1024'ün üzerinde giriş parametreniz varsa, radix sıralaması her zaman daha hızlıdır.

Niye ya?

Complexity of radix sort = max number of digits x number of input parameters.

Complexity of quick sort = log(number of input parameters) x   number of input parameters

Yani radix sıralama ne zaman daha hızlı olur?

log(n)> max num of digits

Java'da max tamsayısı 2147483647'dir. 10 basamak uzunluğunda olan

Yani radix sıralama her zaman daha hızlıdır.

log(n)> 10

Bu nedenle, radix sıralama her zaman daha hızlıdır. n>1024


Uygulama detaylarında gizli sabitler var, fakat temelde “daha ​​büyük giriş radix sıralaması için daha hızlı” diyorsunuz ki, durum böyle olmalı! Bunun için kullanım durumlarını bulmak zor ama ne zaman ...
rogerdpack
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.