排序1——C语言

排序

  • 1. 复杂度
  • 2. 插入排序
    • 2.1 直接插入排序
    • 2.2 希尔排序
  • 3. 选择排序
    • 3.1 直接选择排序
    • 3.2 堆排序

排序在生活中很常见,比如在网购时,按价格排序,按好评数排序,点餐时,按评分排序等等。而排序有快和慢,快的排序效率高,慢的排序效率低,需要的时间也多。下面就一一介绍各种排序。介绍排序算法时,统一以 升序为例。

1. 复杂度

当一个算法编写完成后,运行时需要消耗时间和空间资源。因此,衡量一个算法的好坏,需要从时间和空间两个维度来衡量,即时间复杂度和空间复杂度。

时间复杂度是衡量快慢的,空间复杂度是衡量该算法运行所需的额外空间。现如今,计算机的内存空间已经很大了,因此空间复杂度已经不是特别关注了。

时间复杂度是一个函数,一个算法的基本操作的执行次数就是该算法的时间复杂度。

void Func1(int N)
{
	int count = 0;
	for (int i = 0; i < N; ++i)
	{
		for (int j = 0; j < N; ++j)
		{
			++count;
		}
	}
}

比如这段代码主要执行的是++count语句,计算该语句的执行次数。

可以看到,++count外套了两层循环,外循环每执行一次,内循环执行N次,而外循环执行了N次,因此++count语句执行了N^2次。算法的执行次数最多的语句一般在循环内部。因此计算时间复杂度,首要计算的就是循环内的。而这个函数可能是若干多项式的和,我们不可能把这个算法的时间复杂度算的非常清楚,只需要知道大概就可以了。因此时间复杂度采用大O渐进表示法

大O渐进表示法:
1.在这个运行次数的函数中,只保留最高阶的那一项,比如10N^2+2N+2---->10N^2
2.如果最高阶存在并且不是1,那么将该项的系数化为1,比如10N^2 —>N^2

最终我们就得到了一个很简单的函数。此外,有些算法的时间复杂度在不同情况下会有不同,因此需要计算最坏情况和最好情况,有些排序算法就存在这种情况。

空间复杂度也是一个函数,是对一个算法在运行过程中临时占用存储空间大小的量度 。
空间复杂度计算规则基本跟时间复杂度类似,也使用大O渐进表示法。空间复杂度计算的是额外使用的空间的大小,不包括本身对变量开辟的空间。

复杂度主要有以下几种
在这里插入图片描述

其中含有对数的主要是以2为底数的。

2. 插入排序

2.1 直接插入排序

思想:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。

什么意思呢?我们举一个例子,比如将排序5,9,7,6,2
排序过程如下。
在这里插入图片描述
当数组遍历完,得到的就是有序的数组了。

void InsertSort(int* array, int numsArr)//待排序数组和数组大小
{
	//插入numsArr-1次
	for (int i = 0; i < numsArr - 1; i++)
	{
		int end = i;
		int tmp = array[end + 1];

		while (end >= 0)
		{
			//后移
			if (array[end] > tmp)
			{
				array[end + 1] = array[end];
				--end;
			}
			else
			{
				break;
			}
		}
		array[end + 1] = tmp;
	}
}

直接插入排序的时间复杂度分最好情况和最坏情况,最好情况是数组本就有序,不需要插入,但是需要遍历一遍数组,所以时间复杂度为O(N);最坏情况是数组逆序,插入的次数是1,2,3,4…N-3,N-2,N-1次,数据是一个等差数列,计算出来为**(N^2-N)/2** 根据大O渐进表示法最终化简为O(N^2);

结论:最坏情况O(N^2)最好情况O(N)
空间复杂度O(1),表示没有用到额外空间。

2.2 希尔排序

希尔排序又称为缩小增量排序,希尔排序对直接插入排序进行了优化,先进行若干次预排序,在进行一次直接插入排序,预排的作用是使得所有记录更快的接近有序。

基本思想是:先选定一个整数(假设为K),把待排序的所有记录分成K个
,所有距离为K的记录分在同一组内,并对每一组内的记录进行插入排序。然后缩小K的值,重复上述分组和排序的工作。当K=1时,所有记录在一组内排好序。

这里举例将10,9,8,7,6,5,4,3,2,1进行第一轮的排序,假设K=3;
排序过程如图
在这里插入图片描述
可以看到,第一轮的排序结果,已经很接近有序了,缩小K的值,在进行分组和排序,当K=1时,所有数据为一组,此时进行的就是直接插入排序。

将数据分组进行预排,可以将更小的数据更快的插入到前面更大的数据更快的移到后面,减少了插入和移动的次数。

整数的选择也是一个问题,太小了会导致预排效果不明显,太大了会导致预排次数变多,因此整数的每次选取方式为缩小三倍在加1,加1会使得最后一次这个整数一定为1。即最后一次的排序一定是直接插入排序。

代码如下

void ShellSort(int* array, int numsArr)
{
	int gap = numsArr;
	while (gap > 1)
	{
		//间隔gap的数据作为一组,一共gap组
		//gap=1时是直接插入排序
		gap = gap / 3 + 1;    
		for (int i = 0; i < numsArr - gap; i++)
		{
			int end = i;
			int tmp = array[end + gap];
			while (end >= 0)
			{
				//往后挪数据
				if (array[end] > tmp)
				{
					array[end + gap] = array[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			array[end + gap] = tmp;
		}
	}
}

希尔排序的时间复杂度比较难算,因为预排和gap的选择会影响结果,并且每一次的预排都会对下一次的预排产生影响。这里直接说结论,希尔排序的时间复杂度大约为N^1.3。

3. 选择排序

3.1 直接选择排序

思想:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始(或末尾)位置,直到全部待排序的数据元素排完 。

这里进行一个小的优化,同时选出最大和最小的元素,分别放到末尾和起始位置。

但也会产生一个小问题,我们先看代码。

void SelectSort(int* array, int numsArr)
{
	int begin = 0, end = numsArr - 1;
	while (begin < end)
	{
		//最大最小值的下标
		int minIndex = begin, maxIndex = begin;
		for (int i = begin + 1; i <= end; i++)
		{
			//找最小值并更新下标
			if (array[i] < array[minIndex])
			{
				minIndex = i;
			}
			//找最大值并更新下标
			if (array[i] > array[maxIndex])
			{
				maxIndex = i;
			}
		}
		swap(&array[begin], &array[minIndex]);
		//最大值和起始位置重复了
		if (maxIndex == begin)
			maxIndex = minIndex;
		swap(&array[end], &array[maxIndex]);
		begin++;
		end--;
	}
}

问题是会产生数据重复,看下面这组数据。
9,2,3,4,5,6,8,1
如果没有这两条语句会产生什么情况。

if (maxIndex == begin)
maxIndex = minIndex;

在这里插入图片描述
当最大值的下标和起始位置的下标重复,就会产生上面的情况,解决办法就是加上判断语句。

时间复杂度:O(N^2)
空间复杂度:O(1)

3.2 堆排序

关于堆排序在之前已经介绍过了,这里就不在赘述了,大家可以看这篇进行了解:堆的应用
代码如下

void HeapSort(int* array, int numsArr)
{
	//向下调整建堆,复杂度O(N)
	for (int i = (numsArr - 2) / 2; i >= 0; i--)
	{
		AdJustDown(array, numsArr, i);
	}

	//升序建大堆;降序建小堆
	//复杂度O(N*logN)
	int i = numsArr - 1;
	while (i > 0)
	{
		swap(&array[0], &array[i]);//交换首尾元素
		AdJustDown(array, i, 0);
		i--;
	}
}
void AdJustDown(int* array, int num_array, int parent)//建大堆
{
	//假设左孩子符合条件
	int child = parent * 2 + 1;

	while (child < num_array)
	{
		//存在右孩子且右孩子符合条件
		if (child + 1 < num_array && array[child + 1] > array[child])
		{
			++child;
		}
		
		if (array[child] > array[parent])
		{
			//交换数据
			swap(&array[child], &array[parent]);
			//更新下标
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

这里对堆排序的时间复杂度进行一个计算。
如下图,这是建堆的时间复杂度

在这里插入图片描述
根据大O渐进表示法,最终建堆的时间复杂度为O(N)

而进行排序时,时间复杂度为
在这里插入图片描述
建堆的时间复杂度为O(N),排序的时间复杂度为O(NlogN),最大项为NlogN,因此堆排序的时间复杂度为O(N*logN)

关于其他排序,后续会依次介绍。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IIC和OLED再认识

IIC介绍 51是由于芯片功能不齐全&#xff0c;以至于需要软件编写IIC 而STM32芯片足够将IIC配置在硬件当中以至于直接读写即可 忘记了可回顾51的16.IIC 协议 和 OLED_oled,iic通信波特率-CSDN博客 在STM32中使用IIC可以直接调用HAL库的库函数&#xff1a; HAL_StatusTypeDe…

Appium Desktop + Appium Inspector + 模拟器连接

一、环境预备 1.你需要安装好配置好adb,确保可以在命令行直接运行adb指令 2.安装Appium Desktop、Appium Inspector 、 模拟器 二、启动appium 服务 启动后&#xff0c;画面如下&#xff1a; 三、启动模拟器 此时&#xff0c;启动模拟器&#xff0c;打开电脑cmd窗口&#x…

研发岗-统信UOS系统配置npm git等前端常用配置

第一步 获取root权限 配置环境等都需要用到root权限&#xff0c;所以我们先获取到root权限&#xff0c;方便下面的操作 下载软件 在UOS应用商店下载的所需应用 版本都比较低 安装node 官网下载了【arm64】的包&#xff0c;解压到指定文件夹&#xff0c;设置链接&#xff0…

揭秘AI精准输出:如何构建完美的AIGC提示词?

揭秘AI精准输出&#xff1a;如何构建完美的AIGC提示词&#xff1f;&#x1f916; 文章目录 揭秘AI精准输出&#xff1a;如何构建完美的AIGC提示词&#xff1f;&#x1f916;摘要引言正文&#x1f4d8; 提示词的基本概念1. 什么是提示词&#xff1f;2. 提示词的作用 &#x1f4d…

JAVA云HIS与LIS想知道区别在哪里吗?一分钟带你快速了解

JAVA云HIS与LIS想知道区别在哪里吗&#xff1f;一分钟带你快速了解 HIS系统与LIS系统使用各自独立的服务器&#xff0c;数据库不同&#xff0c;HIS系统、LIS系统服务器分别使用ORACLE数据库和SQLSERVER数据库&#xff0c;彼此数据信息不能共真&#xff0c;要解决HIS系统与LIS系…

vue iview table实现全选

之前我们在文章《iview Table实现跨页勾选记忆功能以及利用ES6的Map数据结构实现根据id进行对象数组的去重》里实现过全选功能,不过那有一个弊端就是需要调接口一次性获取全部的数据,这会造成请求数据响应超时或报错,因为数据量大的话这样体验也不好,于是我们改了一下,因为…

aosp13/14命令行进入分屏相关实战

背景&#xff1a; 分屏一般在手机上都是都是从桌面的最近任务卡片进入的&#xff0c;一般来说手机用户都是这样操作的&#xff0c;但是有一些场景或者情况就不一定可以顺利用上这个桌面的多任务卡片进入。 比如以下场景&#xff1a; 1、可能不是桌面的多任务的场景&#xff0c…

【Altium Designer 20 笔记】PCB铺铜过程

PCB铺铜步骤 切换到Keep-Out Layer&#xff08;禁止布线层&#xff09; 使用shifts键切换单层显示 画禁止布线范围&#xff08;防止铺铜过大&#xff09; 切换到需要铺铜的层 选择铺铜网络&#xff0c;通常是地&#xff08;GND&#xff09;或某个电源网络 隐藏覆铜&#xff1a;…

一.吊打面试官系列-数据库优化-认识MySql索引

1.什么是索引 索引&#xff08;Index&#xff09;是帮助DBMS&#xff08;数据库&#xff09;高效获取数据的数据结构&#xff0c;索引是为了加速对表中数据行的检索而创建的一种分散的存储结构。如果数据库没有索引就会走表进行全表扫描&#xff0c;一旦数据量上来&#xff0c…

如何基于香橙派AIpro对视频/图像数据进行预处理

背景介绍 受网络结构和训练方式等因素的影响&#xff0c;绝大多数神经网络模型对输入数据都有格式上的限制。在计算机视觉领域&#xff0c;这个限制大多体现在图像的尺寸、色域、归一化参数等。如果源图或视频的尺寸、格式等与网络模型的要求不一致时&#xff0c;我们需要对其…

【中间件】ElasticSearch简介和基本操作

一、简介 Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎&#xff0c;支持各种数据类型&#xff0c;包括文本、数字、地理、结构化、非结构化 ,可以让你存储所有类型的数据&#xff0c;能够解决不断涌现出的各种用例。其构成如下&#xff1a; 说明&#xff1…

递归、搜索与回溯算法——递归

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 小比特 大梦想 此篇文章与大家分享递归,搜索与回溯算法关于递归的专题 如果有不足的或者错误的请您指出! 目录 1.什么时候使用递归2.汉诺塔2.1解析2.2题解 3.合并两个有序链表3.1解析3.2题解 4.翻转链表4.1解析4…

Spring Boot 统一功能处理(二)

本篇主要介绍Spring Boot统一功能处理中的统一数据返回格式。 目录 一、定义统一的返回类 二、配置统一数据格式 三、测试配置效果 四、统一格式返回的优点 五、源码角度解析String问题 一、定义统一的返回类 在我们的接口在处理请求时&#xff0c;返回的结果可以说是参…

判断位数、按位输出、倒序输出(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int number 0;int i 1;int m 0;int z 0;int z1 0, z2 0, z3 0, z4 0;//提示用户&#xff1b;printf("请输…

编程新手必看,Python3中函数知识点及语法学习总结(18)

介绍&#xff1a; Python3中的函数是组织好的、可重复使用的代码段&#xff0c;用于实现单一或相关联的功能。 以下是Python3中函数的一些基本介绍&#xff1a; 函数定义&#xff1a;在Python中&#xff0c;可以通过def关键字来定义一个函数。函数定义后&#xff0c;可以多次调…

ADB的基本语法及常用命令

学习网址 ADB命令的基本语法如下&#xff1a; adb [-d|-e|-s <serialNumber>] <command> 如果有多个设备/模拟器连接&#xff0c;则需要为命令指定目标设备。 参数及含义如下&#xff1a; 常用命令如下&#xff1a; 1. 启动ADB服务 adb start-server 2. 停止…

【ROS2笔记六】ROS2中自定义接口

6.ROS2中自定义接口 文章目录 6.ROS2中自定义接口6.1接口常用的CLI6.2标准的接口形式6.3接口的数据类型6.4自定义接口Reference 在ROS2中接口interface是一种定义消息、服务或动作的规范&#xff0c;用于描述数据结构、字段和数据类型。ROS2中的接口可以分为以下的几种消息类型…

腾讯云优惠券领取及使用教程详解

腾讯云作为国内领先的云服务提供商&#xff0c;以其稳定可靠、性能卓越的服务赢得了广大用户的青睐。为了回馈用户&#xff0c;腾讯云经常推出各种优惠活动&#xff0c;其中优惠券就是非常受欢迎的一种。本文将详细介绍腾讯云优惠券的领取和使用方法&#xff0c;帮助大家更好地…

【c语言】结构体的访问

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C语言 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&…

记录 OpenHarmony 使用 request.uploadFile 时踩的坑

​ 开发环境 设备环境&#xff1a;OpenHarmony 4.1.x SDK 版本&#xff1a;API 10 开发模型&#xff1a;Stage 模型 IDLE: Dev Eco 4.1 官方文档 踩坑一&#xff1a;后台服务地址 上传文件依赖后台服务器&#xff0c;如果使用本地搭建的服务&#xff0c;是无法访问的&…
最新文章