Counting Sort
Terakhir diperbarui
Counting sort adalah algoritma pengurutan tanpa perbandingan untuk integer dalam rentang yang diketahui dan terbatas. Algoritma ini menghitung berapa kali setiap nilai muncul, lalu memakai hitungan itu untuk menulis setiap nilai langsung ke posisi terurutnya, tanpa perlu perbandingan. Tekan Putar di atas untuk melihat nilai-nilai dihitung lalu ditempatkan kembali secara berurutan.
Counting sort berjalan dalam waktu O(n + k), dengan k adalah rentang nilai input. Jika k tidak jauh lebih besar daripada n, algoritma ini sangat cepat dan bisa mengalahkan pengurutan berbasis perbandingan O(n log n). Namun, jika rentang nilainya sangat besar, array hitungan O(k) membuatnya tidak praktis.
Kompleksitas waktu dan ruang
| Kasus | Kompleksitas | Catatan |
|---|---|---|
| Waktu | O(n + k) | n elemen, k = rentang nilai |
| Ruang | O(n + k) | Array hitungan + array output |
| Stabil | Ya | Jika ditempatkan dari kanan ke kiri dengan prefix sum |
| Perbandingan? | Tidak | Mengurutkan dengan menghitung, bukan membandingkan |
| Paling cocok untuk | Rentang integer kecil | k mendekati n |
Langkah demi langkah
| Langkah | Apa yang terjadi |
|---|---|
| 1 | Cari nilai maksimum untuk menentukan ukuran array hitungan. |
| 2 | Hitung berapa kali setiap nilai muncul. |
| 3 | (Opsional) Ubah hitungan menjadi prefix sum agar pengurutan stabil. |
| 4 | Tulis setiap nilai ke output sebanyak jumlah kemunculannya. |
| 5 | Array output kini sudah terurut sepenuhnya. |
Contoh penerapan
Mengurutkan [1, 4, 1, 2, 4] (nilainya berkisar dari 0 sampai 4, jadi array hitungan punya 5 slot):
| Tahap | Keadaan | Aksi |
|---|---|---|
| Pindai input | count = [0, 2, 1, 0, 2] | Hitung kemunculan: 1 muncul dua kali, 2 sekali, 4 dua kali. |
| Prefix sum | count = [0, 2, 3, 3, 5] | Setiap slot kini menyimpan berapa banyak nilai yang <= indeksnya, sehingga memberi posisi akhir. |
Tempatkan 4 | output = [_, _, _, _, 4] | Baca dari kanan ke kiri: count[4] = 5, jadi 4 masuk ke indeks 4; kurangi menjadi 4. |
Tempatkan 2 | output = [_, _, 2, _, 4] | count[2] = 3, jadi 2 masuk ke indeks 2; kurangi menjadi 2. |
Tempatkan 1 | output = [_, 1, 2, _, 4] | count[1] = 2, jadi 1 masuk ke indeks 1; kurangi menjadi 1. |
Tempatkan 4 | output = [_, 1, 2, 4, 4] | count[4] = 4, jadi 4 yang ini masuk ke indeks 3; kurangi menjadi 3. |
Tempatkan 1 | output = [1, 1, 2, 4, 4] | count[1] = 1, jadi 1 yang ini masuk ke indeks 0. Array sudah terurut. |
Kapan memakai counting sort
| Pakai saat | Hindari saat |
|---|---|
| Kamu mengurutkan integer (atau key yang bisa dipetakan ke integer) dalam rentang kecil yang diketahui. | Rentang nilai k jauh lebih besar daripada jumlah elemen n. |
Kamu butuh waktu linear O(n + k) dan sanggup menanggung array tambahan. | Memori terbatas: array hitungan berbiaya O(k) berapa pun n-nya. |
| Kamu butuh pengurutan stabil sebagai subrutin (misalnya di dalam radix sort). | Key-nya berupa float, string, atau objek sembarang tanpa pemetaan ke integer. |
| Nilai maksimumnya terbatas dan murah dihitung di awal. | Rentangnya tidak diketahui atau tidak terbatas, jadi kamu tidak bisa menentukan ukuran array hitungan. |
Kode Counting Sort
Implementasi Counting Sort yang rapi dan siap dijalankan dalam Python, JavaScript, Java, C++, C. Pilih bahasa, salin kodenya, atau buka langsung di Coddy Playground.
Kode Counting Sort dalam 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))Kode Counting Sort dalam JavaScript
1function countingSort(arr) {2 // Count occurrences of each value, then rebuild in order3 const max = Math.max(...arr);4 const count = new Array(max + 1).fill(0);5 for (const x of arr) count[x]++;6 const out = [];7 count.forEach((c, value) => {8 for (let k = 0; k < c; k++) out.push(value);9 });10 return out;11}12
13const data = [4, 2, 9, 2, 7, 4, 1, 4];14console.log("Before:", data);15console.log("Sorted:", countingSort(data));Kode Counting Sort dalam Java
1import java.util.Arrays;2
3public class Main {4 static int[] countingSort(int[] arr) {5 int max = 0;6 for (int v : arr) max = Math.max(max, v);7 int[] count = new int[max + 1];8 for (int v : arr) count[v]++;9 // Prefix sums turn counts into final positions10 for (int i = 1; i <= max; i++) count[i] += count[i - 1];11 int[] out = new int[arr.length];12 // Walk backwards so equal values keep their order (stable)13 for (int i = arr.length - 1; i >= 0; i--) {14 out[--count[arr[i]]] = arr[i];15 }16 return out;17 }18
19 public static void main(String[] args) {20 int[] arr = {4, 2, 2, 8, 3, 3, 1};21 System.out.println("Before: " + Arrays.toString(arr));22 int[] sorted = countingSort(arr);23 System.out.println("After: " + Arrays.toString(sorted));24 }25}Kode Counting Sort dalam C++
1#include <algorithm>2#include <iostream>3#include <vector>4
5void printVec(const std::vector<int>& a) {6 for (int x : a) std::cout << x << " ";7 std::cout << "\n";8}9
10void countingSort(std::vector<int>& a) {11 if (a.empty()) return;12 int maxVal = *std::max_element(a.begin(), a.end());13 // count[v] = how many times v appears14 std::vector<int> count(maxVal + 1, 0);15 for (int x : a) ++count[x];16 // Rebuild the array from the counts17 size_t idx = 0;18 for (int v = 0; v <= maxVal; ++v) {19 while (count[v]-- > 0) a[idx++] = v;20 }21}22
23int main() {24 std::vector<int> data = {4, 2, 2, 8, 3, 3, 1, 7};25 std::cout << "Before: ";26 printVec(data);27 countingSort(data);28 std::cout << "After: ";29 printVec(data);30 return 0;31}Kode Counting Sort dalam C
1#include <stdio.h>2#include <stdlib.h>3
4void printArr(const int a[], int n) {5 for (int i = 0; i < n; i++) printf("%d ", a[i]);6 printf("\n");7}8
9void countingSort(int a[], int n) {10 int maxVal = a[0];11 for (int i = 1; i < n; i++) {12 if (a[i] > maxVal) maxVal = a[i];13 }14 // count[v] = how many times v appears15 int* count = calloc(maxVal + 1, sizeof(int));16 for (int i = 0; i < n; i++) count[a[i]]++;17 // Rebuild the array from the counts18 int idx = 0;19 for (int v = 0; v <= maxVal; v++) {20 while (count[v]-- > 0) a[idx++] = v;21 }22 free(count);23}24
25int main(void) {26 int data[] = {4, 2, 2, 8, 3, 3, 1, 7};27 int n = sizeof(data) / sizeof(data[0]);28 printf("Before: ");29 printArr(data, n);30 countingSort(data, n);31 printf("After: ");32 printArr(data, n);33 return 0;34}FAQ Counting Sort
Berapa kompleksitas waktu counting sort?
O(n + k), dengan n adalah jumlah elemen dan k adalah rentang nilai yang mungkin. Jika k = O(n), ini adalah waktu linear. Ruang tambahan yang dipakai O(n + k).Apakah counting sort stabil?
Bisa. Versi stabilnya membangun prefix sum dari hitungan dan menempatkan elemen dari kanan ke kiri, sehingga urutan relatif key yang sama tetap terjaga. Versi sederhana "tulis ulang berdasarkan nilai" yang ditampilkan di sini menghasilkan pengurutan yang benar, tetapi terutama dipakai untuk integer biasa.
Kapan sebaiknya memakai counting sort?
k jauh lebih besar daripada jumlah elemen, array hitungan akan memboroskan memori dan pengurutan berbasis perbandingan lebih baik.Apa perbedaan counting sort dan radix sort?
10 untuk digit desimal). Radix sort bisa menangani rentang nilai besar yang akan membuat satu counting sort tidak praktis.Mengapa counting sort tidak selalu lebih cepat daripada quicksort?
O(n + k), jadi hanya menang saat rentang nilai k sebanding dengan n. Jika k sangat besar, misalnya mengurutkan 100 nilai dalam rentang 0 sampai 1,000,000,000, array hitungan O(k) mendominasi dan memboroskan memori, sementara pengurutan berbasis perbandingan O(n log n) seperti quicksort tetap cepat dan hemat ruang.Bisakah counting sort menangani bilangan negatif?
value - min, sehingga nilai terkecil dipetakan ke indeks 0. Ukuran array hitungan menjadi max - min + 1. Lupa memakai offset ini adalah bug umum yang membuat program crash pada input negatif.