【C语言】选择排序及优化、冒泡排序、计数排序的实现

news2024/9/27 9:20:13

目录

  • 一、选择排序
    • 1.1 常规版(一次排好一个数)
      • 1.1.1 基本思想
      • 1.1.2 实现思路
      • 1.1.3 代码
    • 1.2 优化版(一次排好两个数)
      • 1.2.1 实现思路
      • 1.2.2 代码
    • 1.3 时间复杂度
  • 二、冒泡排序
    • 2.1 实现思路
    • 2.2 代码
    • 2.3 时间复杂度
  • 三、计数排序
    • 3.1 基本思想
    • 3.2 实现思路
    • 3.3 时间和空间复杂度
  • 总结


一、选择排序

1.1 常规版(一次排好一个数)

1.1.1 基本思想

每次从待排序的数据中选出一个最小(最大)值,从起始位置开始存放,每排好一个数,存放位置就会向后移一位,直到排所有的数据排完序。

在这里插入图片描述

1.1.2 实现思路

  1. 假设起始位置(i)是最小的,通过变量(minIndex)保存该下标
  2. a[mini]从该下标(i)的下一个位置(i+1)开始去数据中依次比较
  3. 找到比自己小的数据,就把mini设为小的下标,循环还没有结束,所以还会用mini位置的值去和后面的值比较。
  4. 数据都比较完后,minIndex位置的值就是全部数据中最小的,如果minIndex不等于i(一开始i和minIndex的值一样,找到最小了的值后minIndex的会被改变),就需要交换两个位置的值,相等i的位置就是最小值,不用动。(加这个判断是防止数据是有序的,有序就没有必要交换)
  5. i+1,为了把排好的数据给排除掉,i再去在找数据中最小的值,重复以上操作,直到i < n - 1结束。

注意:循环结束如果到i < n结束,在找数据时候就会越界如n = 1,i + 1就会越界,并且当已经排好了n-1个数后,最后一个元素已经是最大的元素,不需要再进行比较和交换操作了。

1.1.3 代码

// 选择判断(常规版,选一个数)
void SelectSort(int* a, int n)
{
	// n-1个数排好了,最后一个数就是正确的位置,不用在排序
	for (int i = 0; i < n - 1; i++)
	{
		int minIndex = i;
		for (int j = i + 1; j < n; j++)
		{
			if (a[j] < a[minIndex])
			{
				minIndex = j;
			}
		}

		// minIndex改变了需要交换,minIndex的位置就是最小值
		// 没有改变,i的位置就是最小值,不用动
		if (i != minIndex)
		{
			Swap(&a[i], &a[minIndex]);
		}
	}
}

1.2 优化版(一次排好两个数)

选择排序的优化版和常规版,大体思路还是差不多的,只不过每次选出数据中的最小值和最大值。

1.2.1 实现思路

  1. begin和end标识数据的区间,注意是闭区间
  2. 最小值(minIndex)从begin(最左边)开始放,最大值(maxIndex)从end(最右边)开始放。
  3. 排好两个数据后,begin往后走,end往前走,排除已排好的数据(缩小区间),直到begin和end相遇就表示排好了。

特殊情况:
在这里插入图片描述

所以我们进行判断,max不等于begin,我们才进行交换,因为begin和min先交换,begin和max重叠,在begin位置的值就会被换走,如果让end和max先交换,还是会有这种问题,不过情况相反而已,所以这个条件必须要加

1.2.2 代码

// 选择判断(优化版,两个数)
void SelectSort_double(int* a, int n)
{
	int begin = 0, end = n - 1;
	while (begin < end)
	{
		// 一次选出最小值和最大值
		int minIndex = begin, maxIndex = end;
		for (int i = begin; i <= end; i++)
		{
			if (a[i] < a[minIndex])
			{
				minIndex = i;
			}

			if (a[i] > a[maxIndex])
			{
				maxIndex = i;
			}
		}

		if (minIndex != begin)
			Swap(&a[minIndex], &a[begin]);
		
		
		// max和begin重叠,maxIndex的值已被换到minIndex位置
		if (maxIndex == begin)
			maxIndex = minIndex;

		if (maxIndex != end)
			Swap(&a[maxIndex], &a[end]);

		begin++;
		end--;
	}
}

1.3 时间复杂度

时间复杂度为 O ( N 2 ) O(N^2) O(N2),最差的排序,最好情况下也是 O ( N 2 ) O(N^2) O(N2),数据有序的情况也要比较。


二、冒泡排序

2.1 实现思路

  1. 每次就排好一个数,第一个数据和第二数据先比较在交换,小的在前,大的在后,第二个数据在第三个数据交换,一直反复下去。a[j] > a[j + 1]
  2. 该过程会把小数据(不是最小,只是相比下小数据)交换到前面,直到交换到最后一个数据,最大的数据就在最后面了(比他小的数据都交换在他前面了),为了防止后面数据都是有序,用一个变量标识下(交换了没有),如果后面数据有序继续比较和交换效率低,我们做一下判断,如果有序(没有交换),我们就可以直接跳出。
  3. 排好一个数后,就排除已排好的数据(缩小区间),直到只剩最后一个数,如果有n个数,只需要交换n-1次j < n - 1 - i
  4. 一共只需要排n-1个数,和常规选择排序一个情况,n-1个数有序了,剩余的1个数肯定是有序的,就等于自己和自己比较在交换,无意义。

在这里插入图片描述

在这里插入图片描述

2.2 代码

// 冒泡排序
void BubbleSort(int* a, int n)
{
	// 最多排9个数(趟),9个数排好后,第10数就在排好的位置
	for (int i = 0; i < n - 1; i++)
	{
		// 标识是否交换,默认是没交换
		int exchange = 1;	
		// 最多交换9次,最后一次是自己和自己交换,所以只需要排9次
		for (int j = 0; j < n - 1 - i; j++)
		{
			if (a[j] > a[j + 1])
			{
				Swap(&a[j], &a[j + 1]);
				exchange = 0;	// 数据交换了
			}
		}
		
		// 数据没有交换,表示有序,就直接跳出
		if (exchange)
			break;
	}
}


冒泡和插入相比哪个更好?

插入排序,对有序,接近有序,局部有序,适应性更强
用一个接近有序的数据,对比执行次数,就能比较出来。


2.3 时间复杂度

时间复杂度为 O ( N 2 ) O(N^2) O(N2)

三、计数排序

计数排序属于非比较排序,只能排整形。

3.1 基本思想

先统计数据出现次数,写到相对的下标里,在通过数据对应的下标来进行从头依次排序,下标位置有几个数,就需要排几个数,数据值和下标相对的。
在这里插入图片描述

3.2 实现思路

  1. 计算出数据的范围区间,最大值减去最小值,这是相对范围min——max,绝对范围是0——max,太浪费空间。
  2. 创建一个计数数组count,因为是闭区间,大小是max-min+1,用来存放数据出现的次数,初始化都是0。
  3. 统计每个数出现的次数,放入到数据减去最小值的下标位置(计数数组的相对位置)。
  4. 把数据写到原数组里,只写次数不为0的,出现了几次就写入几个数据,数据通过count的下标+最小值还原出来。
// 计数排序
void CountSort(int* a, int n)
{
	// 找到最小值和最大值
	int min = a[0], max = a[0];
	for (int i = 1; i < n; i++)
	{
		if (a[i] < min)
			min = a[i];

		if (a[i] > max)
			max = a[i];
	}

	// 计算出相对范围
	int range = max - min + 1;

	// 创建计数数组,初始化为全0
	// 方法1
	int* count = (int*)malloc(range * sizeof(int));	
	assert(count);
	memset(count, 0, range * sizeof(int));

	// 方法2,calloc申请的空间默认都是NULL或0(根据指针类型决定)
	//int* count = (int*)calloc(range * sizeof(int));	

	// 统计每个数出现的次数
	for (int i = 0; i < n; i++)
	{
		count[a[i] - min]++;
	}
	
	// 把数组写入原数组
	// 数据出现了多少次就写入多少个值
	int j = 0;
	for (int i = 0; i < range; i++)
	{
		while (count[i]--)
		{
			a[j++] = i + min;
		}
	}
}

3.3 时间和空间复杂度

时间复杂度为 O ( N + K ) O(N+K) O(N+K),K是相对范围(计数数组)的大小。
空间复杂度为 O ( K ) O(K) O(K)


总结

  • 选择排序时间复杂度为 O ( N 2 ) O(N^2) O(N2),空间复杂度为 O ( 1 ) O(1) O(1)
  • 冒泡排序时间复杂度为 O ( N 2 ) O(N^2) O(N2),空间复杂度为 O ( 1 ) O(1) O(1)
  • 计数排序时间复杂度为为 O ( N + K ) O(N + K) O(N+K),K是相对范围(计数数组)的大小,空间复杂为 O ( K ) O(K) O(K)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2125821.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DroidBot-GPT: GPT-powered UI Automation for Android论文学习

本文介绍了DroidBot GPT&#xff0c;这是一种利用类似GPT的大型语言模型&#xff08;LLM&#xff09;自动化与Android移动应用程序交互的工具。给定所需任务的自然语言描述&#xff0c;DroidBot GPT可以自动生成并执行导航应用程序以完成任务的操作。它的工作原理是将应用程序G…

99.游戏安全项目-可见数据的搜索与技巧

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;易道云信息技术研究院 上一个内容&#xff1a;98.游戏的启动与多开-分析与实现多开器 下图中红框位置显示的数据&#xff0c;只有下图…

Avaloia 实现国产麒麟系统中文显示界面

最近在搞一个国产麒麟系统的接口对接&#xff0c;因为&#xff0c;接口内含复杂的签名验证&#xff0c;而且还是离线环境&#xff0c;所以&#xff0c;postman不是很好用。 就想着哪个方式好一些&#xff0c;主要是有选择图片的操作&#xff0c;所以&#xff0c;在Electron和A…

有了它,Python性能瓶颈消失!

声明&#xff1a;此篇为 ai123.cn 原创文章&#xff0c;转载请标明出处链接&#xff1a;https://ai123.cn/#1 作为一名互联网行业的Python工程师&#xff0c;你是否也遇到过解释型语言在处理大量数据时速度较慢、内存占用高、并行处理困难、调试复杂、扩展性差和性能瓶颈等各种…

OpenCV-模板匹配多个目标

文章目录 一、基本概念二、基本步骤1.图像准备2.图像预处理3.执行模板匹配4.定位匹配区域5.处理多个匹配6.优化和验证 三、代码实现1.图片读取2.图像预处理3.模板匹配4.绘制矩形框 三、总结 模型匹配&#xff08;Model Matching&#xff09;是一个广泛应用的概念&#xff0c;其…

练练演活姜迎紫 入围金鹰奖提名演技派实至名归

近日&#xff0c;悬疑剧《雪迷宫》正在CCTV-8热播&#xff0c;演员练练凭借其精湛的演技演活姜迎紫一角&#xff0c;塑造的大嫂形象深入人心&#xff0c;赢得了观众的一致好评&#xff0c;成为该剧的一大亮点&#xff0c;成功闯入“内娱大嫂”的赛道。而近日&#xff0c;练练也…

贪心+滑窗+递推,LeetCode 2555. 两个线段获得的最多奖品

一、题目 1、题目描述 2、接口描述 python3 ​ class Solution:def maximizeWin(self, prizePositions: List[int], k: int) -> int:cpp ​ class Solution { public:int maximizeWin(vector<int>& prizePositions, int k) {int n prizePositions.size();std…

windows通过wsl2安装linux系统之Ubuntu,傻瓜式安装

期望通过每一次分享&#xff0c;让技术的门槛变低&#xff0c;落地更容易。 —— around 目录 1.基础环境和要求2.安装wsl23.安装linux系统4.迁移linux系统挂载5.配置linux账号密码6.配置ssh登录方式待续… 前言 为什么要在windows上安装linux&#xff0c;这个问题当你是研发…

Kubernetes动态分配存储卷组件 nfs-subdir-external-provisioner

Kubernetes动态分配存储卷组件 nfs-subdir-external-provisioner 存储组件 nfs-subdir-external-provisioner 是一个存储资源自动调配器&#xff0c;它可用现有的 NFS 服务器通过持久卷声明来支持 Kubernetes 持久卷的动态分配&#xff0c;自动创建的文件夹将被命名为 n a m …

Note24091101_基恩士日期获取相关测试01

基恩士日期获取相关测试 1、SEC和RSEC的使用&#xff1a; 资料如图&#xff1a; 要点提示&#xff1a;SEC和RSEC成对使用。 日期转秒&#xff0c;秒转日期测试如图所示&#xff1a; 2. LDWK与LDWKB星期接点的使用示例&#xff1a; 资料如图&#xff1a; 仿真如图&…

chapter14-集合——(List)——day18

目录 518-Set接口方法 518-Set接口方法

Rickdiculously Easy靶场渗透测试

靶机下载地址 https://www.vulnhub.com/entry/rickdiculouslyeasy-1,207/ 一.信息收集 1.端口扫描 nmap 172.16.1.20 -p- -sV 发现还扫描出一个flag 2.目录扫描 二.获取shell和提权 1、访问靶机IP地址 2、拼接并访问robots.txt文件 3、逐个访问&#xff0c;发现cgi-bin/tr…

‌移动管家手机智能控制汽车系统

‌ 手机可以通过下载特定的应用程序来控制汽车系统&#xff0c;实现远程启动、锁/解锁车门、调节车内温度等功能。‌ ‌ 手机智能控制汽车系统主要通过下载并安装特定的APP来实现。‌ 首先&#xff0c;用户需要确定自己的手机系统是安卓还是苹果版&#xff0c;然后前往应用…

图像和文本统一识别

图像和文本统一识别&#xff08;UNIT&#xff09;是一种尝试将图像识别和文本识别任务统一到单一模型中的技术。这种方法的目标是提高模型在处理包含文本信息的图像时的效率和准确性&#xff0c;从而使模型能够更好地理解和处理视觉内容中的文本信息。 使用的技术&#xff1a;…

浮毛危害人体健康?希喂、安德迈、有哈宠物空气净化器吸毛测评

养宠之前了解清楚相关的知识&#xff0c;这既是对宠物负责&#xff0c;也是对我们自己负责。宠物最让铲屎官头疼的就是毛发问题&#xff0c;大量脱落的毛发会带来繁重的清理任务&#xff0c;同时飘在空中浮毛还是潜藏在身边的健康”杀手“。浮毛微小、质量轻&#xff0c;容易随…

JAVA 使用POI实现单元格行合并生成

预期效果 maven引用 <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.2</version></dependency>Java代码实现 功能实现 private boolean callExcel(List<MColumnValueVo&g…

Nignx 增加权限(windows)

Nignx 增加权限&#xff08;windows&#xff09; 1、nginx增加权限配置 问题描述&#xff1a; windows下路径含有空格和路径符号产生的问题 server {listen 9025;server_name localhost;# 验证时的提示信息auth_basic "请输入用户和密码"; # 认证文件auth_b…

鸿蒙界面开发——组件(7):组件导航 页面路由

组件导航 (Navigation)(推荐) Navigation() Navigation(pathInfos: NavPathStack)Navigation是路由容器组件&#xff0c;一般作为首页的根容器&#xff0c;包括单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。Navigation组件适用于模块内和跨模块的路由切换&#xff0c…

【论文阅读笔记】Tackling the Generative Learning Trilemma with Denoising Diffusion GANs

【论文阅读笔记】Tackling the Generative Learning Trilemma with Denoising Diffusion GANs Introduction方法 使用传统GANS建模去噪分布理解模式覆盖率 Paper&#xff1a;https://arxiv.org/abs/2112.07804 Code&#xff1a;https://github.com/NVlabs/denoising-diffusion-…

大模型LLM部署学习

1、推理工具vLLM vLLM使用指北 https://zhuanlan.zhihu.com/p/685621164 VLLM官方文档 Welcome to vLLM! — vLLM 2、RAG&#xff08;检索增强生成&#xff09; https://zhuanlan.zhihu.com/p/675509396 RAG就是通过检索获取相关的知识并将其融入Prompt&#xff0c;让大模…