先说说计数排序的思想:
计数排序假定待排序的所有元素都是介于0到K之间的整数;计数排序使用一个额外的数组countArray,其中第i个元素是待排序数组array中值等于i的元素的个数。然后根据数组countArray来将array中的元素排到正确的位置。
算法的步骤如下:
- 找出待排序的数组中最大和最小的元素
- 统计数组中每个值为i的元素出现的次数,存入数组countArray的第i项
- 对所有的计数累加(从countArray中的第一个元素开始,每一项和前一项相加)
- 反向填充目标数组:将每个元素i放在新数组的第countArray[i]项,每放一个元素就将countArray[i]减去1
稳定性和复杂度:
计数排序是稳定的排序算法;平局时间复杂度、最优时间复杂度和最差时间复杂度都为O(n+k),空间复杂度为O(n+k),其中,n为待排元素个数,k为待排元素的范围(0~k)。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <assert.h> #define RANDMAX 10000 void getRandArray(int array[], int size); void countSort(int array[], int size); void isSorted(int array[], int size); int main(int argc, char const *argv[]) { int size = 0; scanf("%d", &size); assert(size > 0); int *array = (int *)calloc(size, sizeof(int)); getRandArray(array, size); clock_t begin; clock_t end; begin = clock(); countSort(array, size); end = clock(); //打印排序所花费的时间,在linux下单位为ms printf("%ld\n", (end - begin) / 1000); isSorted(array, size); free(array); return 0; } //利用伪随机数填充数组array void getRandArray(int array[], int size) { assert(array != NULL && size > 0); srand((unsigned) time(NULL)); int i = 0; for (i = 0; i < size; ++i) { //产生RANDMAX以内的伪随机数 array[i] = rand() % RANDMAX; } } //从小到大进行排序 void countSort(int array[], int size) { assert(array != NULL && size > 0); //计数数组,用于统计数组array中各个不同数出现的次数 //由于数组array中的数属于0...RANDMAX-1之间,所以countArray的大小要够容纳RANDMAX个int型的值 int *countArray = (int *) calloc(RANDMAX, sizeof(int)); //用于存放已经有序的数列 int *sortedArray = (int *) calloc(size, sizeof(int)); //统计数组array中各个不同数出现的次数,循环结束后countArray[i]表示数值i在array中出现的次数 int index = 0; for (index = 0; index < size; ++index) { countArray[array[index]]++; } //统计数值比index小的数的个数,循环结束之后countArray[i]表示array中小于等于数值i的元素个数 for (index = 1; index < RANDMAX; ++index) { countArray[index] += countArray[index - 1]; } for (index = size - 1; index >= 0; --index) { //因为数组的起始下标为0,所以要减一 sortedArray[countArray[array[index]] - 1] = array[index]; //这里减一是为了保证当有多个值为array[index]的元素时,后出现的值为array[index]的元素 //放在后面,也就是为了保证排序的稳定性 --countArray[array[index]]; } memcpy(array, sortedArray, size * sizeof(int)); free(sortedArray); free(countArray); } //判断数组array是否已经是有序的 void isSorted(int array[], int size) { assert(array != NULL && size > 0); int unsorted = 0; int i = 0; for (i = 1; i < size; ++i) { if (array[i] < array[i - 1]) { unsorted = 1; break; } } if (unsorted) { printf("the array is unsorted!\n"); } else { printf("the array is sorted!\n"); } }
计数排序是非比较的排序算法,据说其排序速度要快于任何的比较排序算法(我还未验证,但是在排序100000000个10000以内的数时花费为606毫秒,而C语言的qsort函数则为10802毫秒,由此可见一斑),由于计数排序需要一个计数数组以及一个存放有序数列的数组,故计数排序对内存的要求比较高。
时间: 2024-10-25 17:37:19