计数排序
计数排序是线性排序的一种。能够在线性时间内完成给定序列的排序,但计数排序应用的场景就更加具体了。
基本思想:对每一个输入的元素x,确定小于x的元素个数。这样就可以直接把x放到它在输出数组中的位置了。例如,有17个元素小于x,则x应在第18个输出位置上,但当有几个相同元素时,就要略加修改。
下面是算法导论中给出的伪代码:
COUNTING_SORT(A, B, k)
let C[0...k] be a new array
for i = 0 to k
C[i] = 0
for j = 1 to A.length
C[A[j]] = C[A[j]] + 1
for i = 1 to k
C[i] = C[i] + C[i - 1]
for j = A.length downto 1
B[C[A[j]]] = A[j]
C[A[j]] = C[A[j]] - 1
有了伪代码,就很容易转换成代码
void Counting_Sort(int A[], int size)
{
int *B = NULL;
B = (int *) malloc(sizeof(int) * size);
for(int i = 0; i < size; i++)//临时数组的初始化
B[i] = 0;
for(int i = 0; i < size; i++)//记录元素的个数
B[A[i]]++;
for(int i = 0; i < size; i++)确定小于B[i]的元素个数
B[i] += B[i - 1];
int *C = NULL; //C数组用来临时存放有序序列
C = (int *)malloc(sizeof(int) * size);
for(int i = 0; i < size; i++)
{
C[B[A[i]]] = A[i];
B[A[i]]--;
}
for(int j = 0; j < size; j++)//将有序序列赋值给数组A
A[i] = C[j];
free(B); /*最后释放B和C的空间*/
free(C);
}
其实,还可以使代码更简洁,省去临时数组A,像下面这样:
void Counting_Sort(int A[], int size)
{
int *B = NULL;
B = (int *) malloc(sizeof(int) * size);
for(int i = 0; i < size; i++)//临时数组的初始化
B[i] = 0;
for(int i = 0; i < size; i++)//记录元素的个数
B[A[i]]++;
int index = 0;
for(int i = 0; i < size; i++)//B中的下表就是原数中的元素
{ //而B[i]的值代表元素的个数
while(B[i]-- > 0)
{
A[index++] = i;
}
}
free(B);
}