Counting Sort
Son güncelleme
Counting sort, bilinen ve sınırlı bir aralıktaki tam sayılar için karşılaştırmasız bir sıralama yöntemidir. Her değerin kaç kez göründüğünü sayar, ardından bu sayıları kullanarak her değeri doğrudan sıralı konumuna yazar - karşılaştırma gerekmez. Değerlerin sayılıp ardından sıraya yerleştirilişini izlemek için yukarıdan oynat düğmesine basın.
Counting sort O(n + k) sürede çalışır; burada k, giriş değerlerinin aralığıdır. k, n'den çok daha büyük değilse son derece hızlıdır ve O(n log n) karşılaştırmalı sıralamaları geçebilir; ancak değer aralığı çok büyükse O(k) sayım dizisi bunu kullanışsız hale getirir.
Zaman ve alan karmaşıklığı
| Durum | Karmaşıklık | Notlar |
|---|---|---|
| Zaman | O(n + k) | n eleman, k = değer aralığı |
| Alan | O(n + k) | Sayım dizisi + çıktı dizisi |
| Kararlı | Evet | Önek toplamları kullanılarak sağdan sola yerleştirildiğinde |
| Karşılaştırma? | Hayır | Karşılaştırarak değil, sayarak sıralar |
| En uygun | Küçük tam sayı aralığı | k'nin n'ye yakın olduğu durum |
Adım adım
| Adım | Ne olur |
|---|---|
| 1 | Sayım dizisini boyutlandırmak için en büyük değeri bul. |
| 2 | Her değerin kaç kez göründüğünü say. |
| 3 | (İsteğe bağlı) Kararlılık için sayımları önek toplamlarına dönüştür. |
| 4 | Her değeri, göründüğü sayı kadar çıktıya yaz. |
| 5 | Çıktı dizisi artık tamamen sıralanmıştır. |
Çözümlü örnek
[1, 4, 1, 2, 4] dizisi sıralanıyor (değerler 0 ile 4 arasında olduğundan sayım dizisinde 5 yuva var):
| Geçiş | Durum | Eylem |
|---|---|---|
| Girişi tara | count = [0, 2, 1, 0, 2] | Oluşumları say: 1 iki kez, 2 bir kez, 4 iki kez görünür. |
| Önek toplamları | count = [0, 2, 3, 3, 5] | Her yuva artık indeksinden <= kaç değer olduğunu tutar ve nihai konumları verir. |
4'ü yerleştir | output = [_, _, _, _, 4] | Sağdan sola oku: count[4] = 5, bu yüzden 4, 4 indeksine gider; 4'e azalt. |
2'yi yerleştir | output = [_, _, 2, _, 4] | count[2] = 3, bu yüzden 2, 2 indeksine gider; 2'ye azalt. |
1'i yerleştir | output = [_, 1, 2, _, 4] | count[1] = 2, bu yüzden 1, 1 indeksine gider; 1'e azalt. |
4'ü yerleştir | output = [_, 1, 2, 4, 4] | count[4] = 4, bu yüzden bu 4, 3 indeksine gider; 3'e azalt. |
1'i yerleştir | output = [1, 1, 2, 4, 4] | count[1] = 1, bu yüzden bu 1, 0 indeksine gider. Dizi sıralanmıştır. |
Counting sort ne zaman kullanılır
| Şu durumda kullan | Şu durumda kaçın |
|---|---|
| Tam sayıları (veya tam sayıya eşlenebilen anahtarları) küçük ve bilinen bir aralıkta sıralarken. | Değer aralığı k, eleman sayısı n'den çok daha büyükken. |
Doğrusal O(n + k) zaman gerektiğinde ve ek dizileri karşılayabildiğinde. | Bellek kısıtlıyken - sayım dizisi n'den bağımsız olarak O(k) maliyetlidir. |
| Alt rutin olarak kararlı bir sıralamaya ihtiyacın olduğunda (örneğin radix sort içinde). | Anahtarlar float, string veya tam sayıya eşlenemeyen rastgele nesnelerken. |
| En büyük değer sınırlı ve önceden ucuza hesaplanabilirken. | Aralık bilinmiyor veya sınırsızken, dolayısıyla sayım dizisini boyutlandıramazsın. |
Counting Sort kodu
Python, JavaScript, Java, C++, C dillerinde temiz ve çalıştırılabilir bir Counting Sort uygulaması. Bir dil seçin, kodu kopyalayın veya Coddy Playground'da hazır yüklenmiş olarak açın.
Python ile Counting Sort kodu
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))JavaScript ile Counting Sort kodu
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));Java ile Counting Sort kodu
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}C++ ile Counting Sort kodu
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}C ile Counting Sort kodu
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}Counting Sort SSS
Counting sort'un zaman karmaşıklığı nedir?
O(n + k)'dir; burada n eleman sayısı, k ise olası değerlerin aralığıdır. k = O(n) olduğunda bu doğrusal zamandır. O(n + k) ek alan kullanır.Counting sort kararlı mıdır?
Counting sort'u ne zaman kullanmalıyım?
k, eleman sayısından çok daha büyükse sayım dizisi bellek israf eder ve karşılaştırmalı bir sıralama daha iyidir.Counting sort ile radix sort arasındaki fark nedir?
10). Radix sort, tek bir counting sort'u kullanışsız kılacak büyük değer aralıklarını yönetir.Counting sort neden her zaman quicksort'tan hızlı değildir?
O(n + k)'dir, bu yüzden yalnızca değer aralığı k, n ile karşılaştırılabilir olduğunda kazanır. k çok büyükse - örneğin 0 ile 1,000,000,000 aralığında 100 değeri sıralamak - O(k) sayım dizisi baskın olur ve bellek israf ederken, quicksort gibi O(n log n) karşılaştırmalı bir sıralama hızlı ve alan açısından verimli kalır.Counting sort negatif sayıları işleyebilir mi?
value - min ile indeksle; böylece en küçük değer 0 indeksine eşlenir. Sayım dizisinin boyutu max - min + 1 olur. Bu kaydırmayı unutmak, negatif girişlerde hataya yol açan yaygın bir hatadır.