2010-07-22 27 views
20

Notatki: Myślałem o sortowaniu Radix, sortowaniu kubełków, sortowaniu liczenia.Jaki jest najszybszy sposób sortowania 1 miliona liczb całkowitych, gdy liczby całkowite są z zakresu [1100]?

Czy istnieje szansa na uzyskanie dużej liczby O (n)?

+1

To nie jest możliwe w ogóle, aby posortować listę w czasie O (n), nawet jeśli każda liczba na liście jest mniejsza niż 100. – SLaks

+15

@SLaks: Minimalna liczba O (N lgN) ma zastosowanie tylko do sortowania na podstawie porównań. –

+3

w tym przypadku możesz, po prostu licząc elementy od 1 do 100. –

Odpowiedz

62

Można użyć counting sort.

Sortowanie zliczające (czasami określane jako sortowanie ultra lub sortowanie matematyczne) jest algorytmem sortowania, który (podobnie jak sortowanie wiadra) wykorzystuje znajomość zakresu liczb w tablicy do posortowania (tablica A).

Sortowanie zliczania jest sortowaniem trwałym i ma czas działania Θ (n + k), gdzie n ik są długościami macierzy A (tablica wejściowa) i C (tablica zliczania) odpowiednio. Aby ten algorytm był efektywny, k nie może być dużo większe niż n.

W tym przypadku k 100 i n wynosi 1000000.

+1

+1 Oszołomanie oczywiste, ale nigdy wcześniej tego nie widziałem. Dzięki. –

+1

Chcę przegłosować, ale obecnie ma 42 lata i naprawdę chcę, żeby tam został. To największy dylemat, z jakim miałem do czynienia dzisiaj. – EmmaGamma

8

Sortowanie zliczania byłoby oczywistym wyborem w tych okolicznościach. Tak, prawidłowo wdrożone, powinno mieć liniową złożoność.

2

Z sortowanie przez zliczanie dostać O (n), jeśli zakres jest stała i małe (jak 1..100 :))

6

jak o tylko liczenie wystąpienie każdej liczby całkowitej, a następnie drukowanie ich wszystkich. brzmi jak O (n)

+3

Tak, i to jest dokładnie takie sortowanie. To pokazuje, że większość algorytmów nie jest trudna; możesz sam je wymyślić. :-) – ShreevatsaR

+1

sortowanie zliczania jest nieco bardziej skomplikowane (sortuje klucze, ale może obsługiwać dane skojarzone), ale tak, to jest podstawowy pomysł –

3

Zakładam, masz na myśli, że chcesz osiągnąć małe O (n); wtedy sortowanie wiadra będzie najszybsze. W rzeczywistości, ponieważ znasz zakres liczb całkowitych, użycie sortowania wiaderek staje się po prostu problemem zliczania wystąpień liczb, które można wykonać w O (n), tj. W czasie liniowym.

Tak zwany sortowanie zliczania jest po prostu szczególnym przypadkiem sortowania kubełkowego.

+1

Nie, sortowanie zliczania nie jest szczególnym przypadkiem sortowania wiadra. W sortowaniu wiaderek faktycznie przechowujesz elementy w wiadrach. W sortowaniu liczącym przechowujesz tylko licznik. –

0

Dla wszystkich zainteresowanych, szybko rzucił razem ten kawałek Ruby, przed przeczytaniem odpowiedzi:

module Enumerable 
    def counting_sort(k) 
    reduce(Array.new(k+1, 0)) {|counting, n| counting.tap { counting[n] += 1 }}. 
    map.with_index {|count, n| [n] * count }.flatten 
    end 
end 

ary = Array.new(1_000_000){ rand(100) + 1 } 
ary.counting_sort(100) # I'll spare you the output :-) 

ja nawet nie wiem, że miał nazwę. Powinien przekazać pomysł nawet komuś, kto nigdy wcześniej nie widział Rubiego. (Jedyne co musisz wiedzieć to to, że kombinator K jest pisany w Ruby jako tap).

I naprawdę jest bardzo cholernie szybki, chociaż niestety nie udało mi się pokonać wbudowanego ręcznie zoptymalizowanego O (n & thinsp; log & thinsp; n) sort, który jest napisany w C w MRI i YARV i Java w JRuby.

0

Oto porządek liczenia w Scala:

val res = Array.fill (100)(0) 
val r = util.Random 
// generate data to sort 
val nums = for (i <- 1 to 1000*1000) yield r.nextInt (100) 
for (i <- nums) res(i) += 1 
println (res.mkString (" ")) 
0

Korzystanie sortowanie pozycyjne (w Ruby):

def sort(array) 
sorted_array = Array.new(100,[]) 
array.each do |t| 
sorted_array[t-1] = sorted_array[t-1] + [t] 
end 
sorted_array.flatten! 
end 
Powiązane problemy