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;
}

若你喜欢我的文章,欢迎关注👇点赞👇评论👇收藏👇 谢谢支持!!!

posted @ 2022-04-07 11:37  王舰  阅读(133)  评论(0编辑  收藏  举报