計數排序是一個非基於比較的排序算法,它的優點在於在對必定範圍內的整數排序時,它的複雜度爲Ο(n+k)(其中k是整數的範圍),快於任何比較排序算法。咱們估計要有疑問了,這個排序算法這麼快,爲何還存在其餘的排序算法呢,這就須要要咱們綜合時間複雜度和空間複雜度那個最優了。java
Java底層對不一樣的數據實現了各類各樣的排序算法,而對於計數排序只有在比較byte類型的數字纔有效,也就是說數字最大也就是256.Java底層對這個算法實現的至關精巧,基本實現過程以下:(詳情能夠打開jdk java.util.Arrays.sort(byte[]))。算法
1:初始化一個計數數組,大小是輸入數組中的最大的數。數組
2:遍歷輸入數組,遇到一個數就在計數數組對應的位置上加一。例如:遇到7,就將計數數組第七個位置的數加一。優化
3:把計數數組直接覆蓋到輸出數組(節約空間)。code
源碼以下:排序
public static void sort(byte[] a, int left, int right) { // Use counting sort on large arrays if (right - left > COUNTING_SORT_THRESHOLD_FOR_BYTE) { // 初始化了一個大小爲256的計數數組 int[] count = new int[NUM_BYTE_VALUES]; // 按照必定的規律把數字放在計數數組相應的加加以後位置上, //若是重複數字出現則在位置上進行加1 for (int i = left - 1; ++i <= right; count[a[i] - Byte.MIN_VALUE]++ ); //把計數數組直接覆蓋到原數組進行輸出 for (int i = NUM_BYTE_VALUES, k = right + 1; k > left; ) { while (count[--i] == 0); byte value = (byte) (i + Byte.MIN_VALUE); int s = count[i]; do { a[--k] = value; } while (--s > 0); } } }
在jdk中這段代碼仍是存在優化的空間,能夠把初始化數組更小, 舉個例子:源碼
好比說我輸入了一個數組{4, 1, 4, 2, 3},初始化數組大小爲4便可,(按照算法導論中對計數排序的理論,即:計數數組的大小爲排序數組中數字最大的數)
創建計數數組{0, 0, 0, 0}。jdk
遍歷輸入數組:遍歷
{3, 4, 3, 2, 1} -> {0, 0, 1, 0}
{3, 4, 3, 2, 1} -> {0, 0, 1, 1}
{3, 4, 3, 2, 1} -> {0, 0, 2, 1}
{3, 4, 3, 2, 1} -> {0, 1, 2, 1}
{3, 4, 3, 2, 1} -> {1, 1, 2, 1}im
計數數組如今是{1, 1, 2, 1},咱們如今把它寫回到輸入數組裏:
{0, 1, 2, 1} -> {1, 4, 3, 2, 1}
{0, 0, 2, 1} -> {1, 2, 3, 2, 1}
{0, 0, 1, 1} -> {1, 2, 3, 2, 1}
{0, 0, 0, 1} -> {1, 2, 3, 3, 1}
{0, 0, 0, 0} -> {1, 2, 3, 3, 4}
這樣就排好序了。
時間:O(n + k),n是輸入數組長度,k是最大的數的大小。
空間:O(n + k),n是輸入數組長度,k是最大的數的大小。
若有問題,請掃碼回覆