《算法导论》第8章 线性时间排序 (1)计数排序
一种简单的实现是得到数组C,C[i]表示数组A中值为i的元素个数。
C = { 2, 0, 2, 3, 0, 1 }就表示两个0,两个2,三个3,一个5。
然后将这些数字依次存到数组B中。
#include <stdio.h>
#include <stdlib.h>
void printArray(int[], int);
void counting_sort(int A[], int B[], int len, int k)
{
int* C = calloc(k + 1, sizeof(int));
int j;
for (j = 0; j < len; j++)
C[A[j]] += 1;
#include <stdlib.h>
void printArray(int[], int);
void counting_sort(int A[], int B[], int len, int k)
{
int* C = calloc(k + 1, sizeof(int));
int j;
for (j = 0; j < len; j++)
C[A[j]] += 1;
// 保存C[i]个元素i到数组B[j]中。
int i;
for (i = 0, j = 0; i <= k; i++)
while (C[i]-- > 0)
B[j++] = i;
}
int main(void)
{
int A[8] = { 2, 5, 3, 0, 2, 3, 0, 3 };
int B[8];
int k = 5;
counting_sort(A, B, 8, k);
printArray(B, 8);
return 1;
}
void printArray(int array[], int len)
{
int i;
for (i = 0; i < len; i++)
printf("%d,", array[i]);
printf("\n");
}
int i;
for (i = 0, j = 0; i <= k; i++)
while (C[i]-- > 0)
B[j++] = i;
}
int main(void)
{
int A[8] = { 2, 5, 3, 0, 2, 3, 0, 3 };
int B[8];
int k = 5;
counting_sort(A, B, 8, k);
printArray(B, 8);
return 1;
}
void printArray(int array[], int len)
{
int i;
for (i = 0; i < len; i++)
printf("%d,", array[i]);
printf("\n");
}
这样简单的实现可以处理简单的整型数组的排序,但是对于有卫星数据的对象来说,
直接遍历数组C输出结果的方法是行不通的。不能直接创建新的元素当做结果,
而需要挪到输入数组A中的元素。
《算法导论》中的实现如下:保证结果与输入数组中元素的关联,以及稳定性。
// A = { 2, 5, 3, 0, 2, 3, 0, 3 }, len = 8, k = 5
void counting_sort(int A[], int B[], int len, int k)
{
void counting_sort(int A[], int B[], int len, int k)
{
// 输入数范围是[0, k],数组C大小是k+1
int* C = calloc(k + 1, sizeof(int));
int* C = calloc(k + 1, sizeof(int));
// C[i]表示数组A中值为i的元素个数
// C = { 2, 0, 2, 3, 0, 1 }
int j;
for (j = 0; j < len; j++)
C[A[j]] += 1;
int j;
for (j = 0; j < len; j++)
C[A[j]] += 1;
// C[i]表示数组A中小于等于值为i的元素个数
// 即C[A[j]] - 1即为元素应在B中的下标
// C = { 2, 2, 4, 7, 7, 8 }
int i;
for (i = 1; i <= k; i++)
C[i] += C[i - 1];
int i;
for (i = 1; i <= k; i++)
C[i] += C[i - 1];
// 从len - 1到0遍历数组A,保证稳定性
for (j = len - 1; j >= 0; j--) {
B[C[A[j]] - 1] = A[j];
C[A[j]] -= 1;
}
}
for (j = len - 1; j >= 0; j--) {
B[C[A[j]] - 1] = A[j];
C[A[j]] -= 1;
}
}
习题8.2-4,先使用计数排序花费n+k时间得到数组C,
然后区间[a, b]内的数字个数就是C[b] - C[a-1]。(a=0时,C[0] = 0)
例如上面例子中A = { 2, 5, 3, 0, 2, 3, 0, 3 },
C = { 2, 2, 4, 7, 7, 8 },[0, 5] = C[5] - 0 = 8
[1, 3] = C[3] - C[1-1] = 7 - 2 = 5。