这里再介绍一种排序算法,该方法也是不需要进行元素间的比较,却能实现排序过程的。不过,与基数排序一样,它所处理的序列也有些限制:序列元素必须为非负整数,且大小有上限。
仍以序列:49、38、65、97、76、13、27、49为例。计数排序的思想在于:首先,求取该序列中最大的元素,显然为97。然后,创建一个下标为0~97的整型数组counts,且该数组的每个元素均初始化为0。接着,处理待排序序列的第1个元素,该元素是49,则令counts中下标为49的元素加1,也即,counts[49]现在由0变为1。以同样的方式顺次处理待排序序列中的所有剩下的元素。注意,最后处理到49时,同样令counts[49]的值加1,则此时的counts[49]的值变为2。显然,最终的counts数组存放了0~97这些数字在待排序序列中的出现次数(没出现过的则为0),且counts的下标恰好能实现按序排列的目的。接下来要做的就是:从下标0开始直到97,遍历counts数组,每遍历到某个下标i时,假如counts[i]为t,则输出t个i。到了最后,刚才所有的输出顺次相连,明显将形成排序后的结果。
实际上,这种排序算法不适合讨论是否稳定。不过,你可以把它视为稳定排序。代码如下:
int getMax(int list[],int length)
{
int max=0;
for(int i=1;i<length;++i)
{
if(list[i]>list[max])
max=i;
}
return list[max];
}
void countSort(int list[],int length)
{
int max=getMax(list,length);
int * counts=new int [max+1];
for(int i=0;i<=max;++i)
counts[i]=0;
for(int i=0;i<length;++i)
++counts[list[i]];
int index=0;
for(int i=0;i<=max;++i)
{
for(int j=1;j<=counts[i];++j)
list[index++]=i;
}
delete [] counts;
}
设序列元素个数为n,该序列中所有的元素均为0~max的整数。显然,无论初始序列为何种情形,都得遍历全部元素,并分别在counts相应的下标值上加1,此操作的总次数为n。然后又遍历counts以执行输出动作,该步的总操作次数为max+1+n。再算上初始时,求取待排序序列中最大值所需要的操作次数n,以及初始化counts所花费的操作次数max+1。整个排序过程总操作次数为:n+max+1+n+max+1+n=3n+2max+2。综上,时间复杂度为O(n+max)。从时间复杂度可看出,该排序是时间性能最好的排序,不过却大大牺牲了存储空间上的性能!由于要用到长度为max+1的数组counts作为辅助存储空间,该算法的空间复杂度为O(max)。