算法---排序

目录

  • 插入排序
    • 插入排序的思想
    • 代码实现
  • 冒泡排序
    • 冒泡排序的思想
    • 代码实现
  • 堆排序
    • 堆排序的基本思想
    • 代码实现
  • 希尔排序
    • 希尔排序基本思想
    • 代码实现
  • 选择排序
    • 选择排序基本思想
    • 代码展示
  • 总结

插入排序

插入排序的思想

简单来说,插入排序就时将一个数插入一个数插入一个有序的数组使之仍然有序,我们可以用一张动图来展示其基本原理在这里插入图片描述
从上图不难发现,我们可以将第一个数看成一个有序的数,因为只有一个数所以不存在有序与无序,所以我们可以从第二个数开始插入,使前两个数有序,然后接着开始从第三个数开始插入,直到最后一个数。

代码实现

//插入排序
//时间复杂度:O(N^^2)
void InsertSort(int* a, int n)
{////[0,end] end+1//循环n-1次//时间复杂度:O(N^2)//最坏情况是逆序  最好情况是顺序或者接近有序for (int i = 0;i < n-1;i++)//最后一个数是用来插入进去的,所以只能遍历到n-2,最后一个数直接插入进去{int end = i;int tmp = a[end + 1];//1 2 3 4 5 .....n-1(n^2)while (end >= 0){if (tmp < a[end]){a[end + 1] = a[end];end--;}else{break;}}a[end + 1] = tmp;}}

==注意:不管是进入if还是进入else,最后都要将tmp插入到end+1中,所以,我们可以把这个语句放在外面

冒泡排序

冒泡排序的思想

假设排升序
冒泡排序的基本思想大致是:先将 数组中前两个数进行比较,然后如果前一个数大于后一个数,则交换,然后再将后一个数与其后一个再进行比较,然后如果前一个数大于后一个数则前后两个数交换,则经过一轮排序之后,最大的数则会被冒到最后一个位置,以此类推,我们不难发现,如果是十个数的话我们只需要冒泡九轮,所以最后冒泡的次数是数组的元素个数减一。
动图展示:
在这里插入图片描述

代码实现

根据上面的描述:我们可以很容易得写出相应的代码

void Swap(int* ps, int* pa)
{int tmp = *ps;*ps = *pa;*pa = tmp;
}
//冒泡排序
void BubbleSort(int* a, int n)
{for (int i = 0;i < n;i++){for (int j = 0;j < n - 1 - i;j++){if (a[j] > a[j + 1]){Swap(&a[j], &a[j + 1]);}}}
}

注意:冒泡排序的时间复杂度是O(N^2)
为此我们还可以对冒泡排序进行优化,我们知道,冒泡排序不管这个数组有没有序都会将数组遍历一遍,所以我们可以定义一个标记是否进行交换的变量exchange,如果在一轮循环中,exchange没有发生变化,则证明在这次循环中根本没有交换,所以我们可以直接终止这次循环:
改进后的代码如下:

void NewBubbleSort(int* a, int n)
{for (int i = 0;i < n - 1;i++){int exchange = 0;//标志---一个轮回都没有交换for (int j = 1;j < n - j;j++){if (a[j - 1] > a[j]){Swap(&a[j], a[j + 1]);exchange = 1;//交换了,就令exchange为1}}//一轮之后判断exchange是否改变if (exchange == 0){break;}}
}

堆排序

堆排序的基本思想

堆排序是一种基于二叉堆数据结构的排序算法。其基本思想可以总结如下:

  1. 建立堆: 将待排序的数据构建成一个最大堆(或最小堆),即满足堆的性质:父节点的值总是大于等于(最大堆)或小于等于(最小堆)其子节点的值。建立堆的过程一般从最后一个非叶子节点开始,依次向前调整,使得每个节点都满足堆的性质。

  2. 堆调整: 将堆顶元素(最大值或最小值)与堆的最后一个元素交换,并将堆的大小减一,然后对堆顶元素进行调整,使得剩余元素重新构成一个最大堆或最小堆。

  3. 重复步骤2: 不断重复进行堆调整的过程,直到堆的大小减为1,即所有元素都被排序完成。
    堆排序的关键在于建立堆和堆调整的过程。通过构建最大堆,堆顶元素就是整个序列中的最大值,在每一轮的堆调整中将最大值移动到序列的末尾,从而完成排序。同样,如果需要按照从小到大的顺序排序,可以构建最小堆,并将堆顶元素移动到序列的末尾。
    动图展示:
    在这里插入图片描述

注意:假设我们要排升序,则应该建大堆,这里解释一下为什么,如果我们建小堆的话,我们只能取到堆顶元素是最小的,取完堆顶元素之后,又要对剩下的元素重新建堆这样的消耗是很大的,但是如果我们建大堆的话,我们可以知道最大的元素时堆顶然后将堆顶的元素交换到最后一层的最后一个元素,然后再对剩下的元素进行一次向下调整,再选出次大的,这样根本不用重新建堆,不管是对空间还是对时间的消耗都是最小,所以我们排升序选择建大堆。
堆排序
第一步:建堆
第二部:交换堆顶和堆底的元素,然后再向下调整。

代码实现

//堆排序
void AdjustDown(int* a, int n, int root)
{int parent = root;int child = root * 2 + 1;while (child < n){if (a[child] < a[child] && child + 1 < n){child++;}if (a[child] > a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}
void HeapSort(int* a, int n)
{//建堆for (int i = (n - 1 - 1) / 2;i >= 0;i--){AdjustDown(a, n, i);}int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);end--;}
}

希尔排序

希尔排序基本思想

希尔排序(Shell Sort)是一种改进的插入排序算法,也被称为缩小增量排序。其基本思想是通过比较相距一定间隔(称为增量)的元素,使得每一轮比较的元素距离越来越近,最终使得整个序列基本有序,然后再进行最后一轮插入排序。

希尔排序的具体步骤如下:

  1. 选择增量序列: 选择一个增量序列,用于指定待排序序列中相邻元素之间的间隔。通常的增量序列选择包括Hibbard序列、Sedgewick序列等。增量序列的选择会影响希尔排序的性能。

  2. 根据增量序列进行分组: 将待排序序列分成若干个子序列,每个子序列包含间隔为增量的元素。对每个子序列分别进行插入排序。

  3. 逐步缩小增量: 不断减小增量,重复步骤2,直到增量为1。这样,最后一轮排序将是一次插入排序,但是由于之前的步骤已经使得序列基本有序,因此插入排序的时间开销会大大减少。

希尔排序之所以有效,是因为它在一开始通过较大的增量将元素分成较少的子序列,对这些子序列进行插入排序可以使得元素移动的距离减少,从而减少了插入排序的时间复杂度。随着增量的逐步减小,最终一轮的插入排序对于基本有序的序列而言时间开销较小。

希尔排序的时间复杂度与增量序列的选择有关,最好的情况下可以达到O(n log n),最坏情况下为O(n^2)。希尔排序是一种不稳定的排序算法,但由于其简单且在某些情况下表现良好,仍然被广泛使用。

注意:我们接下来展示的是将希尔排序的间隔定义为2的情况下展开的
先用动图展示:
在这里插入图片描述

代码实现

//gap越大数据跳到越快
void ShellSort(int* a, int n)
{//分组预排插入,目标:大的数更快的跳到后面,小的数更快的跳到前面int gap = n;while (gap > 1){gap /= 2;for (int i = 0;i < n - gap;i += gap){int end = i;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;}}}

注意:上面代码随着gap的减小逐渐接近有序,直到最后gap等于1的时候,就是我们前面讲到的插入排序。

选择排序

选择排序基本思想

讨论升序的情况
选择排序的基本思想:遍历整个数组选出最大的元素,然后插入到最后一个位置,然后从剩下的数组中选出次大的,然后插入到倒数第二个位置,以此类推
动图展示:
在这里插入图片描述

代码展示

void SelectSort(int* a, int n)
{int begin = 0, end = n - 1;//选出最小值和最大值的位置int mini = begin, maxi = begin;while (begin < end){for (int i = begin;i <= end;i++){if (a[i] < a[mini]){mini = i;}if (a[i] > a[maxi]){maxi = i;}}if (maxi == begin){maxi = mini;}Swap(&a[begin], &a[mini]);Swap(&a[end], &a[maxi]);begin++;end--;}
}

注意:这里我们我们可以利用两个指针,一个指向头,一个指向尾,然后将最小的元素插入到数列的首位置,将最大的元素插入到数组尾的位置,然后依次向中间遍历,这样优化可以将以前的执行次数减少一半,因为我同时选出了最大和最小的元素。

总结

当然可以。以下是一个关于排序算法的总结:

总的来说,排序算法是计算机科学中一个重要而基础的主题,它们在日常生活和各种应用中都扮演着重要的角色。通过对各种排序算法的了解和研究,我们可以更好地理解数据的组织和处理方式,从而提高算法的效率和性能。

在本文中,我们介绍了几种常见的排序算法,包括冒泡排序、选择排序、插入排序、归并排序、快速排序、堆排序和希尔排序。每种算法都有其独特的思想和实现方式,并且在不同的应用场景下具有不同的优缺点。

冒泡排序和选择排序是最简单的排序算法之一,虽然它们的时间复杂度较高,但对于小规模数据集合仍然是一种有效的选择。插入排序通过构建已排序部分来不断插入新元素,具有较好的性能表现,特别适用于部分有序的数据。归并排序和快速排序是两种基于分治思想的高效排序算法,它们具有较好的平均时间复杂度,并且可以在大规模数据集合下快速排序。堆排序利用堆数据结构实现了一种高效的排序算法,尤其适用于需要原地排序的情况。希尔排序则是一种改进的插入排序算法,通过逐步缩小增量实现了对基本有序序列的高效排序。

除了这些算法外,还有许多其他排序算法,每种都有其特定的应用场景和优劣势。在选择排序算法时,需要考虑数据规模、数据特征、时间复杂度和空间复杂度等因素,并根据实际情况选择最合适的算法。

总的来说,排序算法是计算机科学中一个基础而重要的研究领域,通过不断地学习和研究排序算法,我们可以更好地理解和应用算法,提高程序的效率和性能,为解决实际问题提供更好的解决方案。

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

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

相关文章

使用 ReclaiMe Pro 查找并恢复网络中的 SSH 服务器数据

天津鸿萌科贸发展有限公司是 ReclaiMe Pro 数据恢复软件的授权代理商。ReclaiMe Pro 数据恢复软件专注于恢复几乎所有文件系统及各种类型和复杂程度的 RAID 阵列。 在本文中&#xff0c;我们介绍 ReclaiMe Pro 对于采用 SSH 连接方式的网络服务器中数据的恢复方法。 ReclaiMe…

设计模式及其在项目、框架中的应用

设计模式的作用&#xff1a; 1、类之间关系图&#xff0c;明确的角色及其关系、作用&#xff1b; 2、符合开闭原则&#xff0c;职责明确&#xff0c;并且开放的拓展点可以有效应对后期的变化。 &#xff08;一&#xff09;、责任链模式 适用场景&#xff1a; 在一个流程中&…

HWL-41无辅源静态电流继电器 0.5-9.99A 导轨安装 JOSEF约瑟

HWL-40系列无辅源静态电流继电器 HWL-41HWL-42 HWL-43HWL-61 HWL-62HWL-63 HWL-71HWL-72 HWL-73HWL-81 HWL-82HWL-83 产品概述 1、HWL系列集成电路无辅源电流继电器用于发电机、变压器和输电线的过负荷和短路保护装置中作为启动元件。本继电器为集成电路静态型继电器&a…

Token的详解

Token的详解 文章目录 Token的详解前言:简介:使用token&#xff1a; 前言: 为什么会用到Token&#xff0c;因为cookie和session一些自身的缺点&#xff0c;限制了一些功能的实现&#xff0c;比如&#xff1a; cookie&#xff1a;优点是节省服务器空间&#xff0c;缺点不安全。…

启动Vue-demo时引发的一系列问题—解决办法

目录 1.初始遇到的问题&#xff1a;输入npm run dev 1.治标的解决方法 2.治本的解决方法 第一步&#xff1a;检查是否安装了cnpm 第二步&#xff1a;手动找到cnpm目录 第三步&#xff1a;配置系统环境变量 第四步&#xff1a;查看是否安装成功 1.初始遇到的问题&#xf…

宝塔面板系列——两种方式安装青龙面板

因为最近旧windows服务器到期了&#xff0c;在搬服务器&#xff0c;新服务器尝试用Linux系统。过程中有很多不懂的地方&#xff0c;只能边搬迁边学边弄&#xff0c;顺带记录下来&#xff0c;哪天又要搬迁了&#xff0c;翻翻自己的文章也就一应俱全了。 非科班出身&#xff0c;选…

【计算机网络实践】Cisco Packet Tracer局域网组网(FTP服务器通过交换机连接客户端)

本文为应对计算机网络第一次实验所写的预习报告 一、实验准备 一台装有Cisco Packet Tracer的PC机&#xff0c;一个大学生大脑。 二、了解FTP和Cisco Packet Tracer 具体内容可在百度搜索&#xff0c;在物理机上用FileZilla Server实现ftp可参看我前面的文章。Cisco Packet Tr…

【LabVIEW FPGA入门】FPGA不同传递数据方法比较

数据共享方法的选择应基于应用的需要。根据应用程序的重要特性&#xff0c;所讨论的任何一种方法都可能是合适的。 传输方法FPGA资源损耗&#xff1f;不同时钟源之间传递数据&#xff1f;新数据通知&#xff1f;常见用途变量逻辑片是是否提取最新数据存储器存储器是否否提取最新…

深入理解MySQL中的JOIN算法

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 目录 一、引言二、嵌套循环连接&#xff08;Nested-Loop Join&#xff09;2.1 工作原理2.2 性能考虑2.3 优化策略 三、块嵌套循环…

Java代码基础算法练习-递归求数-2024.03.22

任务描述&#xff1a; 利用递归函数调用方式&#xff0c;将所输入的5个字符&#xff0c;以相反顺序打印出来。 任务要求&#xff1a; 代码示例&#xff1a; package march0317_0331;import java.util.Scanner;/*** m240322类&#xff0c;提供了一个反转输入字符串前5个字符的…

软考复习笔记day3(计算机体系结构和指令系统基础)(精简版)

计算机体系结构分类 处理机数量分类&#xff1a; 单处理&#xff08;一个处理单元&#xff09;并行处理系统&#xff08;两个以上处理机互联&#xff09;.分布式处理系统 Flynn分类&#xff1a;&#xff08;常考&#xff09; 以指令流和数据流进行区别 指令流由控制部分进…

vue3初步学习

vue3初步学习 vue模版 练习代码如下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>实验4</ti…

计算机二级(python)【二】

真题5 1、考生文件夹下存在一个文件PY101.py&#xff0c;请写代码替换横线&#xff0c;不修改其他代码&#xff0c;实现以下功能&#xff1a; 键盘输入正整数n&#xff0c;按要求把n输出到屏幕&#xff0c;格式要求&#xff1a;宽度为15个字符&#xff0c;数字右边对齐&#…

【小米汽车SU7实测】 小米汽车su7到底行不行?小米新能源轿车体验感怎么样?

小米汽车SU7是小米汽车的首款车型&#xff0c;定位“C级高性能生态科技轿车”&#xff0c;也是小米迈入新能源赛道的首次成果落地。 首先&#xff0c;让我们来谈谈它的性能。试驾过程中&#xff0c;小米SU7展现出了惊人的加速能力&#xff0c;0-100km/h加速仅需2.78秒&#xf…

Vue项目使用process.env关键字及Vue.config.js配置解决前端跨域问题

1.process.env 是Node.js 中的一个环境 1.打开命令行查看环境: 2.process.env与Vue CLI 项目 Vue Cli 有以下三种运行模式 development 模式用于 vue-cli-service serve test 模式用于 vue-cli-service test:unit production 模式用于 vue-cli-service build 和 vue-cli-se…

【STL学习】(1)string类

前言 本文将详细讲解STL中string类的常用的接口函数。 一、为什么学习string类&#xff1f; 1、字符串类型的重要性 在现实生活中有很多复杂类型是以字符串来表达的&#xff0c;比如我们在搜索引擎输入的“数据”&#xff0c;一个人的姓名、身份证号等等。 所以字符串类型是很…

ETCD跨城容灾与异地多活网络故障的相关表现分析

ETCD跨城容灾与异地多活网络故障的相关表现分析 1. 网络架构2. 单个网络中断-跟leader区中断2.1. 网络中断2.2. 网络恢复 3. 单个网络中断-跟非leader区中断4. 两个网络中断-leader区中断5. 两个网络中断-非leader区中断6. 两个网络中断-非leader区中断7. 总结8. 参考文档 etcd…

【多线程】有了解过 CAS 和原子操作吗?

SueWakeup 个人主页&#xff1a;SueWakeup 系列专栏&#xff1a;学习Java 个性签名&#xff1a;人生乏味啊&#xff0c;我欲令之光怪陆离 本文封面由 凯楠&#x1f4f7; 友情赞助! 目录 前言 悲观锁和乐观锁 什么是 CAS ? 什么是原子操作&#xff1f; CAS 执行流…

git 上传文件夹至远端仓库的方法

上传的远端git可以是gitlab、github、gitee、gitblit或者gitCode等等 以下以GitHub为例说明&#xff1a; 1、登录GitHub网站&#xff08;账户/密码&#xff09; 2、创建一个新的空白项目&#xff08;或者已有的项目&#xff09;hello-world 分支是master &#xff0c;这里默认即…

面经Java开发

联奕一面: 1、这段代码的输出结果是多少?t q z package com.smart.community.test;public class Test {public class B{static {System.out.println("t");}public B(){System.out.println("z");}}public class A extends B{static {System.out.println…