計數排序

       計數排序是一個非基於比較的排序算法,它的優點在於在對必定範圍內的整數排序時,它的複雜度爲Ο(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是最大的數的大小。

 

若有問題,請掃碼回覆

相關文章
相關標籤/搜索