C语言 桶式排序 空间换时间的最快排序算法
一、算法描述
假设待排序数组有 N 个整数,且范围是 1 到 M(或 0 到 M - 1)。留置一个数组称为 buckets,大小为 M,并初始化为 0。所以数组 buckets 有 M 个单元(或 “桶” ),开始的时候它们都是空的。遍历待排序数组,当 ai 读入时 buckets[ai] 递增 1。在所有元素都遍历过后,再遍历数组 buckets,打印输出排好序的元素。
动图如下:
动图来源:https://www.bookstack.cn/read/JS-Sorting-Algorithm/8.countingSort.md
上一半蓝色的代表待排序数组,下一半灰色的代表桶数组 buckets。
核心代码如下:
/**
* @brief 桶式排序
*
* @param arr 待排序数组
* @param size 数组大小
*/
static void bucket_sort(int *arr, int size)
{
for (int i = 0; i < size; i++)
buckets[arr[i]]++;
for (int i = 0, j = 0; i < MAX; i++)
if (buckets[i] >= 1)
for (int k = 0; k < buckets[i]; k++) // 遍历重复值
arr[j++] = i; // 重新赋值
}
注意会出现 2 个 1,7 个 2 等重复值的情况,此时还要再次遍历以输出所有重复值。
二、算法分析
- 时间复杂度:O(M + N)
- 空间复杂度:O(M),即桶数组的长度,花费 M 个 “桶”
- 最好情况:O(N),当待排序数组大小和桶大小一致,且待排序数组为 “连续不重复” 的整数时,即 M = θ(N),元素均匀地放到了每一个桶中
- 最坏情况:O(M + N),待排序数组元素全一致时,元素全部放到了同一个桶中
连续不重复是指排好序的数组情况,如 5 6 3 2 1 4 9 8 7,这类情况使用桶排序是最快的。
三、完整代码
/**
* @file bucket_sort.c
* @date 2022-01-18
* @author Pineapple (pineapple_cpp@163.com)
*
* @brief 桶排序
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 100
int buckets[MAX];
/**
* @brief 桶式排序
*
* @param arr 待排序数组
* @param size 数组大小
*/
static void bucket_sort(int *arr, int size)
{
for (int i = 0; i < size; i++)
buckets[arr[i]]++;
for (int i = 0, j = 0; i < MAX; i++)
if (buckets[i] >= 1)
for (int k = 0; k < buckets[i]; k++) // 遍历重复值
arr[j++] = i; // 重新赋值
}
/**
* @brief 测试函数
*
*/
static void test()
{
const int size = rand() % 500; // 生成随机数组大小
int *arr = (int *)calloc(size, sizeof(int));
// 生成 0 ~ 99 内的随机数
for (int i = 0; i < size; i++)
arr[i] = rand() % MAX;
bucket_sort(arr, size);
for (int i = 0; i < size - 1; i++)
assert(arr[i] <= arr[i + 1]);
free(arr);
}
int main()
{
srand(time(NULL));
test();
return 0;
}
若你喜欢我的文章,欢迎关注
👇点赞
👇评论
👇收藏
👇 谢谢支持!!!