计数排序详解

   前面学习的归并排序、快速排序、堆排序、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 }
posted @ 2012-09-23 16:41  answer0107  阅读(168)  评论(0)    收藏  举报