计数排序:
特点:
- 非比较排序
- 桶思想的一种
适用场景:量大但是范围小
- 某大型企业数万员工的年龄排序 范围(0--100)
- 如何快速得知高考名次(腾讯面试题) 范围(0--750)
以下面为例: n多个数,但是范围是0--60
第一步:开辟一个长度为范围大小的计数数组,上图为61,并赋值为0
第二步:从原数组的第一个数字开始遍历,如遍历到51,就把计数数组下标为51的值加1,0->1;再遇到就再加1,1->2;
23就把23的值加1,以此类推记录每个数出现的次数
假设最后计数数组变成:
第三步:分配一个新的数组,和原数组一样长,把计数数组里面的值传到这个数组;
如: {0,0,0,0,1,1,2,...,30,30,30,30,30,31,31,31,32,32,。。。。}
这样这个数组就是已经排好序的数组了
代码:
#include<iostream>
#include<cstring>
using namespace std;
void countingSort(int a[], int n) {
//找到最大的元素,如果知道范围就不用这一步了,直接开c数组就好了
int maxNum = a[0];
for (int i = 1; i < n; ++i)
if (a[i] > maxNum)maxNum = a[i];
int* c = new int[maxNum + 1];
memset(c, 0, sizeof(int) * (maxNum + 1));
//统计每个元素有几个
for (int i = 0; i < n; ++i)++c[a[i]];
//前缀和
for (int i = 1; i <= maxNum; ++i)c[i] += c[i - 1];
int* b = new int[n];
//反向填充
for (int i = n - 1; i >= 0; --i) {
//两种实现
/*
第一种
b[c[a[i]] - 1] = a[i];
--c[i];*/
//第二种
b[--c[a[i]]] = a[i];
}
//复制回去
memcpy(a, b, sizeof(int) * n);
//for (int i = 0; i < n; ++i)a[i] = b[i];
delete[] b;
delete[] c;
}
void Show(int* arr,int n)
{
for (int i = 0; i < n; i++)
{
cout << arr[i] << ",";
}
cout << endl;
}
int main()
{
int arr[10] = { 1,3,5,2,6,0,7,4,9,8 };
countingSort(arr, 10);
Show(arr, 10);
return 0;
}
十大经典算法复杂度及稳定性比较:https://blog.csdn.net/alzzw/article/details/98100378
冒泡排序:https://blog.csdn.net/alzzw/article/details/97906690
选择排序:https://blog.csdn.net/alzzw/article/details/97964320
插入排序:https://blog.csdn.net/alzzw/article/details/97967278
快速排序:https://blog.csdn.net/alzzw/article/details/97970371
归并排序:https://blog.csdn.net/alzzw/article/details/98047030