前面排序是通过比较排序,下界就是O(nlogn)
计数排序用另外的临时空间,通过运算进行排序,可以达到线性时间O(n)
大体思路是:找到最大的数max,申请临时空间c[max+1](包括0),然后遍历一次a,根据a数组的内容在c数组中记录该数出现的次数,(a数组的内容就是c的索引,如此计数),然后c再处理一次,累计,最后倒着开始,把a数组中每个元素,根据在c里面记录的顺序,填充到输出b数组里面。
很明显,输入数组的范围比较大的话很不适合这种方法,所以这种方法虽然时间复杂度低,但是申请内存,内存开销比较大。
//计数排序
#include <iostream>
#include <string.h>
using namespace std;
inline void Swap(int &a,int &b);
void CountSort(int a[],int b[],int n);//a数组是输入数组,b数组是输出数组,n是数组个数
int main()
{
int a[10] = {1,5,10,13,16,2,4,4,7,11};
int b[10];
CountSort(a,b,10);
for(int i=0;i<10;i++)
cout<<"b[i]="<<b[i]<<endl;
}
inline void Swap(int &a,int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
void CountSort(int a[],int b[],int n)
{
int max=0;
int i;
for(i=0;i<n;i++)
if(max<a[i]) max=a[i];//找到最大值,看需要的空间
int *c;
c = new int[max+1];//计数的数组 ,0到max一共max+1个数,
memset(c,0,sizeof(int)*(max+1));
for(i=0;i<n;i++)
{
c[a[i]]++;
}
for(i=1;i<max+1;i++)
{
c[i] += c[i-1];//c[i]代表的是包括i,这个位置一共有多少个数,
}
for(i=n-1;i>=0;i--)
{
b[c[a[i]]-1] = a[i];//针对每个a[i],在c里面找到它在数组中的位置,再填充到输出b里面即可。
//c[j]是几的话,这个数a[j]应该排在输出数组b里面的第几个,所以索引要减一
c[a[i]]--;
}
delete [] c;
}