基本排序算法总结与对比 之八 ——计数排序
1、计数排序
前面介绍的七种排序算法都属于 基于比较的排序算法(CBA式算法)。这类算法的共同点就是:时间复杂度最优只能到O(nlogn)。接下来包括这次介绍的三种算法都属于非比较算法,其时间复杂度平均情况下均为O(k·n),k为常数。
计数排序 又叫 鸽巢排序。就是用一个与 数列最大数数值 相等长度 的数组记录每个元素出现的次数。然后遍历记录数组,按照记录的个数打印下标。这种排序在数值小的时候特别快。
但是,也特别不实用。一是 最大数太大就得开一个特大的数组;二是 数组下标只能为非负整数。
//找出数列最大数
int findMax(int arr[], int lo, int hi)
{
int max = *(arr + lo);
while(++lo < hi)
{
if (*(arr + lo) > max) max = *(arr + lo);
}
return max;
}
void countSort(int arr[], int lo, int hi)
{
int maxNum = findMax(arr, lo, hi);
size_t *count = new size_t[maxNum + 1]; //建一个能装maxNum + 1个数的数组
for(int j = 0; j < maxNum + 1; j++) count[j] = 0; //置零
for(int i = lo; i < hi; i++)
{
count[*(arr + i)]++;
}
int *p = arr;
for(int j = 0; j < maxNum + 1; j++)
{
while(count[j]--)
{
*p++ = j;
}
}
}
显然,该算法时间复杂度为O(2n),而且是稳定的。
关于计数排序有个 特殊的 版本叫 位图排序。它只适用于无重复的非负整数数列。它的原理是开辟一段内存,用内存里的0,1表示 对应位数数值 的有无。这样可以大量节省内存空间,提高运算速度。 同样,他也特别不实用!位图排序相关内容将不再介绍。