Interesuje mnie sortowanie tablicy dodatnich wartości liczb całkowitych w czasie liniowym (w modelu pamięci RAM z jednolitą miarą kosztów, tj. Liczby całkowite mogą mieć wielkość logarytmiczną, ale przyjmuje się, że operacje arytmetyczne na nich przyjmą czas jednostkowy). Oczywiście nie jest to możliwe w przypadku algorytmów sortowania opartych na porównaniu, więc jestem zainteresowany obliczeniem sortowania „przybliżonego”, tj. Obliczeniem pewnej permutacji z , która tak naprawdę nie jest klasyfikowane w ogóle, ale „dobrym przybliżeniem” z posortowanej wersji L . Zakładam, że sortujemy liczby całkowite w malejącej kolejności, ponieważ sprawia to, że kontynuacja jest nieco przyjemniejsza w stwierdzeniu, ale oczywiście można by sformułować problem na odwrót.
Jednym z możliwych kryteriów przybliżonego sortowania jest (*): pozwalając być , dla każdego , wymagamy, aby (tj. lista „quasi-posortowana” jest ograniczona od góry przez malejącą funkcję ). Łatwo zauważyć, że faktyczny sort spełnia to: może być większy niż więc jest co najwyżej czyli , i ogólnie może być większy niż który jest .
Na przykład wymaganie (*) można osiągnąć za pomocą poniższego algorytmu (sugerowanego przez @Louis). Moje pytanie brzmi: czy istnieją prace nad tym zadaniem „prawie sortowania” liczb całkowitych w czasie liniowym, poprzez nałożenie jakiegoś wymogu, takiego jak (*), który spełniłby prawdziwy sort? Czy poniższy algorytm lub jego wariant ma ustaloną nazwę?
Edycja: poprawiono algorytm i dodano więcej wyjaśnień
Algorytm:
INPUT: V an array of size n containing positive integers
OUTPUT: T
N = Σ_{i<n} V[i]
Create n buckets indexed by 1..n
For i in 1..n
| Add V[i] into the bucket min(floor(N/V[i]),n)
+
For bucket 1 to bucket n
| For each element in the bucket
| | Append element to T
| +
+
Ten algorytm działa zgodnie z przeznaczeniem z następujących powodów:
- Jeśli element znajduje się w wiadrze wówczas .
jest wstawiane do wiadra , a zatem j ≤ \ lfloor N / v \ rfloor ≤ N / v
- Jeśli element znajduje się w wiadrze albo lub .
j = min ( N / v , n ) j = ⌊ N / v ⌋ j = n j = ⌊ N / v ⌋ j ≤ N / v < j + 1 N / ( j + 1 ) < v jest wstawiane do segmentu , a zatem lub . W pierwszym przypadku co oznacza a zatem .
Dla istnieje najwyżej elementów w wiadrach od 1 do .
Niech i niech będzie całkowitą liczbą elementów w jednym z segmentów 1..j. Do 2. mamy, że każdy element w segmencie (z ) jest taki, że . Dlatego suma wszystkich elementów w segmentach od do jest większa niż . Ale ta suma jest również mniejsza niż zatem a zatem co daje nam lub .
spełnia (*) tj. -ty element jest taki, że
Do 3. mamy, że , ty element , pochodzi z wiadra z dlatego .
Algorytm ten zajmuje czas liniowy.
Obliczenie zajmuje czas liniowy. Wiadra mogą być implementowane za pomocą połączonej listy, która ma wstawianie i iterację . Zagnieżdżona pętla działa tyle razy, ile jest elementów (tj. razy).