演算法系列:計數排序

大飛發表於2014-08-01

計數排序可能是最簡單的一種排序,它可以被用來對一個列表進行排序,並且是基數排序的一個關鍵部分。這兩者都是被Harold Seward發明的,這篇文章我將解釋計數排序並且用C寫出來。

  • 計數排序

計數排序非常基礎,他的主要目的是對整數排序並且會比普通的排序演算法效能更好。例如,輸入{1, 3, 5, 2, 1, 4}給計數排序,會輸出{1, 1, 2, 3, 4, 5}。這個演算法由以下步驟組成:

  1. 初始化一個計數陣列,大小是輸入陣列中的最大的數。
  2. 遍歷輸入陣列,遇到一個數就在計數陣列對應的位置上加一。例如:遇到5,就將計數陣列第五個位置的數加一。
  3. 把計數陣列直接覆蓋到輸出陣列(節約空間)。
  • 例子

輸入{3, 4, 3, 2, 1},最大是4,陣列長度是5。

建立計數陣列{0, 0, 0, 0}。

遍歷輸入陣列:

{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}

計數陣列現在是{1, 1, 2, 1},我們現在把它寫回到輸入陣列裡:

{0, 1, 2, 1} -> {1, 4, 3, 2, 1}
{o, o, 2, 1} -> {1, 2, 3, 2, 1}
{o, o, 1, 1} -> {1, 2, 3, 2, 1}
{o, o, o, 1} -> {1, 2, 3, 3, 1}
{o, o, o, o} -> {1, 2, 3, 3, 4}

這樣就排好序了。

  • 時間:O(n + k),n是輸入陣列長度,k是最大的數的大小。
  • 空間:O(n + k),n是輸入陣列長度,k是最大的數的大小。
  • 程式碼

插播一句:如果你程式設計有困難,無妨看看我的教程

  • 總結

不幸的是,這個演算法的簡潔性同時也是它的弱點。很多程式設計師不需要對整數排序,至少他們覺得他們不需要。其實通常非整數都可以被規約為整數,然後再用計數排序或者基數排序(基數排序就是多加了一層,這樣會快一些)。谷歌一下可以有不少結果,比如這篇文章

相關文章