计数排序
一、什么是计数排序
当我们排序的时候,是对于一定范围的字符进行排序的。
比如如果是a-z26个字母排序,这个时候可能出现的字母总数一共是26个,依次遍历字母出现的顺序,然后按照字母顺序以及出现的次数重新排列就可以了。
如果是数字排序,也是这样,找到出现的数字的范围,然后对于范围以内的进行遍历,确定不同的数字出现的次数,然后按照次数一次排序。
二、例子
例子一
有这样的字母: abdefde
当我们遍历的时候得到如下的表格
字母 | a | b | c | d | e | f |
遍历之后得到每个字母出现的次数 | 1 | 1 | 0 | 2 | 2 | 1 |
随后按照每个字母的顺序,出现几次就排几个,排序之后出现的结果如图所示:
秩 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
字母 | a | b | d | d | e | e | f |
例子二
有这样的一组数字:
当我们遍历之后得到该范围内每个数字的出现次数:
数字 | 7, | 8 | 9 | 10 | 11 |
出现次数 | 1 | 2 | 1 | 0 | 1 |
当我们按照每个数字出现的次数由大到小排序之后:
秩 | 0 | 1 | 2 | 3 | 4 |
数字 | 7 | 8 | 8 | 9 | 11 |
三、算法实现
对于数字排序的过程加以说明:
上面的数字中,我们找到数字的最大值与最小值,这样获得了排序的元素范围以及大小
我们可以看到:
int max=11, min=7 ;
随后我们设置一个大小为 size= max-min+1 的数组,用来记录每一个元素出现的次数。
接着就是遍历整个数组,获得元素出现的次数。
之后按照出现次数以及元素的顺序重新排列即可。
四、代码实现
这里的代码实现用的是这位大佬的(我觉得写的很好,所以就不写啦。)
链接:https://blog.csdn.net/KKnick1/article/details/99735120
private int[] countSort(int arry[]) { //获得数组的最大值和最小值 int min = arry[0], max = arry[0]; for (int i = 0; i < arry.length; i++) { if (arry[i] > max) { max = arry[i]; } if (arry[i] < min) { min = arry[i]; } } //对于原始数组的出现的每一个元素计数 int size = max - min + 1; int[] arryCount = new int[size]; for (int i = 0; i < arry.length; i++) { arryCount[arry[i] - min]++; } //排序 int size1 = 0; int[] sortedArray = new int[arry.length]; for (int i = 0; i < arryCount.length; i++) { for (int j = 0; j < arryCount[i]; j++) { arry[size1] = min + i; size1++; } } return sortedArray; }
在这里说明一下,在扫描计数的时候:
我们认为记录数据出现次数的数组:秩为0的位置对应数字min,这样他们的秩与数字的对应关系就是: a[i] 对应 i + min
五、适用条件
1、如果需要排序的元素种类不是太多,可以使用
2、不适用于小数
复杂度: O(n + k) 其中n是待排序数据规模, k 是需要排序字符种类数目,也就是另外开辟的记录数据出现次数的数组大小。