计数与基数排序

参考 http://www.cnblogs.com/eaglet/archive/2010/09/16/1828016.html

计数排序是一种算法复杂度 O(n) 的排序方法,适合于小范围集合的排序。比如100万学生参加高考,我们想对这100万学生的数学成绩(假设分数为0到100)做个排序。我们如何设计一个最高效的排序算法。本文不光给出计数排序算法的传统写法,还将一步步深入讨论算法的优化,直到时间复杂度和空间复杂度最优。

先看看计数排序的定义

计数排序是一个类似于桶排序的排序算法,其优势是对已知数量范围的数组进行排序。它创建一个长度为这个数据范围的数组C,C中每个元素记录要排序数组中对应记录的出现个数。这个算法于1954年由 Harold H. Seward 提出。

下面以示例来说明这个算法

假设要排序的数组为 A = {1,0,3,1,0,1,1}

这里最大值为3,最小值为0,那么我们创建一个数组C,长度为4.

然后一趟扫描数组A,得到A中各个元素的总数,并保持到数组C的对应单元中。

比如0 的出现次数为2次,则 C[0] = 2;1 的出现次数为4次,则C[1] = 4

C索引=A元素

0

1

2

3

C元素的值,A元素的个数

2

4

0

1

A相同元素的最大索引值+1,记为新C元素

2

6

0

7

由于C 是以A的元素为下标的,所以这样一做,A中的元素在C中自然就成为有序的了,这里我们可以知道 顺序为 0,1,3 (2 的计数为0)

然后我们把这个在C中的记录按每个元素的计数展开到输出数组B中,排序就完成了。

怎么输出展开应该是该算法中最难以实现的部分;我们目标应该是

B0=0, B1=0;

B2=1, B3=1, B4=1, B5=1;

B6=3;

代码中就是处理B的index与值A[i]的关系。

B[C0-2]=A1, B[C0-1]=A4; 即 B[C[A1]-1]=A1,B[C[A4]]=A4;

B[C1-4]=A0, B[C3-3]=A3, B[C5-2]=A5, B[C6-1]=A6;

èB[C[A0]-4]=A0,B[C[A3]-3]=A3,B[C[A5]-2]=A5,B[C[A6]-1]=A6

所以可以推出计数展开的一般表达式

B[C[Ai]-k]=Ai;

在这个算法里引入是辅助数组B,其实还可以不引入数组的,假设序列的范围是0~k,在扫描一遍之后统计出一个数字i的个数c[i],那么对于所有序列中的数字,可以这样赋值

for(int i=0;i<k;++i)

{

while(c[i]--)

{

A[z++]=i;

}

}

完整代码在http://download.csdn.net/detail/mochounv/9691113

文件的CountingSort及Improved_CountingSort。

另外基数排序也比较简单RadixSort代码在RadixSort中。

发布了32 篇原创文章 · 获赞 7 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/mochounv/article/details/53321363