经典排序算法之计数排序|c++代码实现

 引言

排序算法c++实现系列第8弹——计数排序。

计数排序是理解起来相对简单的一个排序算法,

计数排序

计数排序(Counting Sort)是一种非比较型的排序算法,它的基本思想是统计待排序数组中每个元素的出现次数,然后根据统计信息将元素放置到正确的位置上,从而实现排序。计数排序适用于排序范围不大的非负整数数组,并且可以在线性时间内完成排序。

算法步骤

  1. 确定数据范围:寻找数据中的最大值和最小值。

  2. 统计频次:遍历待排序数组,统计每个元素出现的次数,并将统计结果存储在一个辅助数组(计数数组)中。

  3. 累加频次:对计数数组进行顺序累加,方便后续排序操作中得到原数组中每个数的下标位置。

  4. 排序:遍历待排序数组,根据元素的值和计数数组的统计信息,将元素放置到正确的位置上。

  5. 输出:将排序后的数组输出,排序完成。

算法的核心步骤如上,仅看步骤可能还是难以理解,可以联系着代码一起看。这边也推荐一个我个人觉得会让算法不那么抽象的学习方法:当在学习某一算法时,可以先去b站搜该算法的简单动图演示,大概了解步骤后,再来看以上的步骤总结和代码实现,事半功倍。

这里借助一个实实在在的例子,向大家演示计数排序算法:假设有 a[] = {1,2,3,5,6,7,3};

  1. 寻找最大值max=7;最小值min=1。

  2. 创建一个新数组b作为计数数组,将a遍历统计每个数据出现的频次。

for (int i = 0; i < len; i++) {
		a[arr[i] - min]++; //arr[i] - min即将输入的数据值转化为的键
	}
// 如 a[arr[0]-min] = a[1-1] => a[0] = 1;
// a[arr[1]-min] = a[2-1] => a[1] = 1;

特点

  • 计数排序是一种稳定的排序算法,相同元素的相对位置在排序后保持不变。

  • 计数排序的时间复杂度为O(n+k),其中 n 为待排序数组的长度,k为待排序数组中的最大值与最小值之差加一。

  • 计数排序适用于待排序数组元素范围不大的情况,如果待排序数组范围较大,计数数组的空间消耗会增加。

代码

#include<bits/stdc++.h>
using namespace std;
int main() {
	int max = INT_MIN, min = INT_MAX;
	int arr[] = {61, 17, 29, 22, 34, 60, 72, 21, 50, 1, 62};
	int len = (int) sizeof(arr) / sizeof(*arr);
	// 寻找数组的max和min,以便建立计数数组 
	for (int i = 0; i < len; i++) {
		max = max < arr[i] ? arr[i] : max;
		min = min > arr[i] ? arr[i] : min;
	}
//	printf("max:%d,min:%d\n", max, min);
	int d = max - min + 1;  // 计数数组长度 
	int a[d] = {0};  // 计数数组 
	for (int i = 0; i < len; i++) {
		a[arr[i] - min]++;
	}

	for (int i = 1; i < d; i++) {
		a[i] += a[i - 1];  // 对次数累加,方便后续得到每个数的index 
	}
	int b[len] = {0}; // b[]存放排序后的数组 
	for (int i = len - 1; i >= 0; i--) {// 从后往前排序-->稳定排序算法 
		int index = a[arr[i] - min] - 1;  // 遍历a[]中每一个数,确定其index 
		b[index] = arr[i];
		a[arr[i] - min]--;
	}
	for (int i = 0; i < len; i++) {
		arr[i] = b[i];
		printf("%d ", arr[i]);
	}

	return 0;
}

运行结果展示

系列其他文章

十大经典排序算法复杂度、应用场景总结 | 插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序、桶排序、计数排序-CSDN博客 

经典排序算法之桶排序详解|c++代码实现|简单易懂-CSDN博客

经典排序算法之基数排序详解|c++代码实现|简单易懂-CSDN博客

经典排序算法之堆排序详解|c++代码实现|什么是堆排序|如何代码实现堆排序-CSDN博客

经典排序算法之快速排序|c++代码实现|什么是快速排序|如何代码实现快速排序-CSDN博客

经典排序算法之归并排序|递归和迭代法代码均提供|c++代码实现|什么是归并排序|如何代码实现-CSDN博客

经典排序算法之希尔排序|c++代码实现||什么是希尔排序|如何代码实现-CSDN博客

经典排序算法之插入排序|c++实现|什么是插入排序|如何代码实现-CSDN博客

排序算法之选择排序|c++实现-CSDN博客

经典排序算法之冒泡排序|c++代码实现-CSDN博客

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃香菜的小趴菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值