【数据结构】排序算法系列——桶排序(附源码+图解)

桶排序

算法思想

桶排序(BucketSort),也被叫做箱排序,它将整个数据组分为n个相同大小的子区间,这类子区间或称为 。输入数据是均匀、独立分布的,所以一般不会出现一个桶中装有过多数据的情况。作为一种排序算法,它会对每个桶中的数进行排序,然后直接遍历桶,最终就可以按照次序输出数据。

它的算法步骤大概如下所示:

  1. 设置定量数组作为每个桶的容量大小
  2. 遍历数据组,并将数据一个一个放到对应桶中
  3. 对非空桶中的数据进行排序
  4. 最后将数据按照大体排序放回原来序列中

图解

C语言代码解析

c 复制代码
#define CRT_SECURE_NO_WARNINGS 1
//桶排序
#include <stdio.h>
#include <stdlib.h>	

#define MAX 1000
#define BUCKET_NUM 10

//建桶中节点
struct BNode
{
	int data;
	struct Node* next;
};

//建桶
struct BNode* CreateNode(int data)
{
	struct BNode* newNode = (struct BNode*)mlooc(sizeof(struct BNode));
	newNode->data = data;
	newNode->next = NULL;
	return newNode;
}

//插入节点到链表中
void insertNode(struct BNode* head, struct BNode* newNode)
{
	struct BNode* p = head;
	while (p->next != NULL)
	{
		p = p->next;
	}
	p->next = newNode;
}

//桶排序
void BucketSort(int arr[], int n)
{
	struct BNode* bucket[BUCKET_NUM];
	for (int i = 0; i < BUCKET_NUM; i++)
	{
		bucket[i] = CreateNode(0);//创建多个桶
	}
	for (int i = 0; i < n; i++)
	{
		int index = arr[i] / BUCKET_NUM;//确定元素所在桶的位置
		struct BNode* newNode = CreateNode(arr[i]);
		insertNode(bucket[index], newNode);//插入节点到链表中
	}
	for (int i = 0; i < BUCKET_NUM; i++)//对每个桶进行排序
	{
		struct BNode* p = bucket[i]->next;
		while (p != NULL)
		{
			printf("%d ", p->data);
			p = p->next;
		}
	}
}

时间复杂度

桶排序的时间复杂度取决于以下几个因素:

  1. 将数据分配到桶的时间
  2. 对每个桶内的数据进行排序的时间
  3. 合并所有桶中的数据的时间

假设我们有 n 个元素需要排序,并且我们使用了 k 个桶。

1. 将数据分配到桶的时间复杂度

将每个元素放入对应的桶中的操作通常是一个线性的操作。对于每一个元素,确定它所属的桶位置的时间是 O(1) 的,总的时间复杂度为 O(n)。

2. 对每个桶内的数据进行排序的时间复杂度

每个桶中的数据数量决定了桶内排序的复杂度。如果所有元素均匀分布到 k 个桶中,那么每个桶中的元素大约是 n/k 个。通常,我们会在每个桶内使用一种常规的排序算法(如快速排序或插入排序)来对桶内的元素排序。

  • 如果使用插入排序或其他 O((n/k)^2) 的排序算法来对每个桶排序,那么对所有桶排序的时间复杂度为 O(k * (n/k)^2) = O(n^2/k)。
  • 如果使用更高效的排序算法(如快速排序,时间复杂度为 O((n/k) * log(n/k))),那么对每个桶排序的时间复杂度为 O(n/k * log(n/k)),所有桶的总排序时间复杂度为 O(n * log(n/k))。
3. 合并所有桶中的数据的时间复杂度

在所有桶都排序好之后,需要将它们合并起来,这个步骤的时间复杂度是 O(n)。

综合时间复杂度

综合上述三部分的分析,桶排序的平均时间复杂度为:

O(n) + O(n \log(n/k)) + O(n) = O(n \log(n/k))

桶排序的最坏情况时间复杂度

桶排序的最坏情况发生在所有元素都被分配到一个桶中,导致排序退化为对所有 n 个元素进行一次 O(n log n) 的排序。在这种情况下,桶排序的时间复杂度为:

O(n \log n)

总而言之,桶排序在数据分布均匀的情况下效率非常高,但如果数据分布不均匀或者不适合划分到桶中时,可能会退化为更高的复杂度。

稳定性

桶排序是否稳定取决于我们将元素插入桶中时是否会改变元素的相对顺序。

相关推荐
土司大王1 分钟前
LeetCode hot100——394.字符串解码:Java 双栈模拟
java·算法·leetcode
a187927218318 分钟前
【算法】双指针与滑动窗口(三):相向双指针——比较、排除、收缩
算法·leetcode·双指针·滑动窗口·原理·相向双指针·算法讲解
代码王同学12 分钟前
2026.9.15日C++类和对象学习收获笔记
c语言·c++
irislinAmelia25 分钟前
Day11文章_多路视频流加权公平调度与令牌桶QoS
c语言·人工智能
AI 小老六28 分钟前
Agent 记忆系统难在取舍
人工智能·算法·架构·agent·memory·harness
大熊背30 分钟前
《Color constancy by characterization of illumination chromaticity》之色度色域最大化算法(一)
数码相机·算法·白平衡·色度色域
不会就选b30 分钟前
算法日常・每日刷题--<贪心>13
算法
带多刺的玫瑰44 分钟前
Leecode#35刷题之搜索插入位置
java·python·算法
我不会起名字3221 小时前
万字总结Golang入门项目
数据结构·经验分享·算法·golang·项目实战·复盘
6Hzlia1 小时前
【Classic 150 刷题计划】 LeetCode 14. 最长公共前缀 | C++ 纵向扫描法与防越界细节
c++·算法·leetcode