计数排序
思路:它的**基本思想**是统计待排序数组中每个元素的出现次数,然后根据统计信息将元素放置到正确的位置上,从而实现排序。计数排序适用于**排序范围不大的非负整数**数组,并且可以在线性时间内完成排序。
具体步骤:
- - 找到待排序数组最大最小值。
- - 创建一个临时数组arrtmp,大小max-min+1,其数据代表下标数据出现的次数。
- - 遍历待排序数组,数据为a时,将arrtmp[a]位置加1。
- - 最后遍历临时数组,覆盖待排序数组,delete临时数组。
计数排序对待排序数组有要求:
数据大小较为集中。即max-min较小。
代码实现:
// 获取待排序数组元素中的最小和最大值。
void arrminmax(int arr[], int len, int& minvalue, int& maxvalue)
{
minvalue = maxvalue = arr[0];
for(int ii=0;ii<len;ii++)
{
if(minvalue>arr[ii]) minvalue = arr[ii];
if(maxvalue<arr[ii]) maxvalue = arr[ii];
}
}
// 计数排序主函数,arr-待排序数组的地址,len-数组的长度。
void countsort(int arr[], int len)
{
if(len<=1) return;
// 获取待排序数组元素中的最小和最大值。
int minvalue,maxvalue;
arrminmax(arr,len,minvalue,maxvalue);
// 分配并初始化临时数组。
int *arrtmp = new int[maxvalue-minvalue+1];
memset(arrtmp,0,sizeof(arrtmp));
// 临时数组计数。
for(int ii=0;ii<len;ii++) arrtmp[arr[ii]-minvalue]++;
// for (int ii = 0; ii < maxvalue-minvalue+1; ii++) cout <<ii<<":"<< arrtmp[ii] <<endl;;
// 把临时数组计数的内容恢复到到arr数组中。
int index = 0;
for(int ii=0;ii<maxvalue-minvalue+1;ii++)
{
for(int jj=0;jj<arrtmp[ii];jj++)
{
arr[index++] = ii+minvalue;
}
}
// 不要忘记堆上数据的释放!!!
delete[] arrtmp; // 释放临时数组。
}
算法分析
时间复杂度:
- 最好:O(n+k)
- 最坏:O(n+k)
- 平均:O(n+k)
空间复杂度:O(n+k)
稳定性:稳定