it-swarm.asia

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

Kararlıdır ve O (n) 'nin zaman karmaşıklığına sahiptir. Quicksort ve Mergesort gibi algoritmalardan daha hızlı olmalı, ancak kullanıldığını neredeyse hiç görmüyorum.

32
Queequeg

Sayı tabanı sıralamasından farklı olarak, hızlı sıralama evrenseldir, sayı tabanı sıralaması yalnızca uzunluk tamsayı tuşlarını düzeltmek için yararlıdır.

Ayrıca şunu da anlamalısınız, O(f(n)) gerçekten K * f (n) sırasıyla anlamına gelir, burada K biraz keyfi sabittir. oldukça büyük (en azından sıralı tamsayılardaki bit sayısı sırası), diğer yandan quicksort tüm sıralama algoritmaları ve n * log (n) ortalama karmaşıklığı arasında en düşük K'den birine sahiptir. sayı tabanı sıralamasından çok daha hızlıdır.

40
vartec

Sıralama algoritmalarının çoğu genel amaçlıdır. Bir karşılaştırma işlevi göz önüne alındığında, her şey üzerinde çalışırlar ve Quicksort ve Heapsort gibi algoritmalar O(1) ekstra bellek ile sıralanır).

Radix sıralama daha uzmanlaşmıştır. Sözcük bilgisi düzeninde olan belirli bir anahtara ihtiyacınız vardır. Anahtardaki olası her sembol için bir kovaya ihtiyacınız vardır ve kovaların çok fazla kayıt tutması gerekir. (Alternatif olarak, olası her anahtar değeri tutacak büyük bir kova dizisine ihtiyacınız vardır.) Sayı tabanı sıralaması yapmak için çok daha fazla belleğe ihtiyacınız vardır ve rastgele kullanırsınız. Bunların hiçbiri modern bilgisayarlar için iyi değildir, çünkü Quicksort gibi sayfa hataları elde edersiniz, çünkü önbellek özlüyor olur.

Son olarak, insanlar artık kendi sıralama algoritmalarını artık yazmıyorlar. Çoğu dilde sıralanacak kütüphane olanakları vardır ve yapılacak doğru şey normalde bunları kullanmaktır. Sayı tabanı sıralaması evrensel olarak uygulanabilir olmadığından, genellikle gerçek kullanıma göre uyarlanması gerektiğinden ve çok fazla bellek kullandığından, bunu bir kütüphane işlevine veya şablonuna koymak zordur.

20
David Thornley

Sıraladığınız tuşların aslında bilinen, seyrek bir aralıktaki tamsayılar olması oldukça nadirdir. Genellikle, karşılaştırmalı olmayan sıralamayı destekleyecekleri gibi bak alfabetik alanlarınız vardır, ancak gerçek dünya dizeleri alfabeye eşit olarak dağıtılmadığından, olması gerektiği gibi çalışmaz teorisi.

Diğer zamanlarda, kriter tanımlanır sadece işlevsel olarak (iki kayıt verildiğinde hangisinin önce geleceğine karar verebilirsiniz, ancak izole bir kaydın ölçeğin ne kadar 'ne kadar olduğunu değerlendiremezsiniz). Dolayısıyla yöntem genellikle uygulanamaz, sandığınızdan daha az uygulanabilir veya O (n * log (n)) 'den daha hızlı değildir.

5
Kilian Foth

Her zaman, aslında karşılaştırma tabanlı türlerden daha fazla kullanıyorum, ama kuşkusuz, her şeyden çok sayılarla çalışan bir tuhafım (neredeyse hiç dizelerle çalışmıyorum ve eğer öyleyse genellikle bu noktada radyus sıralama, yinelenenleri 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, bir aramanın veya medyan bölünmesinin bir parçası olarak belirli bir boyuta göre yarıçap sıralama veya çakışma noktalarını, derinlik sıralama parçalarını veya daha fazla önbellek dostu erişim sağlamak için birden fazla döngüde kullanılan bir dizi indeksi tespit etmenin hızlı bir yoludur. (yalnızca tekrar geri dönüp aynı belleği bir önbellek satırına yeniden yüklemek için bellekte ileri geri gitmemek). En azından etki alanımda (bilgisayar grafikleri) yalnızca sabit boyutlu 32 bit ve 64 bit sayısal anahtarları sıralamak için çok geniş bir uygulama var.

Konuşmak istediğim bir şey de, sayı tabanı sayıları ve negatifleri üzerinde sayılabilecek bir sayıdır, ancak FP sürümü olabildiğince taşınabilir olan bir sürüm yazmak zor olsa da). O (n * K), K sadece anahtar boyutunun bayt sayısı olmalıdır (ör. Bir milyon 32 bit tam sayı, kovada 2 ^ 8 giriş varsa genellikle 4 bayt boyutunda geçiş alır). bellek erişim deseni de paralel bir diziye ve tipik olarak küçük bir kova dizisine ihtiyaç duysa bile hızlı sıralamadan çok daha fazla önbellek dostu olma eğilimindedir (ikincisi genellikle yığına tam olarak sığabilir). QS sıralamak için 50 milyon swap yapabilir Sporadik rasgele erişim kalıplarına sahip bir milyon tamsayı dizisi Radx sıralaması bunu verilerin 4 doğrusal, önbellek dostu geçişinde yapabilir.

Bununla birlikte, bunu küçük bir K ile, negatif sayılarla birlikte kayan nokta ile yapabilme bilincinin olmaması, sayı tabanı türlerinin popülaritesinin bulunmamasına çok iyi katkıda bulunabilir.

İnsanların neden daha sık kullanmadığına dair düşünceme gelince, genellikle sayıları sıralamak veya arama anahtarları olarak kullanmak zorunda olmayan birçok alanla ilgili olabilir. Ancak, sadece kişisel deneyimlerime dayanarak, eski meslektaşlarımın birçoğu da mükemmel bir şekilde uygun olduğu durumlarda kullanmadı ve kısmen FP ve negatifler, bu yüzden sadece sayısal türler üzerinde çalışmanın yanı sıra, genellikle aslında olduğundan daha fazla geçerli olduğu düşünülür daha az. Ya kayan nokta sayıları ve negatif tamsayılar üzerinde çalışmadığını düşündü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 benim saf uygulama ile (mt_sort_int De sayı tabanı sıralaması ama daha hızlı bir kod dalı ile verilen anahtar bir tamsayı olduğunu varsayabilir). Uzmanlar tarafından yazılan standart bir uygulamanın ne kadar hızlı olabileceğini düşünün.

Sayı tabanı sıralamasının C++ 'ın gerçekten hızlı karşılaştırma tabanlı std::sort' Dan daha kötü olduğunu bulduğum tek durum, 32 $ gibi çok az sayıda öğe içindi, bu noktada std::sort sıralamalar, yığınlar veya ekleme türleri gibi en az sayıda öğe için daha uygundur, ancak bu noktada uygulamam yalnızca std::sort kullanır.

4
user204677

Bir neden daha: Bu gün sıralama genellikle derleyici tarafından sağlanan sıralama mantığına bağlı kullanıcı tarafından sağlanan bir sıralama yordamı ile uygulanır. Bir sayı tabanı sıralamasıyla, sıralama yordamı değişken uzunluktaki birden çok tuşa etki ettiğinde bu çok daha karmaşık olur ve daha da kötüleşir. (Söyle, isim ver ve doğum tarihi.)

Gerçek dünyada aslında bir sayı tabanı uyguladım bir kez. Bu, belleğin sınırlı olduğu eski günlerde, tüm verilerimi aynı anda belleğe getiremedim. Bu, verilere erişim sayısının O(n) vs O (n log n) değerinden çok daha önemli olduğu anlamına geliyordu.Her kaydı bir depo gözüne ( gerçekte hiçbir şeyi hareket ettirmeyen, hangi kayıtların bulunduğu kayıtların bir listesi.) Boş olmayan her kutu için (sıralama anahtarım metindi, çok fazla boş kutu olurdu) Verileri gerçekten belleğe getirip getiremeyeceğimi kontrol ettim - evet ise, getirin ve hızlı sıralama kullanın. Hayır ise, yalnızca bölmedeki öğeleri içeren bir geçici dosya oluşturun ve rutini yinelemeli olarak çağırın. Yerel depolama için bunun% 10'unu basitçe sıralamak, 2 * n günlük n okumanın ve yazının yaklaşık yarısının - oldukça yavaş olmasına neden olur.

Bu günlerde böyle büyük veri sorunlarının ortaya çıkması çok daha zor, muhtemelen bir daha böyle bir şey yazmayacağım. (Bu gün aynı verilerle karşılaşmış olsaydım sadece 64 bit işletim sistemini belirtirdim, RAM bu düzenleyicide daralma yaşarsanız) ekleyin.)

1
Loren Pechtel