【数据结构】【排序算法】桶排序

前言

在之前的计数排序中,排序成员只能为整数型,不能对浮点型的成员进行排序。对此,桶排序(Bucket sort)是弥补了这一缺点的排序算法。

实现原理

对于桶排序而言,其核心思想是分治思想(化大为小)。
首先,根据数据成员的值和个数进行范围划分(确定桶的范围,桶的数量):
每个桶的范围长度
R = V m a x − V m i n N e l e m + 1 R = \frac{V_{max}-V_{min}}{N_{elem}}+1 R=NelemVmaxVmin+1
桶的个数
N = V m a x − V m i n R + 1 N = \frac{V_{max}-V_{min}}{R}+1 N=RVmaxVmin+1
根据上述的公式,可以确定每个桶的范围分别为:
[ b 1 , b 2 , b 3 , . . . , b N B u c k e t ] ⇒ [ [ V m i n , V m i n + R ) , [ V m i n + R , V m i n + 2 ∗ R ) , . . . , [ V m i n + ( N − 1 ) ∗ R , V m i n + N ∗ R ) ] [b_1,b_2,b_3,...,b_{N_{Bucket}}]\Rightarrow [[V_{min},V_{min}+R),[V_{min}+R, V_{min}+2*R),...,[V_{min}+(N-1)*R,V_{min}+N*R)] [b1,b2,b3,...,bNBucket][[Vmin,Vmin+R),[Vmin+R,Vmin+2R),...,[Vmin+(N1)R,Vmin+NR)]
其次,根据该关系,扫描待排序成员,将其放在符合范围内的桶中:
例如,{5.1,2.3,3.9,6.6,9.6,10.5},R和N分别为:R = (10.5-2.3)/6 +1 = 2 和 N = 8.2/2 + 1 = 5
在这里插入图片描述
之后,对每个桶的元素进行排序。
最后,依次输出每个桶的元素,构成最终的排序结果。

实现代码:
头文件:

class BucketSort {
public:
	BucketSort(std::vector<double>& ele);
	~BucketSort() {};
	void Sort();
	double operator[](int i)const;
private:
	std::vector<double> elements;
};

根据上述原理,实现的桶排序:

BucketSort::BucketSort(std::vector<double>& ele):elements(ele) {};
void BucketSort::Sort() {
	//求出最小值与最大值
	auto minmax_v = std::minmax_element(elements.begin(), elements.end());
	double min = *minmax_v.first, max = *minmax_v.second;
	double range = (max - min) / elements.size()+1;
	int nums = static_cast<int>((max - min) / range + 1);
	//初始化桶容器
	std::vector<std::vector<double>> bucket(nums);
	//桶容器分配元素
	for (auto item : elements) {
		for (int i = 0; i < nums; i++) {
			if (item < (min + (i + 1) * range) && item >= (min + i * range))
				bucket[i].push_back(item);
		}
	}
	//针对桶的内容进行排序
	for (int i = 0; i < nums; i++) std::sort(bucket[i].begin(), bucket[i].end());
	//进行排序
	int count = 0;
	for (int i = 0; i < nums; i++) {
		for (auto item : bucket[i]) {
			elements[count++] = item;
		}
	}
}
double BucketSort::operator[](int i) const{
	return elements[i];
}

结果:
a1d8d4935e4d1.png)

int main()
{
	std::vector<double> elem= { 0.8, 9.2, 3.4, 8.4, 5.6, 1.1, 6.5, 6.4 };
	BucketSort bs(elem);
	bs.Sort();
	for (int i = 0; i < elem.size(); i++) std::cout << bs[i] << ",   ";

	return 0;
}

上述代码仍存在部分问题:①分配元素的过程为O(N^2),可优化为O(N),关键在元素分配给对应桶的计算过程;②分配的变量过多,可以进一步删减等。后续会进行优化和更新。

程序复杂度

在时间复杂度上,桶排序的平均时间复杂度为O(n),最坏时间复杂度为O(nlogn),空间复杂度为O(N),桶排序在对等值元素进行排序是稳定的。

注意事项

在待排序元素的值分布为不均匀时,尤其是极端不均匀情况下,会出现第一个桶有n-1个元素,而最后的桶只有一个元素的问题,白白浪费空间。

  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值