桶排序
算法思想
桶排序是计数排序(计数排序实现点这里)的一种改进和推广,其核心思想是把给定的数据分布到有限数量的桶里,每个桶再分别排序,最后把各个桶里排好序的数字合并在一起。
算法步骤:
- 设置一定数量的桶(即定义一定数量的数组,存储数据)
- 遍历待排序的数组,把每个数据放入对应的桶里
- 对非空的桶进行排序
- 把非空的排好序的桶合并起来
举个例子:arr=[29,25,3,49,9,37,21,43],这个组数据的范围是0~50,设有5个桶,每个桶可以盛放十个数组,那么把每个数字放到对应的桶里,如下图所示
然后对于非空的桶,对桶里的数据进行排序,然后合并,如下图所示
根据上述的排序过程,桶排序也是一种稳定的排序算法,是基于非比较排序的。需要定义n个桶,每个桶需要可以容纳m个数字,所以在每个桶都排序好,更新到原始数组的时候,需要循环
m
+
n
m+n
m+n 次,所以时间复杂度为
O
(
m
+
n
)
O(m+n)
O(m+n),同样的空间复杂度也是
O
(
m
+
n
)
O(m+n)
O(m+n)。
代码实现
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
/*
* 计算输入的数据对应哪个桶
*/
int bucketNum(int num, int len, int min, int max) {
return (num - min) * len / (max - min);
}
void bucketSort(vector<int>& vec) {
// 如果数据的长度小于2,直接返回
if (vec.size() < 2) {
return;
}
int min = vec[0]; // 记录整个排序数组的最小值
int max = vec[0]; // 记录整个排序数组的最大值
// 查找待排序数据的最大值和最小值
for (int i = 0; i < vec.size(); i++) {
min = min < vec[i] ? min : vec[i];
max = max > vec[i] ? max : vec[i];
}
int bucketSize = vec.size(); // 这里定义桶的数量等于数据的长度,正式的桶需要增加一个
vector<vector<int>> bucket(bucketSize+1, vector<int>()); // 这里定义bucketSize+1个桶
// 把对应的数字放进桶里
for (int i = 0; i < vec.size(); i++) {
int num = bucketNum(vec[i], bucketSize, min, max); // 计算桶号
bucket[num].push_back(vec[i]); // 对应桶添加数据
}
for (int i = 0; i < bucket.size(); i++) {
sort(bucket[i].begin(), bucket[i].end()); // 这里每个桶对应的数据是有限个,所以直接使用系统排序,也可以使用计数排序,这样时间复杂度还是O(1);
}
int index = 0; // 原始数组下标
// 把排序好的桶合并
for (int i = 0; i < bucket.size(); i++) {
for (int j = 0; j < bucket[i].size(); j++) {
vec[index] = bucket[i][j];
index++;
}
}
}
int main() {
vector<int> arr = { 5,9,-1,9,5,3,7,6,1,10,20,-30 };
bucketSort(arr);
for (int i = 0; i < arr.size(); i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
总结
- 稳定性:稳定
- 时间复杂度: O ( m + n ) O(m+n) O(m+n)
- 空间复杂度: O ( m + n ) O(m+n) O(m+n)
欢迎大家关注我的个人公众号,同样的也是和该博客账号一样,专注分享技术问题,我们一起学习进步