计数排序详解
前面学习的归并排序、快速排序、堆排序、shell排序、插入排序、选择排序、冒泡排序都是基于元素比较的排序算法。用决策树的方法可以得出它们最好的时间复杂度为O(nlgn)然而它们的适用场合比较多。
计数排序以及桶排序、基数排序都不是基于比较的方法的,它们属于线性排序,也就是它们可以在线性时间内完成排序。但它们的条件要求相对比较法来说也是比较苛刻,计数排序就要求要指明排序的元素的是0~k之间的整数。当然了解了其运行方法后就可以将输入的任意数归一化到0~k范转围之内。
线性时间排序效率提高是以空间的增加换取的。计数排序要与输入数组一样的内存空间,还要有长度为K的辅助数组以记录每一个元素出现的次数,这样可以推断出同一个元素重复出现时最后的位置所在。
假如我们输入的数的序列为2、3、2、1、0那么辅助数组长度要为最大值减最小值,也就是前面提到的范围,这里显然是0 ~3,所以辅助数组的大小为4。算法运行时先将辅助数组初始化为0,后对输入序列进行遍历,计算出每个位置索引所代表的值出现的个数,对于我们的例子辅助数组为1、1、2、1,分别表示了每个位置数出现的次数。很显然0应该放到第一个位置,1存入第二个位置,后面两个位置存2,最后存3。所以将出现次数累加可以得到元素出现的最后位置。假如辅助数组为c[],那么也就是一个循环c[i] = c[i] + c[i -1]。最后一次扫描输入数组可从辅助数组中找到其位置,将之存入另一个数组中,并将位置数减1。
以下是实现的C程序代码:
1 /************************************************* 2 Function: countsort 3 Description: 计数排序的实现 4 Input: intarrry 输入的待排序数组 然后是开始 结尾下标 5 minnum maxnum为输入的数组中的最大值与最小值 6 其中的值要保证在这个范围之内 7 Return: void 8 *************************************************/ 9 void countsort(int* intarray, int startpos, int endpos, int minnum, int maxnum) 10 { 11 int size = endpos - startpos + 1; 12 int range = maxnum - minnum + 1; 13 if (startpos < 0 || endpos < startpos || range == 0) 14 return; 15 16 //存储排序过后的数据 17 int* b = (int*)malloc(sizeof(int) * size); 18 //待排序数据的范围,当不是时可以标准化 19 int* c = (int*)malloc(sizeof(int) * range); 20 int i; 21 //将计数数组的值初始化为0 22 for (i = 0; i != range; i++) 23 c[i] = 0; 24 //统计对于一定位置的数字出现的个数 25 for (i = 0; i != size; i++) 26 c[intarray[i + startpos] - minnum] += 1; 27 //记录数字排序后的最靠后的位置 28 for (i = 1; i != range; i++) 29 c[i] = c[i - 1] + c[i]; 30 //将每个待排序的数字放到其最终的位置 31 for (i = endpos; i != startpos - 1; i--) 32 { 33 b[c[intarray[i] - minnum] - 1] = intarray[i]; 34 c[intarray[i] - minnum] -= 1; 35 } 36 memcpy(intarray + startpos, b, size * sizeof(int)); 37 free(c); 38 free(b); 39 } 40 41 void main() 42 { 43 int len, startpos, endpos; 44 int a[100]; 45 int i; 46 //inputmax inputmin 用来计数排序 47 int inputmax = 0; 48 int inputmin = 0; 49 50 printf("input your number count less than 100 and startposition and end position\n"); 51 scanf("%d%d%d", &len, &startpos, &endpos); 52 printf("input your numbers less than 100....\n"); 53 for (i = 0; i != len; i++) 54 scanf("%d", &a[i]); 55 inputmax = a[startpos]; 56 inputmin = a[startpos]; 57 for (i = startpos + 1; i != endpos + 1; i++) 58 { 59 if (inputmax < a[i]) 60 inputmax = a[i]; 61 else if(inputmin > a[i]) 62 inputmin = a[i]; 63 } 64 //-------------countsort---- 65 countsort(a, startpos, endpos, inputmin, inputmax); 66 for (i = 0; i != len; i++) 67 printf("%d ", a[i]); 68 }

浙公网安备 33010602011771号