1. 程式人生 > >常用排序演算法總結9一一計數排序

常用排序演算法總結9一一計數排序

定義

計數排序(英語:Counting Sort)是一種穩定的線性時間排序演算法。計數排序使用一個額外的陣列C,其中第i個元素是待排序陣列A中值等於i的元素的個數。然後根據陣列C來將A中的元素排到正確的位置。

演算法步驟

  • 找出待排序的陣列中最大和最小的元素
  • 統計陣列中每個值為i的元素出現的次數,存入陣列 C 的第 i 項
  • 對所有的計數累加(從C中的第一個元素開始,每一項和前一項相加)
  • 反向填充目標陣列:將每個元素i放在新陣列的第C(i)項,每放一個元素就將C(i)減去1

當輸入的元素是n個0到k之間的整數時,它的執行時間是O(n + k)。計數排序不是比較排序,排序的速度快於任何比較排序演算法。
由於用來計數的陣列C的長度取決於待排序陣列中資料的範圍(等於待排序陣列的最大值與最小值的差加上1),這使得計數排序對於資料範圍很大的陣列,需要大量時間和記憶體。例如:計數排序是用來排序0到100之間的數字的最好的演算法,但是它不適合按字母順序排序人名。但是,計數排序可以用在基數排序演算法中,能夠更有效的排序資料範圍很大的陣列。
通俗地理解,例如有10個年齡不同的人,統計出有8個人的年齡比A小,那A的年齡就排在第9位,用這個方法可以得到其他每個人的位置,也就排好了 序。當然,年齡有重複時需要特殊處理(保證穩定性),這就是為什麼最後要反向填充目標陣列,以及將每個數字的統計減去1的原因。

程式碼實現(java)

public static int[] countSort(int []a)
{
    int b[] = new int[a.length];
    int max = a[0], min = a[0];
    for(int i : a) {
        if(i > max) {
            max = i;
        }
        if(i < min) {
            min = i;
        }
    }
    //這裡k的大小是要排序的陣列中,元素大小的極值差+1
    int k = max
- min + 1; int c[] = new int[k]; for(int i = 0; i < a.length; ++i) { c[a[i]-min] += 1;//優化過的地方,減小了陣列c的大小 } for(int i = 1; i < c.length; ++i) { c[i] = c[i] + c[i-1]; } for(int i = a.length-1; i >= 0; --i) { b[--c[a[i]-min]] = a[i];//按存取的方式取出c的元素 } return
b; }

總結

計數排序和基數排序很類似,都是非比較型排序演算法。但是,它們的核心思想是不同的,基數排序主要是按照進位制位對整數進行依次排序,而計數排序主要側重於對有限範圍內物件的統計。基數排序可以採用計數排序來實現。

參考文章