计数排序(六)——计数排序及排序总结

目录

一.前言

二.归并小补充

三.计数排序

操作步骤:

代码部分:

四.稳定性的概念:

五.排序大总结:

​六.结语


一.前言

我们已经进入排序的尾篇了,本篇主要讲述计数排序以及汇总各类排序的特点。码字不易,希望大家多多支持我呀!(三连+关注,你是我滴神!)

二.归并小补充

归并排序即有外排序,也有内排序,这是它的弊端所在。

当数据太多的时候,就会把数据存在磁盘中。

假设我们有大约4G的数据那要选择什么排序好呢?

我们这里不能用希尔排序,**因为在磁盘中是不支持下标访问的。磁盘的特点是顺序写,顺序读。**所以在这里只有归并排序在可以做到在磁盘中排序。

但别忘了我们还有1G的内存,我们把让小文件在里面进行排序再拿出来。这时候内存中的排序就可以用希尔排序了。

然后我们再通过合并两个有序序列的相关操作,用fscanf来读对比两个文件中谁小再fprintf写到大文件中去。

以此类推

最后我们再对两个大文件进行对比,然后覆盖写入原文件中去。

三.计数排序

思想:计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。

操作步骤:

  1. 统计相同元素出现次数
  2. 根据统计的结果将序列回收到原来的序列中

计数排序的特性总结:

计数排序在数据范围集中时,效率很高,但是适用范围及场景有限

时间复杂度:O(MAX(N,范围))

空间复杂度:O(范围)

稳定性:稳定

接下来我们开始进行分析:

每个值对应一个位置,如5就对下标为5的地方++。

对所有值开始计数

当统计好出现的次数时,我们又应该如何排序呢?

在原数组中,0出现0次那我们就覆盖写0次,1出现3次,那我们就依次覆盖写3次.......

之所以会有排序的效果是因为我们count遍历的时候是从小到大去遍历的。

该排序也是有局限性的,在我们新的数据中最大数是199,那我们就得开200个空间去遍历它们,可是前面有100空间是浪费的,因为没有数出现在那。

这种方法本质是**绝对映射,**值为多少那么下标就为多少。

为了避免空间的浪费,我们采用的相对映射 的方法,在投影下标时用该数减数据中的最小值就能得到相对位置,而在我们需要**往回去覆盖时重新+最小值就可以回到原来的位置。**这种适合范围相对集中的时候,如果出现绝对大的值那就不行了。

代码部分:

代码其实很好写,最关键的是要知道如何处理相对映射时的下标转换,以及返回覆盖时重新加上最小值。

cpp 复制代码
void CountSort(int* a, int n)
{
	//找出最大与最小
	int max = a[0];
	int min = a[0];
	for (int i = 0; i < n; i++)
	{
		if (a[i] < min)
		{
			min = a[i];
		}
		if (a[i] > max)
		{
			max = a[i];
		}
	}
	//划定范围
	int range = max - min + 1;
	//创建count数组
	int* count = (int*)malloc(sizeof(int) * range);
	if (count == NULL)
	{
		perror("malloc faile");
		return;
	}

	//初始化数组
	memset(count, 0, sizeof(int) * range);

	//开始计数
	for (int i = 0; i < n; i++)
	{
		//记住要用到相对映射
		//往count数组里面计数
		count[a[i] - min]++;
	}
	//开始覆盖,最重要的一步
	int j = 0;
	for (int i = 0; i < range; i++)
	{
		while (count[i]--)
		{
			a[j] = i + min;
			j++;
		}
	}
}

时间复杂度:O(N+range)

因为我们不仅仅要遍历原数组a,还要遍历count数组。如果数据范围很大,那么range影响就大。

对于空间复杂度也是同理。

所以计数排序适用于数据范围集中的时候。

四.稳定性的概念:

如果排完序后能保证红5还在黑5的前面,那么这个排序就是稳定的。相同数据的顺序是否变化------相对顺序)

稳定性的意义:

假设我们比赛的时候有选手的分数是相同的,那我们就要看谁先提交,那谁就排前面。

五.排序大总结:

其中选择排序之所以不稳定是因为在确保1相对稳定时,我们无法保证3的相对稳定。

而堆排序中因为堆顶的值要进行交换,所以也不能保证稳定性

快速排序也无法保证稳定性,当有3个5时,如果左边的5作key,那么它就会换到中间去,就破坏了相对顺序了。

归并是可以做到稳定的,只要我们在**取小插入的过程中把<改成<=**就行了。

六.结语

排序正式完结了,感谢大家对我的支持与陪伴,我会努力写出更通俗易懂的文章。最后感谢大家的观看,友友们能够学习到新的知识是额滴荣幸,期待我们下次相见~kk

相关推荐
鸣弦artha21 分钟前
蓝桥杯——杨辉三角
java·算法·蓝桥杯·eclipse
我是聪明的懒大王懒洋洋24 分钟前
力扣力扣力:动态规划入门(1)
算法·leetcode·动态规划
未知陨落28 分钟前
数据结构——二叉搜索树
开发语言·数据结构·c++·二叉搜索树
丶Darling.29 分钟前
Day44 | 动态规划 :状态机DP 买卖股票的最佳时机IV&&买卖股票的最佳时机III
算法·动态规划
一丝晨光1 小时前
gcc 1.c和g++ 1.c编译阶段有什么区别?如何知道g++编译默认会定义_GNU_SOURCE?
c语言·开发语言·c++·gnu·clang·gcc·g++
TN_stark9322 小时前
多进程/线程并发服务器
服务器·算法·php
汉克老师2 小时前
GESP4级考试语法知识(贪心算法(四))
开发语言·c++·算法·贪心算法·图论·1024程序员节
smj2302_796826522 小时前
用枚举算法解决LeetCode第3348题最小可整除数位乘积II
python·算法·leetcode
CyberMuse3 小时前
表的数据结构和常见操作
数据结构
爱吃生蚝的于勒3 小时前
C语言最简单的扫雷实现(解析加原码)
c语言·开发语言·学习·计算机网络·算法·游戏程序·关卡设计