计数排序
一句话:用辅助的数组对数组中出现的数字计数,元素转下标,下标转元素。
假设所有元素均大于等于0,依次扫描原数组,将元素值k记录在辅助数组的k位上。
依次扫描辅助数组,如果为1,将其插入目标是数组的空白位处。
问题:
-----重复元素
-----有负数
优点:快;(可以说是最快的排序算法,没有比较,直接映射)
缺点:数据范围很大,比较稀疏,会导致辅助空间很大,也稀疏,造成空间的浪费。
#include<iostream>
using namespace std;
void countSort(int arr[],int length){
int maxL=arr[0];
//求原数组元素中的最大值
for(int i=1;i<length;i++){
maxL=max(maxL,arr[i]);
}
int helper[maxL+1];
//辅助数组赋初值为0
for(int i=0;i<=maxL;i++){
helper[i]=0;
}
//遍历原数组,元素转下标,若出现,则对应位置元素+1
for(int i=0;i<length;i++){
helper[arr[i]]++;
}
int current=0;//数据回填的位置
for(int i=1;i<=maxL;i++){
while(helper[i]>0){
arr[current++]=i; //下标转元素
helper[i]--;
}
}
}
int main(){
int arr[]={6,2,5,8,2,1,9,5,6};
int len= 9;
countSort(arr,len);
for(int i=0;i<len;i++){
cout<<arr[i]<<" ";
}
return 0;
}
时间复杂度:扫描一次source,扫描一次helper,复杂度为N+k;
空间复杂度:辅助空间k,k=maxOf(source);
非原址排序;
如果要优化一下空间,可用求minOf(source),helper的长度为max-min+1,这样能短点;
计数有缺陷,数据较为密集或者范围较小是,适用。
结果:
NOTICE:
计数排序,适用数据范围小,且范围已知。