排序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.mzph.cn/news/813489.shtml

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

相关文章

Navicat Premium 16 for Mac/Win:数据库管理的全能之选

在数字化时代&#xff0c;数据库管理已成为各行各业不可或缺的一环。而Navicat Premium 16作为一款功能强大的数据库管理软件&#xff0c;无疑为数据库管理员和开发者提供了高效、便捷的解决方案。 Navicat Premium 16支持多种主流数据库系统&#xff0c;无论是MySQL、Postgre…

JS - BOM(浏览器对象模型)

BOM 浏览器对象模型 BOM可以使我们通过JS来操作浏览器 在BOM中为我们提供了一组对象&#xff0c;用来完成对浏览器的操作 BOM对象 BOM&#xff08;Browser Object Model&#xff09;是指浏览器对象模型&#xff0c;它提供了与浏览器窗口进行交互的对象和方法。BOM包括一些核…

Linux系统——Zookeeper集群

目录 一、Zookeeper概述 1.Zookeeper简介 2.Zookeeper工作机制 3.Zookeeper数据结构 4.Zookeeper应用场景 4.1统一命名服务 4.2统一配置管理 4.3统一集群管理 4.4服务器动态上下线 4.5软负载均衡 5.Zookeeper选举机制 5.1第一次启动选举机制 5.2非第一次启动选举机…

【Unity】常见性能优化

1 前言 本文将介绍下常用的Unity自带的常用优化工具&#xff0c;并介绍部分常用优化方法。都是比较基础的内容。 2 界面 2.1 Statistics窗口 可以简单查看Unity运行时的统计数据&#xff0c;当前一帧的性能数据。 2.1.1 Audio 音频相关内容。 Level&#xff1a;音量大小&a…

图机器学习导论

图&#xff1a;描述关系数据的通用语言&#xff0c;起源于哥尼斯堡七桥问题 传统的机器学习&#xff1a;数据样本之间独立同分布&#xff0c;简单拟合数据边界&#xff0c;在传统的机器学习中&#xff0c;每个数据样本彼此无关。传统的神经网络&#xff0c;只能处理简单的表格、…

实体行业的品牌传播与网络运营,迅腾文化解决完善品牌定位运营

实体行业的品牌传播与网络运营&#xff0c;迅腾文化解决完善品牌定位运营 在今日的商业环境中&#xff0c;如何借助网络的力量&#xff0c;将品牌有效地传播出去&#xff0c;让渠道商、加盟商和消费者感受到安全感&#xff0c;成为了深思的问题。品牌是一个企业的灵魂&#xf…

动态规划先导片

大家知道动规是由前一个状态推导出来的&#xff0c;而贪心是局部直接选最优的&#xff0c;对于刷题来说就够用了。 对于动态规划问题&#xff0c;我将拆解为如下五步曲&#xff0c;这五步都搞清楚了&#xff0c;才能说把动态规划真的掌握了&#xff01; 确定dp数组&#xff0…

开源!工厂数字化项目会用到的地理信息系统

软件介绍 QGIS&#xff08;Quantum GIS&#xff09;是一款免费、开源、跨平台的地理信息系统&#xff08;GIS&#xff09;软件&#xff0c;适用于Unix平台、Windows和MacOS。提供了强大且用户友好的功能&#xff0c;使其成为地理信息处理领域的热门选择。 功能特点 1.空间数据管…

react使用npm i @reduxjs/toolkit react-redux

npm i reduxjs/toolkit react-redux 创建一个 store文件夹&#xff0c;里面创建index.js文件和子模块文件夹 index,js文件写入以下代码 import {configureStore} from reduxjs/toolkit // 导入子模块 import counterReducer from ./modules/one import two from ./modules/tw…

鸿蒙TypeScript学习第14天:【联合类型】

1、TypeScript 联合类型 联合类型&#xff08;Union Types&#xff09;可以通过管道(|)将变量设置多种类型&#xff0c;赋值时可以根据设置的类型来赋值。 注意&#xff1a;只能赋值指定的类型&#xff0c;如果赋值其它类型就会报错。 创建联合类型的语法格式如下&#xff1…

RTSP/Onvif安防视频EasyNVR平台 vs.多协议接入视频汇聚EasyCVR平台:设备分组的区别

EasyNVR安防视频云平台是旭帆科技TSINGSEE青犀旗下支持RTSP/Onvif协议接入的安防监控流媒体视频云平台。平台具备视频实时监控直播、云端录像、云存储、录像检索与回看、告警等视频能力&#xff0c;能对接入的视频流进行处理与多端分发&#xff0c;包括RTSP、RTMP、HTTP-FLV、W…

大厂Java笔试题之判断字母大小写

/*** 题目&#xff1a;如果一个由字母组成的字符串&#xff0c;首字母是大写&#xff0c;那么就统计该字符串中大写字母的数量&#xff0c;并输出该字符串中所有的大写字母。否则&#xff0c;就输出* 该字符串不是首字母大写*/ public class Demo2 {public static void main(St…

Redis的双写一致性问题

双写一致性问题 1.先删除缓存或者先删除数据库都可能出现脏数据。 2.删除两次缓存&#xff0c;可以在一定程度上降低脏数据的出现。 3.延时是因为数据库一般采用主从分离&#xff0c;读写分离。延迟一会是让主节点把数据同步到从节点。 1.读写锁保证数据的强一致性 因为一般放…

在视频号开店,新手一定要注意了,这几个细节很多人都不知道

大家好&#xff0c;我是电商笨笨熊 视频号小店作为今年黑马项目&#xff0c;自是吸引力不少的电商玩家&#xff1b; 但是在这些玩家中不免有一些新手玩家&#xff0c;从未做过电商&#xff0c;或者做过其他平台的电商但是没有接触过视频号&#xff1b; 而视频号小店在某些地…

thinkphp6入门(23)-- 如何导入excel

1. 安装phpexcel composer require phpoffice/phpexcel composer update 2. 前端 <form class"forms-sample" action"../../xxxx/xxxx/do_import_users" method"post" enctype"multipart/form-data"><div class"cont…

【InternLM 实战营第二期-笔记4】XTuner 微调个人小助手认知

书生浦语是上海人工智能实验室和商汤科技联合研发的一款大模型,很高兴能参与本次第二期训练营&#xff0c;我也将会通过笔记博客的方式记录学习的过程与遇到的问题&#xff0c;并为代码添加注释&#xff0c;希望可以帮助到你们。 记得点赞哟(๑ゝω╹๑) XTuner 微调个人小助手…

基于 FPGA 的 DE1-SoC 功率估算器

Introduction 功耗是当今许多技术都要考虑的重要因素。例如&#xff0c;手机生产商总是谈论他们在电源管理方面的改进&#xff0c;以及如何延长电池的使用寿命。功能与功耗之间的平衡是许多人都在研究的有趣课题。然而&#xff0c;当我们做实验时&#xff0c;我们很少会考虑我…

SpringBoot3整合Mybatis plus

Java版本&#xff1a;17 Spring Boot版本&#xff1a;3.1.10 Mybatis plus版本&#xff1a;3.5.5 源码地址&#xff1a;Gitee仓库 01 创建我们的项目工程 首先&#xff0c;我们创建一个maven工程spring-boot3-demo&#xff0c;pom文件配置如下。 这里我们将spring-boot-start…

视频号小店好做吗?普通人没有货源,也可以做吗?

大家好&#xff0c;我是电商糖果 视频号小店作为2022年才出来的电商黑马项目&#xff0c;吸引了不少正在找创业项目的朋友。 这里面也有很多没有接触过电商&#xff0c;没有货源的普通人。 于是不少朋友就问糖果&#xff0c;如果普通人没有货源可以做吗&#xff1f;小店好做…

简单好用的SaaS知识库工具都在这了,看完赶紧收藏!

在信息飞速发展的今天&#xff0c;企业如何有效地管理海量的信息和知识成为了提高工作效率的关键。SaaS知识库工具正成为企业寻求的解决方案&#xff0c;它们不仅能够帮助团队组织文档&#xff0c;而且优化知识分享流程。现在就让我们来看看市场上几款简单又好用的SaaS知识库工…