原理:
假設待排序序列沒有負數。對序列裏面的所有元素,確定比該元素小的元素有幾個。利用這個信息就能知道該元素應該放在哪個位置上。
舉例:
A序列(待排序)
然後我們對B序列相鄰兩個元素進行相加,相加後的數字放在下標較大的位置裏。
B序列(相加後的結果,用於表示比A中元素小的元素個數)
然後我們對A序列逆序便利一下,結果放在C序列裏面。
倒數第一個爲6,找到B序列下標爲6的位置,裏面的值爲8,說明這個元素應該排在第七個位置上。
B序列對應的第六個位置的元素-1。避免相同的數字。
倒數第二個爲5,找到B序列下標爲5的位置,裏面的值爲7,說明這個元素應該排在第六個位置上。
C序列
B序列對應的第五個位置的元素-1。
倒數第三個爲3,找到B序列下標爲3的位置,裏面的值爲4,說明這個元素應該排在第三個位置上。
B序列對應的第三個位置的元素-1。
倒數第四個爲9,找到B序列下標爲9的位置,裏面的值爲10,說明這個元素應該排在第九個位置上。
B序列對應的第九個位置的元素-1。
倒數第五個爲3,找到B序列下標爲3的位置,裏面的值爲3,說明這個元素應該排在第二個位置上。
倒數第六個爲2,找到B序列下標爲2的位置,裏面的值爲2,說明這個元素應該排在第一個位置上。
倒數第七個爲5,找到B序列下標爲5的位置,裏面的值爲6,說明這個元素應該排在第五個位置上。
B序列對應的第五個位置的元素-1。
B序列
倒數第八個爲5,找到B序列下標爲5的位置,裏面的值爲5,說明這個元素應該排在第四個位置上。
C序列
B序列對應的第五個位置的元素-1。
倒數第九個爲7,找到B序列下標爲7的位置,裏面的值爲9,說明這個元素應該排在第八個位置上。
B序列對應的第七個位置的元素-1。
倒數第十個爲1,找到B序列下標爲1的位置,裏面的值爲1,說明這個元素應該排在第零個位置上。
B序列對應的第一個位置的元素-1。
代碼:
void CountSort(int a[], int nlen)
{
int temp = a[0];
for (int i = 0; i != nlen; ++i)
{
if (temp < a[i])
{
temp = a[i];
}
}
int b_size = temp + 1;
int *b = new int[b_size];
for (int i = 0; i != b_size; ++i)
{
b[i] = 0;
}
for (int i = 0; i != nlen; ++i)
{
++b[a[i]];
}
for (int i = 1; i != b_size; ++i)
{
b[i] += b[i - 1];
}
int *c = new int[nlen];
for (int i = nlen-1; i >= 0; --i)
{
c[--b[a[i]]] = a[i];
}
for (int i = 0; i != nlen; ++i)
{
a[i] = c[i];
}
delete[] b;
b = nullptr;
delete[] c;
c = nullptr;
}
總結:
計數排序的思想很簡單,並且是已常量時間完成的排序,時間複雜度爲O(N),但是缺陷也很明顯,其一,必須是大於等於0的元素,當有數字爲負數的時候,可以給每個元素都加上一個正數,使得待排序序列爲正數,排完後再減去這個正數(前提不越界的情況下)。其二,該排序算法浪費了大量的空間來換取時間。例如有99999的元素,那麼B序列也應該有100000的長度。