什么是计数排序?计数排序的思想是什么?它是如何实现的?
本文会对计数排序进行由浅入深的探究,让你彻底掌握计数排序!
计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。
统计每个元素出现的次数,然后根据元素的大小顺序将它们放入正确的位置。
计数排序是一种小众的排序,它适合于数据密集的场景,按最大数的数值来开空间。
假设现有一组数据,最大的数据是1000,那么便会开一千个大小的空间,这种属于绝对映射,在极端的场景下,极易造成空间上的浪费,比如现在有5,99,88,1000,8888,452,635,82,777,555,只有10个数但是最大的数是8888因此要开8888大小的空间,剩余的空间全部都浪费了。
因此绝大多数情况下,都会使用相对映射。
具体的步骤如下:
//计数排序
void CountSort(int* a, int n)
{
int min = a[0];
int max = a[0];
for (int i = 0; i < n; i++)
{
if (a[i] < min)
{
min = a[i];
}
if (a[i] > max)
{
max = a[i];
}
}
int range = max - min + 1;
int* count = (int*)malloc(sizeof(int) * range);
if (count == NULL)
{
perror("malloc fail");
exit(-1);
}
memset(count, 0, sizeof(int) * range);
for (int i = 0; i < n; i++)
{
count[a[i] - min]++;
}
int j = 0;
for (int i = 0; i < range; i++)
{
while (count[i]--)
{
a[j++] = i + min;
}
}
}
a
,找到数组中的最小值 min
和最大值 max
。这是为了确定排序范围。range
,即 (max - min + 1)
,这表示需要排序的整数范围。malloc
函数为计数数组 count
分配内存,该数组的大小是排序范围 range
。计数数组用于存储每个整数在输入数组中出现的次数。memset
函数将计数数组 count
中的所有元素初始化为0。a
,对于每个整数 a[i]
,将其减去 min
的值作为索引,然后在计数数组中对应索引位置的值加1。这一步会统计每个整数在输入数组中出现的次数。count
,然后在内部循环中,根据计数数组中的值,将相应数量的整数值还原到原始输入数组 a
。这将完成排序过程。计数排序的时间复杂度为 O(n+k),其中 n 是输入数组的大小,k 是整数的范围。它具有线性时间复杂度的优点,适用于整数排序,特别是当整数范围相对较小且分布均匀时。
计数排序的空间复杂度取决于整数范围,为 O(k)。因此,它需要额外的空间来存储计数数组,当整数范围较大时可能会占用较多内存。
计数排序是一种稳定的排序算法。稳定性意味着具有相同值的元素在排序后仍保持相对顺序不变。在计数排序中,具有相同值的元素会按照它们在输入数组中的顺序被放置在输出数组中。
计数排序仅适用于整数排序,特别是当整数范围相对较小且分布均匀时。它不适用于排序包含负数或浮点数的数组。此外,如果整数范围过大,可能会导致内存占用过多。
尽管计数排序具有线性时间复杂度的优点,但它对于大规模数据集的排序可能并不理想。当整数范围非常大且分布不均匀时,计数排序的性能可能会受到限制。
计数排序适用于特定范围内的整数排序,并且在这种情况下具有稳定的性能表现。然而,在应用计数排序时,需要仔细考虑整数范围和数据集的分布情况,以确保不会出现内存占用过大或性能下降的情况。
本章专门对计数排序从概念到实现,进行了细致入微的讲解,期望对你理解掌握计数有所帮助!
看到这里希望给博主留个:点赞收藏⭐️关注!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。