Menu
Coddy logo textTech

Sortowanie przez zliczanie (counting sort)

Ostatnia aktualizacja

Sortowanie przez zliczanie to sortowanie bez porównań dla liczb całkowitych ze znanego, ograniczonego zakresu. Zlicza, ile razy pojawia się każda wartość, a potem na podstawie tych liczników zapisuje każdą wartość bezpośrednio na jej miejscu w posortowanym wyniku, bez żadnych porównań. Kliknij odtwarzanie powyżej i zobacz, jak wartości są zliczane, a potem odkładane z powrotem w kolejności.

Sortowanie przez zliczanie działa w czasie O(n + k), gdzie k to zakres wartości wejściowych. Gdy k nie jest dużo większe od n, algorytm jest niezwykle szybki i może pokonać sortowania przez porównania o złożoności O(n log n), ale przy ogromnym zakresie wartości tablica liczników O(k) czyni go niepraktycznym.

Złożoność czasowa i pamięciowa

PrzypadekZłożonośćUwagi
CzasO(n + k)n elementów, k = zakres wartości
PamięćO(n + k)Tablica liczników + tablica wynikowa
StabilneTakPrzy umieszczaniu od prawej do lewej z sumami prefiksowymi
Porównania?NieSortuje przez zliczanie, nie przez porównywanie
Najlepsze dlaMały zakres liczb całkowitychk bliskie n

Krok po kroku

KrokCo się dzieje
1Znajdź wartość maksymalną, aby ustalić rozmiar tablicy liczników.
2Policz, ile razy występuje każda wartość.
3(Opcjonalnie) Zamień liczniki na sumy prefiksowe, aby zapewnić stabilność.
4Zapisz każdą wartość w wyniku tyle razy, ile się pojawia.
5Tablica wynikowa jest teraz w pełni posortowana.

Przykład krok po kroku

Sortowanie [1, 4, 1, 2, 4] (wartości od 0 do 4, więc tablica liczników ma 5 pól):

PrzebiegStanDziałanie
Skanowanie wejściacount = [0, 2, 1, 0, 2]Zlicz wystąpienia: 1 pojawia się dwa razy, 2 raz, 4 dwa razy.
Sumy prefiksowecount = [0, 2, 3, 3, 5]Każde pole zawiera teraz liczbę wartości <= jego indeksowi, co daje pozycje końcowe.
Umieść 4output = [_, _, _, _, 4]Czytaj od prawej do lewej: count[4] = 5, więc 4 trafia pod indeks 4; zmniejsz do 4.
Umieść 2output = [_, _, 2, _, 4]count[2] = 3, więc 2 trafia pod indeks 2; zmniejsz do 2.
Umieść 1output = [_, 1, 2, _, 4]count[1] = 2, więc 1 trafia pod indeks 1; zmniejsz do 1.
Umieść 4output = [_, 1, 2, 4, 4]count[4] = 4, więc ta 4 trafia pod indeks 3; zmniejsz do 3.
Umieść 1output = [1, 1, 2, 4, 4]count[1] = 1, więc ta 1 trafia pod indeks 0. Tablica jest posortowana.

Kiedy używać sortowania przez zliczanie

Używaj, gdyUnikaj, gdy
Sortujesz liczby całkowite (lub klucze, które da się na nie odwzorować) z małego, znanego zakresu.Zakres wartości k jest dużo większy niż liczba elementów n.
Potrzebujesz liniowego czasu O(n + k) i stać cię na dodatkowe tablice.Pamięci jest mało: tablica liczników kosztuje O(k) niezależnie od n.
Potrzebujesz stabilnego sortowania jako podprocedury (np. w radix sort).Klucze to liczby zmiennoprzecinkowe, napisy lub dowolne obiekty bez odwzorowania na liczby całkowite.
Wartość maksymalna jest ograniczona i łatwo ją wcześniej obliczyć.Zakres jest nieznany lub nieograniczony, więc nie da się ustalić rozmiaru tablicy liczników.

Counting Sort: kod

Przejrzysta, gotowa do uruchomienia implementacja algorytmu Counting Sort w językach: Python, JavaScript, Java, C++, C. Wybierz język, skopiuj kod albo otwórz go od razu w edytorze online Coddy.

Counting Sort: kod (Python)

Python
1def counting_sort(a):2    # Works for non-negative integers with a small max value3    counts = [0] * (max(a) + 1)4    for value in a:5        counts[value] += 16    # Prefix sums turn counts into final positions7    for i in range(1, len(counts)):8        counts[i] += counts[i - 1]9    out = [0] * len(a)10    for value in reversed(a):  # reversed keeps equal values stable11        counts[value] -= 112        out[counts[value]] = value13    return out14
15
16nums = [4, 2, 2, 8, 3, 3, 1]17print("Before:", nums)18print("After: ", counting_sort(nums))
Uruchom ten kod w edytorze Python online

Sortowanie przez zliczanie: najczęstsze pytania

Jaka jest złożoność czasowa sortowania przez zliczanie?
Sortowanie przez zliczanie ma złożoność O(n + k), gdzie n to liczba elementów, a k to zakres możliwych wartości. Gdy k = O(n), jest to czas liniowy. Zużywa O(n + k) dodatkowej pamięci.
Czy sortowanie przez zliczanie jest stabilne?
Może być. Wersja stabilna buduje sumy prefiksowe liczników i umieszcza elementy od prawej do lewej, co zachowuje względną kolejność równych kluczy. Prosta wersja "przepisz według wartości" pokazana tutaj daje poprawne sortowanie, ale stosuje się ją głównie do zwykłych liczb całkowitych.
Kiedy używać sortowania przez zliczanie?
Używaj go przy sortowaniu liczb całkowitych (lub kluczy, które da się na nie odwzorować) z małego, znanego zakresu. Jeśli zakres wartości k jest dużo większy niż liczba elementów, tablica liczników marnuje pamięć i lepsze jest sortowanie przez porównania.
Czym różni się sortowanie przez zliczanie od sortowania pozycyjnego (radix sort)?
Sortowanie przez zliczanie sortuje według całej wartości w jednym przebiegu i potrzebuje tablicy liczników tak dużej jak zakres wartości. Radix sort sortuje cyfra po cyfrze i zwykle wywołuje stabilne sortowanie przez zliczanie dla każdej cyfry, co utrzymuje mały zakres w każdym przebiegu (np. 10 dla cyfr dziesiętnych). Radix sort radzi sobie z dużymi zakresami wartości, przy których pojedyncze sortowanie przez zliczanie byłoby niepraktyczne.
Dlaczego sortowanie przez zliczanie nie zawsze jest szybsze od quicksorta?
Sortowanie przez zliczanie ma złożoność O(n + k), więc wygrywa tylko wtedy, gdy zakres wartości k jest porównywalny z n. Jeśli k jest ogromne, na przykład przy sortowaniu 100 wartości z zakresu od 0 do 1,000,000,000, dominuje tablica liczników O(k) i marnuje pamięć, a sortowanie przez porównania O(n log n), takie jak quicksort, pozostaje szybkie i oszczędne.
Czy sortowanie przez zliczanie obsługuje liczby ujemne?
Tak, z niewielkim przesunięciem. Zamiast indeksować tablicę liczników bezpośrednio wartością, indeksuj ją przez value - min, aby najmniejsza wartość trafiała pod indeks 0. Rozmiar tablicy liczników wynosi wtedy max - min + 1. Pominięcie tego przesunięcia to częsty błąd, który powoduje awarię przy ujemnych danych.
Ilustracja języków programowania w Coddy

Opanuj algorytmy z Coddy

ZACZNIJ