计数排序,认为是最简单的排序!

计数排序

由于用来计数的数组的长度取决于待排序数组中数据的范围,这使得计数排序对于数据范围很大的数组,需要大量时间和内存。计数排序不使用于含有非负数数组的排序。

计算排序思想

对数组{1,3,4,2,3,6}进行计数排序

计数排序步骤:

1. 找到数组中的最大值

在这里插入图片描述
代码如下

	int maxVal=0;
    //找到数组中的最大值
    for(int i:nums){
        maxVal=i>maxVal?i:maxVal;
    }
2. 申请计数数组的长度:原数组中最大值+1

计数数组元素初始化为0
原数组的最大值为6,那么申请计数数组的长度为7,并初始化为0
在这里插入图片描述
代码如下:

	vector<int> bucket(maxVal+1,0);
3. 为计数数组赋值。

统计数组中每个值为i的元素出现的次数,存入计数数组下标为i的位置.
在此例中:
数组中值为1出现了一次,存入bucket数组下标为1的位置。即bucket[1]=1.
数组中值为3出现了两次,存入bucket数组下标为3的位置。即bucket[3]=2.
数组中值为4出现了一次,存入bucket数组下标为4的位置。即bucket[4]=1.
数组中值为2出现了一次,存入bucket数组下标为2的位置。即bucket[2]=1.
数组中值为6出现了一次,存入bucket数组下标为6的位置。即bucket[6]=1.
在这里插入图片描述
代码如下:

	for(int i=0;i<nums.size();i++){
		++bucket[nums[i]];
	}
4. 反向填充到原数组

计数数组的下标对应原数组中的值
计数数组中的值对应原数组中值的个数
计数数组中的值还原到原数组的值,将计数数组计数不为0的下标值存入原数组中,每存入一次,该下标对应的计数数组中的计数减一。

原数组没有在bucket数组中计数为0的下标值(判断条件)
在这里插入图片描述
因此在还原时,如果bucket数组中的值不为0,则将此值的下标放到原数组中,再将bucket数组的值减一,即计数减一。
在这里插入图片描述
代码如下

int index=0;
for(int i=0;i<bucket.size();i++){
	while(bucket[i]!=0){
		nums[index++]=i;
		bucket[i]--;
	}
}
完整代码

计数排序完整代码如下

#include <iostream>
#include <vector>
using namespace std;
void countSort(vector<int> &nums) {
 //1.找到数组中的最大值
 int maxValue=0;
 for(auto i:nums){
   maxValue=maxValue>i?maxValue:i;
 }
 //2.初始化计数数组
 vector<int> bucket(maxValue+1,0);
 //3.为计数数组赋值
 for(int i=0;i<nums.size();i++){
     bucket[nums[i]]++;
 }
 //4.还原到原数组中
 maxValue=0;
 for(int i=0;i<bucket.size();i++){
   while(bucket[i]!=0){
     nums[maxValue++]=i;
     bucket[i]--;
   }
 }
}
int main() {
 vector<int> nums = {2, 4, 7, 8, 3, 4};
 countSort(nums);
 for (auto i : nums) {
   cout << i << " ";
 }
}


}

时间复杂度和空间复杂度

  • 时间复杂度:O(n+k)
  • 空间复杂度:O(n+k)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值