【八大排序(九)】计数排序-非比较排序法

这篇具有很好参考价值的文章主要介绍了【八大排序(九)】计数排序-非比较排序法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:八大排序专栏⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习排序知识
  🔝🔝


【八大排序(九)】计数排序-非比较排序法


1. 前言

我们已经学过的:
插入排序,希尔排序,选择排序,堆排序
快速排序等等都是
比较排序
也就是需要通过数据的比较来进行排序

而这里的计数排序比较特殊
它用的是一一对应的映射关系
它不用比较数据就能排好序

【八大排序(九)】计数排序-非比较排序法

本篇文章分享的是:
计数排序思路以及代码全解


2. 计数排序基本思路

基本思路:

  • 找出数组中的最大值和最小值
  • 动态开辟一个空间
  • 元素个数为最大值-最小值+1
  • 再统计数据出现的次数

先定义一个无序数组:

int a[]={2,5,3,0,2,3,0,3};

此情况的分析:

  1. 数组最大值为5,最小值为0
  2. 开辟6个空间,统计数据出现的次数
  3. 开辟的数组中:
  4. 第一个元素对应的是最小值0的个数
  5. 最后一个元素对应的是最大值5的个数
  6. 中间的1,2,3,4不管原数组有没有都写上
  7. 统计完后重新导入原数组

画图理解:

【八大排序(九)】计数排序-非比较排序法


3. 特殊情况分析


特殊情况:最小值为0

上面举例说明中,最小值是0.
所以开辟的数组中:
下标为0的位置对应数据0的个数
下标为5的位置对应数据5的个数

当最小值不为0时:

假设我们再定义一个数组:

int a[]={1000,1200,1001,1500,1300,1301};
  1. 最大值为1500,最小值为1000
  2. 开辟一个长度为1500-1000+1=501的数组
    (注意:长度为501的数组下标范围为0~500)
  3. 我们把开辟的数组称为数组b
  4. 此时b下标为0的点对应数据1000
  5. b下标为501的点对应数据1500的个数

以此我们得出一个结论:

待排序数组中的元素X
映射到数组b的X-min的位置


画图理解:

【八大排序(九)】计数排序-非比较排序法


4. 计数排序代码实现

我们分步骤来实现:

1. 函数参数以及返回值:

//计数排序
void CountSort(int* a, int n)
{
	//...
}

2. 找最值:

	int max = a[0];
	int min = a[0];
	//找最值
	for (int i = 1; i < n; i++)
	{
		if (max < a[i])
		{
			max = a[i];
		}
		if (a[i] < min)
		{
			min = a[i];
		}
	}
	int range = max - min + 1;//动态开辟数组的元素个数
	int* count = (int*)calloc(range, sizeof(int));//将元素初始化为0

2. 计数:

//计数
	for (int i = 0; i < n; i++)
	{
		count[a[i] - min]++;
		//计数是去原数组中计数
	    //所以循环次数是n
	}

3. 根据次数进行排序:

	int j = 0;
	for (int i = 0; i < range; i++)
	{
		while (count[i]--)//只要count数组中元素不为0就赋值到原数组
		{
			a[j++] = i + min;
		}
	}
	free(count);//用完后释放空间
	count = NULL;

5. 计数排序缺陷

问题:

当数组中出现负数时.
比如:

int a[]={0,5,3,3,-1,2,0};

最小值是-1,最大值是5
这时开辟5-(-1)+1=7个空间有问题


解决方法:

我们知道-1的补码是:(32位机器下)
11111111111111111111111111111111

只需要将 -1 看作是一个无符号数
即:11111111...的无符号数是
十进制的: 4,294,967,295.

这时这个数组变成了
最大值为4,294,967,295
最小值为0.
开辟4,294,967,296个空间
进行计数排序


总结:

  • 计数排序适合数据比较集中的数组
  • 范围较大,有负数或者浮点数就不适合了

6. 计数排序复杂度分析

  1. 时间复杂度分析:

一共有三个板块:

  • 选最值.时间复杂度: O(N)
  • 计数.时间复杂度: O(N)
  • 排序.时间复杂度: O(Range)

注:N代表原数组长度.
range代表动态开辟数组长度

计数排序总时间复杂度:

O( Max(N , Range) )

  1. 空间复杂度分析:

开辟了一个大小为Range的空间

空间复杂度为:
O (Range)


7. 总结以及拓展

终于!
八大排序全部结束!

插入排序,希尔排序,选择排序,堆排序
冒泡排序,快速排序,归并排序
和本节讲的计数排序.
在实际生活中都有很多运用
并且在面试时排序是必考的内容!

要熟练掌握啊!
完结撒花!

【八大排序(九)】计数排序-非比较排序法

当然,排序部分还有稳定性
各大排序的比较,与实际运用
这最后一步放在下一章讲解
文章来源地址https://www.toymoban.com/news/detail-497869.html


🔎 下期预告:八大排序总结分析 🔍

到了这里,关于【八大排序(九)】计数排序-非比较排序法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包