01 计数排序算法概念
计数排序不是一个比较排序算法,该算法于1954年由 Harold H. Seward提出,通过计数将时间复杂度降到了O(N)
。
02 基础版算法步骤
第一步:找出原数组中元素值最大的,记为max
。
第二步:创建一个新数组count
,其长度是max
加1,其元素默认值都为0。
第三步:遍历原数组中的元素,以原数组中的元素作为count
数组的索引,以原数组中的元素出现次数作为count
数组的元素值。
第四步:创建结果数组result
,起始索引index
。
第五步:遍历count
数组,找出其中元素值大于0的元素,将其对应的索引作为元素值填充到result
数组中去,每处理一次,count
中的该元素值减1,直到该元素值不大于0,依次处理count
中剩下的元素。
第六步:返回结果数组result
。
03 基本原理
04 优化
基础版能够解决一般的情况,但是它有一个缺陷,那就是存在空间浪费的问题。
比如一组数据{101,109,108,102,110,107,103}
,其中最大值为110,按照基础版的思路,我们需要创建一个长度为111的计数数组,但是我们可以发现,它前面的[0,100]
的空间完全浪费了,那怎样优化呢?
将数组长度定为max-min+1
,即不仅要找出最大值,还要找出最小值,根据两者的差来确定计数数组的长度。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main(){
void count_sort(int *arr,int size);
int a[]={0,1,5,4,8,6,3,4,8,3};
count_sort(a,10);
int i;
for(i=0;i<10;i++){
printf("%5d",a[i]);
}
printf("\n");
}
void count_sort(int *arr,int size){
int i;
int min=arr[0];
int max=arr[0];
int range=0;
int *temp=0;
int count=0;
for(i=0;i<size;i++){
if(arr[i]<min){
min=arr[i];
}
if(arr[i]>max){
max=arr[i];
}
}
range=max-min+1;
temp=(int *)malloc(sizeof(int)*range);
if(temp==NULL) return;
memset(temp,0,sizeof(int)*range);
for(i=0;i<size;i++){
temp[arr[i]-min]++;
}
int j=0;
for(i=0;i<range;i++){
while(temp[i]--){
arr[j++]=i+min;
}
}
free(temp);
}