排序算法——桶排序、计数排序与基数排序(C++)

本文深入讲解了桶排序、计数排序和基数排序三种高效的非比较排序算法,详细介绍了它们的基本思想、复杂度分析及源码实现,是理解排序算法原理与实践应用的优质资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

桶排序

基本思想

先扫描得到待排序数组中的最大值maxVal与最小值minVal,假设桶的个数为k,则代表则将[minVal, maxVal]均分为k个范围,每个范围中的元素各自放入对应的桶中。如此桶之间必然是有序的,桶内使用排序算法进行排序,最后按序收集所有桶的元素,即完成桶排序;

复杂度

  1. 时间复杂度
    总的时间复杂度为 O(n)+O(k)O(n/klog(n/k)) = O(n+nlog(n/k))
    当 k 接近于 n 时,桶排序的时间复杂度就可以金斯认为是 O(n) 的。即桶越多,时间效率就越高,而桶越多,空间就越大。
  2. 空间复杂度:O(n+k)

源码

//桶排序
//b表示需要nums.size()/b个桶;
void BucketSort(vector<int>& nums, int b=1) {
	if (nums.size() < 2) return;
	int maxVal = INT32_MIN;
	int minVal = INT32_MAX;
	for (int i = 0; i < nums.size(); ++i) {
		maxVal = max(maxVal, nums[i]);
		minVal = min(minVal, nums[i]);
	}
	int k = (maxVal - minVal + b) / b;
	vector<vector<int>>buckets(k);
	//分配
	for (int i = 0; i < nums.size(); ++i) {
		int index = (nums[i] - minVal) / b;
		buckets[index].push_back(nums[i]);
	}
	int index = 0;
	//桶内排序与收集
	for (int i = 0; i < buckets.size(); ++i) {
		//使用其他排序方法进行桶内排序
		sort(buckets[i].begin(), buckets[i].end());
		for (auto& val : buckets[i])
			nums[index++] = val;
	}
}

计数排序

基本思想

先扫描得到待排序数组中的最大值maxVal与最小值minVal,之后分配一个长度为 maxVal-minVal+1 的计数数组,之后扫描待排序元素,将其所在的计数数组的位置加一。最后再扫描一遍计数器数组,按顺序把值收集起来。
注:计数排序实际上是桶排序的一种特例,即k=maxVal-minVal+1;

复杂度

  1. 时间复杂度:
    平均:O(n+k);最好:O(n+k);最坏:O(n+k)
  2. 空间复杂度:O(k)

源码

//计数排序
void CountSort(vector<int>& nums) {
	if (nums.size() < 2) return;
	int maxVal = INT32_MIN;
	int minVal = INT32_MAX;
	for (int i = 0; i < nums.size(); ++i) {
		maxVal = max(maxVal, nums[i]);
		minVal = min(minVal, nums[i]);
	}
	int k = maxVal - minVal + 1;
	vector<int>count(k);
	//计数
	for (int i = 0; i < nums.size(); ++i)
		++count[nums[i] - minVal];
	int index = 0;
	//收集
	for (int i = 0; i < count.size(); ++i) {
		while (count[i] > 0) {
			nums[index++] = i + minVal;
			--count[i];
		}
	}
}

基数排序

基本思想

从最低位开始,按照该位的大小进行一次稳定排序,再对下一位进行稳定排序,直至最高位结束;
注:一般会开辟一个大小为10的桶,将元素按照个位/十位/…放入对应位置,进行稳定排序;

复杂度

  1. 时间复杂度:
    平均:O(nxk);最好:O(nxk);最坏:O(nxk)
    注:k表示待排序元素中最大的位数
  2. 空间复杂度:O(n+k)

源码

//基数排序
void RadixSort(vector<int>&nums) {
	//最大位数
	int k = 0;
	for (int i = 0; i < nums.size(); ++i) 
		k = max(int(log(nums[i])) + 1, k);
	for (int i = 0; i < k; ++i) {
		//十进制
		vector<vector<int>>radix(10);
		//分配
		for (int j = 0; j < nums.size(); ++j) {
			int index = int(nums[j] / pow(10, i)) % 10;
			radix[index].push_back(nums[j]);
		}
		int index = 0;
		//收集
		for (int j = 0; j < radix.size(); ++j) {
			for (auto& r : radix[j]) {
				nums[index++] = r;
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值