桶排序

桶排序

算法思想

桶排序是计数排序(计数排序实现点这里)的一种改进和推广,其核心思想是把给定的数据分布到有限数量的桶里,每个桶再分别排序,最后把各个桶里排好序的数字合并在一起。

算法步骤:

  1. 设置一定数量的桶(即定义一定数量的数组,存储数据)
  2. 遍历待排序的数组,把每个数据放入对应的桶里
  3. 对非空的桶进行排序
  4. 把非空的排好序的桶合并起来

举个例子: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)

欢迎大家关注我的个人公众号,同样的也是和该博客账号一样,专注分享技术问题,我们一起学习进步
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值