开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第20天,点击查看活动详情
计数排序:
计数排序属于非比较类型的排序算法。
它的排序思想是申请一个额外的空间保存待排序序列的数值(最大最小值)可容纳的空间,待排序序列一一对应到这个空间中,将值转换为空间的索引值,也就是说待排序的对象值只能是整数,且有确定范围。它的时间复杂度比较小,O(n+k),空间复杂度占用的比较大为O(n+k)。
排序流程:
- 扫描得到待排序序列中的最大最小值 :m M,然后申请M-m+1大小的一个空间C;
- 把待排序序列的值对应到C相应的位置中,同时进行计数,直至完成待排序序列的全部对象;
- 再把c中数值返回交换到原空间中去,排序完成。
代码实例:
#include<stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include <string.h>
#include <errno.h>
#define SWAP(a1, a2, type) do {type tempNoI = a1; a1 = a2; a2 = tempNoI;} while(0)
int ArrCnt = 0;
int NumArr[200] = {0};
void PrintNums()
{
for(int i = 0;i < ArrCnt;i++){
fprintf(stdout," %d-",NumArr[i]);
}
}
//升序排序
int CountSort(int Cnt,int* ArrPtr)
{
int i = 0;
int MinVal = ArrPtr[0];
int MaxVal = ArrPtr[0];
for(i = 1;i < Cnt;i++){
if(ArrPtr[i] < MinVal) MinVal= ArrPtr[i];
if(MaxVal < ArrPtr[i]) MaxVal= ArrPtr[i];
}
fprintf(stderr,"申请额外空间大小:%d\n",MaxVal - MinVal+1);
int *C = (int*)malloc(4*(MaxVal-MinVal+1));
memset(C,0,4*(MaxVal-MinVal+1));
for(i = 0;i < Cnt;i++){
C[ArrPtr[i] -MinVal]++;
fprintf(stderr,"space [%d]=[%d]\n",ArrPtr[i] -MinVal,C[ArrPtr[i] -MinVal]);
}
int Js = 0;
for(i = 0;i < Cnt;i++){
while(C[Js] == 0){
Js++;
}
if(C[Js] > 0) {
ArrPtr[i] = MinVal+Js;
C[Js]--;
}
}
return 0;
}
int main(int argc, char** argv)
{
if(argc == 1) {
fprintf(stderr,"%s:need a some arg\n",argv[0]);
exit(1);
}
int CntTemp = ArrCnt = argc -1;
for(int i = 0;i < ArrCnt;i++){
NumArr[i] = atoi(argv[i+1]);
}
fprintf(stdout,"\t\t\t\t[Heap Sort]inputNum:");
PrintNums();
fprintf(stdout,"\n");
CountSort(ArrCnt,NumArr);
fprintf(stdout,"\n\t\t\t\tresult:");
PrintNums();
fprintf(stdout,"\n");
return 0;
}
测试结果如下:
计数排序比较简单粗暴,效率较快,额外占用空间较大,可排序的数据类型受限制。小范围数据排序使用比较好一点,不会造成较大的系统内存增长。