【数据结构和算法】--- 基于c语言排序算法的实现(1)

目录

  • 一、排序的概念及其应用
    • 1.1排序的概念
    • 1.2 排序的应用
    • 1.3 常见的排序算法
  • 二、插入排序
    • 2.1直接插入排序
    • 2.2 希尔排序
      • 2.2.1 预排序
      • 2.2.2 缩小gap
      • 2.2.3 小结
  • 三、选择排序
    • 3.1 直接选择排序
    • 3.2 堆排序

一、排序的概念及其应用

1.1排序的概念

排序: 所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
稳定性: 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。
内部排序: 数据元素全部放在内存中的排序。
外部排序: 数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

1.2 排序的应用

以下是 “软科中国大学排名” 情况,这便是日常生活中排序的应用,此处排序标准为,以各个大学的总分作为唯一标准,进行降序排序。 此处的排序便是由排序算法实现,下面将对不同的排序算法进行剖析。

在这里插入图片描述

1.3 常见的排序算法

在这里插入图片描述
下面将基于c语言,对以上七种排序逐一实现。

二、插入排序

2.1直接插入排序

基本思想:
直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。
我们可以将直接插入排序想象成玩扑克牌,即每当我们拿到一张牌,然后插入到我们手上已排好序的牌中,从小到大直到找到合适的位置然后插入,以此循环直到排完序为止。
依据上述方法,我们可以先排数组的前两个数。第一个数作为已排好序的数组,第二个数作为要插入数组的数,插入完成后,将上述所有已插入的数作为已排好序的数组,然后再向后取一个数执行上述逻辑。 以此作为循环的主体,直到取完数组中所有的数,即当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移。

代码实现:

//直接插入排序
void InsertSort(int* a, int n)
{for(int i = 0; i < n - 1; i++){//[0, end] 已排好序的数组int end = i;int tmp = a[end + 1];//要插入的数//tmp 向前比较 -- 小于前一个数,则 a[end] 向后拷贝,end--,继续比较前一个数//大于则说明 tmp 到了合适的位置while(end >= 0){if(tmp <= a[end]){a[end + 1] = a[end];end--;}else{break;}}//比较完成,插入!a[end + 1] = tmp;}
}

代码实现时几点注意

  • 确定好要以排好序的数组范围(下标为0 ~ n - 2)n -1位置是最后一个要插入的数;
  • 要插入的数为已排好序的数组最后一个元素(end = i)的下一个(tmp = a[end + 1),使用tmp记录;
  • tmp向前比较,小于a[end]则继续比较前一个,当前a[end]向后拷贝,并使end--直到tmp大于a[end],或end < 0,则结束,并使a[end] = tmp

直接插入排序动态演示:

在这里插入图片描述

直接插入排序的特性总结:

  1. 元素集合越接近有序,直接插入排序算法的时间效率越高
  2. 时间复杂度: O(N^2)
  3. 空间复杂度: O(1),它是一种稳定的排序算法;
  4. 稳定性: 稳定

2.2 希尔排序

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。

根据元素集合越接近有序,直接插入排序算法的时间效率越高的规律,那么我们可以想方法先把一堆数据排的接近有序(预排序),然后再进行直接插入排序

2.2.1 预排序

可以定义gap来表示每次预排序的元素的跨度(即每次趟排序的数组下标相隔的值),这时gap也表示整个数组要排序的趟数。大致如下图所示:
在这里插入图片描述
gap趟中的每一趟,又是直接插入排序。那么在直接插入排序的基础上,我们只需要控制一下初始值,下标增值和结束条件即可,如:for(int j = i; j < n - gap; j += gap),其中n - gap是因为,每趟排序的最后一个元素都在整个数组的后gap个,又因为直接插入排序最后一个位置不取,所以要< n - gap。代码如下:

//预排序(以 gap = 3 为例)
int gap = 3;
//gap 趟
for(int i = 0; i < gap; i++)
{//直接插入排序for(int j = i; j < n - gap; j += gap){int end = j;int tmp = a[end + gap];while(end >= 0){if(tmp <= a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp; }
}

当然还可以对上面代码进行一点小优化可以将外层两个for循环改成一个:for(int j = 0; j < n - gap; j++) 事实上循环总次数是不变的,我们只是将原来先排好第一组再排后面组的思路,改成了混在一起排,效果还是一样的。由一组一组排变为了多组并排。

2.2.2 缩小gap

有了预排序,那么我们只要合理的控制gap的大小,便完成了希尔排序。如:gap = gap / x + 1其中的x可以根据具体的待排序的数组的长度来决定。 待排序数组长,则x设置较大一些;待排序数组短,则x设置较小一些。gap / x后还要加一,是为了让排序的最后一趟gap = 1,即直接插入排序。

//希尔排序(缩小增量排序)
void ShellSort(int* a, int n)
{int gap = n;//gap > 1 时是预排序,目的是让他接近有序//ga[ = 1 时是直接插入排序,目的是让他有序while(gap > 1){gap = gap / 3 + 1;  //加1是为了让他最后一次 gap = 1//预排序// ....}
}

排序整体逻辑基本如下:
在这里插入图片描述

2.2.3 小结

希尔排序的特性总结:

  1. 希尔排序是对直接插入排序的优化。
  2. gap > 1时都是预排序,目的是让数组更接近于有序。如此一来,当gap == 1时,数组已经接近有序的了,这样效率也会很高。这样整体而言,可以达到优化的效果。
  3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些书中给出的希尔排序的时间复杂度都不固定:
    《数据结构(C语言版)》— 严蔚敏
    在这里插入图片描述
    《数据结构-用面相对象方法与C++描述》— 殷人昆
    在这里插入图片描述
    因为咋们的gap是按照 Knuth 提出的方式取值的,而且 Knuth 进行了大量的试验统计,我们暂时就按照:O(N^1.25)O(1.6 * N^1.25)来算。
  4. gap越大,大的值越快跳到后面,小的值越快跳到前面,越不接近有序;gap越小,大的之越慢跳到后面,小的值越慢跳到前面,越接近有序;
  5. 稳定性: 不稳定

三、选择排序

3.1 直接选择排序

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

直接插入排序动态演示:
在这里插入图片描述
上述的方法是从头遍历到尾,找最小值,然后插入到目标位置,事实上效率并不是很高,于是我们可以这样进行点小优化定义一个变量int begin = 0,从下标为begin的位置向后找小,再定义一个变量int end = n - 1,从下标为begin的位置向后找大,待循环结束大值和下标为end的值交换,小值和下标为begin的值交换,然后begin++; end--;,直到begin == end排序结束。这样每次循环都会找到两个目标值,且缩小了下一次搜索的范围,达到了优化的效果。
代码实现:

//直接插入选择(优化)
void SelectSort(int* a, int n)
{int begin = 0, end = n - 1;//记录 较大值 和 较小值 的下标int mini = begin, maxi = degin;while(begin < end){//找大值和小值for(int i = begin + 1; i < end + 1; i++){if(a[i] < a[mini])mini = i;if(a[i] > a[maxi])maxi = i;}//交换Swap(&a[begin], &a[mini]);//判断防止最大值丢失if(maxi == begin)maxi = mini;Swap(&a[end], &a[maxi]);++begin;--end;}
}

还有一点需要注意的是,交换完一个值我们要先判断,看最大值是否在begin位置,if(maxi == begin),若在,则将maxi换到mini位置。逻辑大致如下:
在这里插入图片描述

直接选择排序的特性总结:

  1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
  2. 时间复杂度: O(N^2)
  3. 空间复杂度: O(1)
  4. 稳定性: 不稳定

3.2 堆排序

堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。
因为之前已经介绍过了,所以这里就不多讲了,详细请参考:【数据结构和算法】—二叉树(2)–堆的实现和应用

直接选择排序的特性总结:

  1. 堆排序使用堆来选数,效率就高了很多。
  2. 时间复杂度: O(N*logN)
  3. 空间复杂度: O(1)
  4. 稳定性: 不稳定

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

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

相关文章

【Spring Boot】第一篇 创建简单的Spring Boot项目

导航 一. 简介二. 创建简单的Spring Boot项目1. 工具选择和版本确定2. 创建步骤 三. 部署项目四. 测试验证 一. 简介 Spring Boot是一个用于构建独立的、生产级别的Spring应用程序的框架。它简化了Spring应用程序的创建和配置过程&#xff0c;同时提供了很多开箱即用的功能&am…

C++ map和set

1. 关联式容器 序列式容器&#xff1a;因为其底层为线性序列的数据结构&#xff0c;里面存储的是元素本身&#xff0c;比如&#xff1a;vector、list、deque 关联式容器也是用来存储数据的&#xff0c;与序列式容器不同的是&#xff0c;其里面存储的是结构的键值对&#xff0…

C# Socket通信从入门到精通(21)——Tcp客户端判断与服务器断开连接的三种方法以及C#代码实现

前言 我们开发的tcp客户端程序在连接服务器以后,经常会遇到服务器已经关闭但是作为客户端的我们不知道,这时候应该应该有一个机制我们可以实时监测客户端和服务器已经断开连接,如果已经断开了连接,我们应该及时报警提示用户客户端和服务器已经断开连接,本文介绍三种可以监…

CICD注册和使用gitlab-runner常见问题

1、现象 fatal: unable to access https://github.com/homebrew/brew/: 2、解决 git config --global --unset http.proxy git config --global --unset https.proxy 查看gitlab-runner是否成功&#xff1a; userusers-MacBook-Pro ~ % gitlab-runner -h 查看gitlab-run…

Google Chrome Close AutoUpdate

DOMException: play() failed because the user didn‘t interact with the document first.-CSDN博客 html5 audio video-CSDN博客 Google Chrome Close AutoUpdate 关闭google浏览器自动更新 1&#xff1a;检查是否已安装google浏览器&#xff0c;并卸载&#xff1a; 2&…

RabbitMQ 安装

下载erlang语言&#xff1a; erlang语言 下载RabbitMQ rabbitmq 安装erlang 1.以管理员身份安装erlang 2.弹出框选择next 3.选择安装路径&#xff0c;亦可以安装在默认路径 4.接下来一路点击下一步&#xff0c;无需任何修改&#xff0c;直到 install安装为止&#xff…

Intellij Idea的数据库工具 DataGrip

DataGrip DataGrip&#xff1a; IDEA自带&#xff0c;非常好用。智能提示很强大&#xff0c;快捷键跟IDEA自身一致。 如果下载不了 DataGrip&#xff0c;也可以直接用 IDEA 自带的。 常用的快捷键 alt8&#xff1a; 打开数据库Service ctrlshiftF10&#xff1a;打开常用的数…

Elasticsearch:BM25 及 使用 Elasticsearch 和 LangChain 的自查询检索器

本工作簿演示了 Elasticsearch 的自查询检索器将非结构化查询转换为结构化查询的示例&#xff0c;我们将其用于 BM25 示例。 在这个例子中&#xff1a; 我们将摄取 LangChain 之外的电影样本数据集自定义 ElasticsearchStore 中的检索策略以仅使用 BM25使用自查询检索将问题转…

我的世界Java版服务器如何搭建并实现与好友远程联机Minecarft教程

文章目录 1. 安装JAVA2. MCSManager安装3.局域网访问MCSM4.创建我的世界服务器5.局域网联机测试6.安装cpolar内网穿透7. 配置公网访问地址8.远程联机测试9. 配置固定远程联机端口地址9.1 保留一个固定tcp地址9.2 配置固定公网TCP地址9.3 使用固定公网地址远程联机 本教程主要介…

Three.js学习6:透视相机和正交相机

一、相机 相机 camera&#xff0c;可以理解为摄像机。在拍影视剧的时候&#xff0c;最终用户看到的画面都是相机拍出来的内容。 Three.js 里&#xff0c;相机 camera 里的内容就是用户能看到的内容。从这个角度来看&#xff0c;相机其实就是用户的视野&#xff0c;就像用户的眼…

【力扣】Z字形变换,模拟+直接构造

Z字形变换原题地址 方法一&#xff1a;利用二维矩阵模拟 对于特殊情况&#xff0c;z字形变换后只有一行或只有一列&#xff0c;则变换后的字符串和原字符串相同。 对于一般情况&#xff0c;我们可以考虑按照题目要求&#xff0c;把字符串按照Z字形存储到二维数组中&#xff…

Django模板(一)

一、基本规则 作为一个Web框架,Django需要一种方便的方式来动态生成HTML。最常用的方法依赖于模板。模板包含所需HTML输出的静态部分以及描述如何插入动态内容的特殊语法 1.1、django默认模板 在settings中配置: TEMPLATES = [{BACKEND: django.template.backends.django.…

车位检测,YOLOV8,OPENCV调用

车位检测YOLOV8NANO,opencv调用 车位检测&#xff0c;YOLOV8NANO&#xff0c;训练得到PT模型&#xff0c;然后转换成ONNX&#xff0c;OPENCV的DNN调用&#xff0c;支持C,PYTHON,ANDROID

QXlsx Qt操作excel

QXlsx 是一个用于处理Excel文件的开源C库。它允许你在你的C应用程序中读取和写入Microsoft Excel文件&#xff08;.xlsx格式&#xff09;。该库支持多种操作&#xff0c;包括创建新的工作簿、读取和写入单元格数据、格式化单元格、以及其他与Excel文件相关的功能。 支持跨平台…

Mysql索引优化建议

1&#xff0c;最左前缀法则 如果为一张表创建了多列的组合索引&#xff0c;要遵守最左前缀法则。就是指查询从索引的最左前列开始并且不要跳过索引中的列。&#xff08;因为Mysql的InnoDB引擎的索引树是一个按顺利排序存储的数据结构&#xff08;BTREE&#xff09;&#xff0c…

第01课:自动驾驶概述

文章目录 1、无人驾驶行业概述什么是无人驾驶智慧出行大趋势无人驾驶能解决什么问题行业趋势无人驾驶的发展历程探索阶段&#xff08;2004年以前&#xff09;发展阶段&#xff08;2004年-2016年&#xff09;成熟阶段&#xff08;2016年以后&#xff09; 2、无人驾驶技术路径无人…

uniapp canvas游标卡尺效果

效果 根据公司业务仿照写的效果。原项目从微信小程序转uniapp,未测试该效果在android端效果。 uniapp直接使用canvas不可做子组件,否则无效果显示,其次显示时要考虑页面渲染超时的问题。 如效果所见,可以设置取值精度。 gitee地址:project_practice: 项目练习 - Gitee.…

【LangChain-04】利用权重和偏差跟踪和检查LangChain代理的提示

利用权重和偏差跟踪和检查LangChain代理的提示 一、说明 考虑到&#xff08;生成&#xff09;人工智能空间&#xff0c;&#xff08;自主&#xff09;代理现在无处不在&#xff01;除了更强大且幸运的是开放的大型语言模型&#xff08;LLM&#xff09;之外&#xff0c;LangCh…

宝塔+php+ssh+vscode+虚拟机 远程调试

远程(虚拟机)宝塔 安装扩展 配置文件添加&#xff0c;zend_extension看你虚拟机的具体位置 [Xdebug] zend_extension/www/server/php/74/lib/php/extensions/no-debug-non-zts-20190902/xdebug.so xdebug.modedebug xdebug.start_with_requesttrigger xdebug.client_host&quo…

Dockerfile文件参数配置和使用

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…