排序篇(七大基于比较的排序算法)

news2024/9/20 20:31:55

目录

插入排序

直接插入排序

希尔排序(缩小增量排序)

选择排序

选择排序

堆排序

交换排序

冒泡排序

快速排序

1.挖坑法

2.Hoare版

3.前后指针

快速排序优化

三数取中法 选基准数

2.递归到小的子区间时 可以考虑使用插入排序

非递归快速排序

归并排序

归并排序----非递归

其他非基于比较的排序

计数排序


几种常见的排序算法:

        1.插入排序:直接插入排序、希尔排序

        2.选择排序:选择排序、堆排序

        3.交换排序:冒泡排序、快速排序

        4.归并排序:归并排序

接下来我们一一讲解

插入排序

直接插入排序

思想:

当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移

简单点说 就是在已排好序的区间中 找到当前元素(无序区间)的应插入位置

代码实例:

特性:

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

空间复杂度:O(1) 它是一种稳定的排序算法

这里我们对稳定做下解释 当一个数组中 当采用某一排序算法时 重复数据原先在前面的仍在前面 这便称之为稳定

关于时间复杂度的分析:

· 最好情况下 也就是有序的时候 我们不需要移动元素 每次只需要比较一次即可 那么最好情况时的时间复杂度为O(N)

· 最坏情况下 也就是待排序区间为逆序的情况

例如: 9  8  7  6  5 (需要排为升序)

此时需要比较 1+2+3+4=10次

如果有n个元素的话 则需要比较1+2+3+....+(n-1)=n*(n-1)/2

所以最坏时间复杂度为:O(N^2)

空间复杂度分析:

插入排序不需要额外的存储空间 所以其空间复杂度为O(1)

稳定性分析:

根据插入排序思想可知 我们只会移动比temp值大的元素 所以我们排序后可以保证相同元素的相对位置不变 所以直接插入排序是稳定的

希尔排序(缩小增量排序)

思想:先选定一个整数gap  把待排序文件中所有记录分成多个组 所有距离为该整数gap的记录分在同一组内 并对每一组内的记录进行排序 然后 重复上述分组和排序的工作

直到该整数=1时 所有记录最后再统一排好序

特性:

1.希尔排序是对直接插入排序的优化

2.当gap>1时 都是预排序 目的是 让数组更接近于有序 当gap==1时 数组已经接近有序 这样就会很快 这样整体而言 可以达到优化的效果

3.希尔排序的时间复杂度不好计算 因为gap的取值方法有很多 导致很难去计算 因此在好些书中给出的希尔排序的时间复杂度都不固定

4.当然 希尔排序是不稳定的

代码实例:

选择排序

选择排序

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

例如升序:每一次从待排序的数据元素中 找到最小的那个元素 存放在序列的起始位置

代码1:

关于选择排序 我们还有另一种方法:同时找到最大和最小的元素 的下标 每次排好两个元素

代码实例:

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

空间复杂度:O(1)

稳定性:不稳定

堆排序

堆排序(HeapSort)是指利用堆积树(堆:完全二叉树)这种数据结构所设计的一种排序算法 它也是选择排序的一种 它是通过堆来进行选择数据

需要注意的是:排升序要建大堆  排降序要建小堆

现在我们来理解一下 什么是大/小堆

大堆:每个结点的值都不大于其父节点的值(也就是 结点的值较大)

小堆:每个结点的值都不小于其父节点的值(也就是 结点的值较小)

大堆(结点的值较大):

数组{6,7,9,4,5,1,3}建好大堆如下图:

小堆(结点的值较小):

看了这两张图后 我们发现 即使建好大堆/小堆后 仍然需要排序

大概流程:建大堆(升序)---->然后需要将根节点和从最后一个元素进行交换(根节点的值是最大的)  然后再重新建大堆  直到每个元素都与根节点交换过

现在呢 我们先进行建大堆:

首先呢 先创建parent child两个变量

parent指向最后一棵树的根   child指向最后一棵树的子树  然后依次将每棵树置成大堆

即:让child指向子树元素较大的 若child指向位置的元素大于parent处的元素 则交换

然后令parent-- 直到parent走到0下标处

接下来我们给出上述图片转化为大堆的过程图

当child指向超过下标最大值时 siftDown结束

展示代码:

在创建好大堆以后 我们就需要将根节点的数 与end指向的元素 进行交换

然后再重排大堆 让end--

整体代码:

时间复杂度:O(N*logN)

空间复杂度:O(1)

稳定性:不稳定

交换排序

冒泡排序

这里我们就不对冒泡排序进行讲解了 在之前有讲过

如果大家有些遗忘 可以通过下列链接进行复习

https://blog.csdn.net/L2770789195/article/details/137197253

快速排序

基本思想:任取待排序元素序列中的某元素作为基准值 按照该基准值 将待排序集合分割成两个子序列 左子序列中所有元素均小于基准值 右子序列中所有元素均大于基准值 然后重复该过程 直到所有元素都排列在相应位置上为止

1.挖坑法

我们先给个排序过程图:

代码实现

2.Hoare版

这个跟挖坑法也很相似 只是没有坑 当选择L处的元素作为基准值时 先让R移动 找到小于基准值的数 让L移动 找到大于基准值的数 然后让L、R两处的元素进行交换 当L、R相遇时 让相遇处的元素与基准数进行交换 然后在L、R相遇处的左右两侧接着重复上述步骤

3.前后指针

初始时 prev指针指向序列开头  cur指针指向prev指针的后一个位置

cur指针向后移动 寻找比基准值小的元素

当找到比基准值小的元素时 如果 ++prev和cur不相等 则交换prev和cur位置处的元素

这样做的原因是:cur和prev本身相差一个距离 当cur碰到几个大于基准值的元素时 prev就会与cur的距离增加几个距离 prev会停留在大于基准值处  当cur再次找到比基准值小的元素时 则可以把小于基准值的元素与大于基准值的元素进行交换 直到cur走到数组之外

代码实例:

总结:在这三种方法中 我们使用挖坑法最多 其次是Hoare法 至于前后指针已经使用的很少了

对于快速排序的过程 其实可以形象地用递归树来表示

具体来说 快速排序的递归树中的每个结点代表一次递归调用 左子树代表 对小于基准值的子数组进行排序的递归调用 右子树代表对大于基准值的子数组进行排序的递归调用

快速排序优化

  1. 三数取中法 选基准数

我们前面的基准数 选择的都是Left处的元素(也就是每个数组的最左侧元素)

但基准数当选择的过大或者过小时 会让数组排序的次数增加

如下图:

我们可以看到当选择的基准数过大时 会导致每次只排好一个元素或者很少的元素

而如果当选择的基准数为中间的数时 每次会排好一半的元素  大大减少了时间

所以我们三数取中法是 在最左侧、最右侧和中间的数中 选择某一位于两者区间的数

代码实例:

2.递归到小的子区间时 可以考虑使用插入排序

我们知道快速排序 每次会数组分成两个部分 类似于二叉树

这里 我们借用下之前的图:

在这里我们更加明显的看到了二叉树的样子

我们把每个圈当成一个数组 每次排序就会分成两个数组

当某一数组被分成另外几个数组时 也就是某一次递归 递归到剩余的几次 我们就可以采取直接插入排序  

我们在前面都是用递归实现快速排序的

现在我们来学习一下非递归的快速排序

非递归快速排序

我们知道在使用递归的快速排序中 递归起到了将数组一分为二的作用

所以我们的非递归排序的核心就是 如何将数组一分为二

这里我们需要一个栈来配合

先利用自已写过的代码(partition)找到基准数要替换到的位置--pivot

注意:partition在找到基准值要替换的位置的同时 也进行着将小于基准数的划分到左边 将大于基准数的划分到其右边

让基准数左右两侧数组的起始和结尾的下标入栈

注意:当基准数某一侧只剩下一个元素时 代表着已经有序 不需要再进行排序  

当pivot满足pivot>left+1或pivot<right-1 代表着至少有两个元素---》即需要入栈 排序

代码如下:

时间复杂度:O(N*logN)

空间复杂度:O(logN)

稳定性:不稳定

归并排序

基本思想:

归并排序(Merge Sort)是一种分而治之的排序算法。它将一个大的列表分成两个小列表,分别进行排序,然后将排序好的小列表合并成一个最终的排序列表。这个过程递归地进行,直到子列表的大小为1(因为只有一个元素的列表自然是排序好的)

归并排序算法主要包含两个主要步骤:

分解:将数组分解成两个较小的子数组,直到子数组的大小为1。

合并:将已排序的子数组合并成一个大的有序数组,直到合并为1个完整的数组

过程实例:

代码实现:

归并排序----非递归

在递归的归并排序中 递归的作用在于将数组进行分解

所以我们在 非递归中主要是将数组进行分解

我们利用gap当作每个子数组的大小

利用left mid right来指示要合并的区间

代码实现:

时间复杂度:O(N*logN)

空间复杂度:O(N)

稳定性:稳定

其他非基于比较的排序

计数排序

思想:计数排序又称为鸽巢原理 是对哈希直接定址法的变形应用

操作步骤:

  1. 统计相同元素出现次数
  2. 根据统计的结果将序列回收到原来的序列中

例如:

但也有一个问题 假如数组arr存放的是 {90,95,91,92,90,92}  tmp数组难道还要申请100个空间吗?

其实不然  我们仍然只需要申请max-min+1个空间 即:6个空间(下标:0~5)

只需要在放入tmp数组时 让 下标=元素-min

在tmp数组中 取出元素放入arr的时候 让元素=下标+min 即可

代码实现:

计数排序总结:

  1. 计数排序在数据范围集中时 效率很高 但是适用范围及场景有限
  2. 时间复杂度:O(N+(arr的长度))
  3. 空间复杂度:O(arr的长度)
  4. 稳定性:稳定

排序算法总结:

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

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

相关文章

「C++系列」异常处理

【人工智能教程】&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。 点击跳转到网站&#xff1a;【人工智能教程】 文章目录 一、异常处理1. 基本概念2. 示例代码3. 注意事项 二、常见的异常类…

如何使用宝塔面板安装中间件

如何快速安装中间件&#xff0c;宝塔镇河妖非常简单。 使用 SSH 连接工具&#xff0c;如堡塔SSH终端连接到您的 Linux 服务器后&#xff0c;挂载磁盘&#xff0c;根据系统执行相应命令开始安装&#xff08;大约2分钟完成面板安装&#xff09;&#xff1a; Centos安装脚本 yum…

分布式光伏发电系统如何确保电能质量达到并网要求?

随着全球对可再生能源的日益重视&#xff0c;光伏发电已成为推动能源转型的重要力量。特别是在应对气候变化、提升能源安全方面&#xff0c;光伏发电的潜力被广泛认同。然而&#xff0c;光伏电站的运营与维护面临许多挑战&#xff0c;如发电效率监测、故障诊断和数据管理等。因…

react hooks--useContext

概述 ◼ 在之前的开发中&#xff0c;我们要在组件中使用共享的Context有两种方式&#xff1a;  类组件可以通过 类名.contextType MyContext方式&#xff0c;在类中获取context&#xff1b; 多个Context或者在函数式组件中通过 MyContext.Consumer 方式共享context&…

基于云计算和大数据技术的传感器数据存储与分析系统

传感器被广泛用于监测环境参数&#xff0c;如温度、压力、湿度和特定气体的浓度。这些数据通常被收集并保存在数据存储系统中&#xff0c;随后进行分析以识别异常模式。在数据量巨大的情况下&#xff0c;传统的关系型数据库可能在性能上遇到瓶颈&#xff0c;使得处理和分析来自…

知道什么是热key吗?如何排查和处理?

目录标题 一、什么是热Key&#xff1f;二、热点key危害&#xff1f;三、如何发现热点 key&#xff1f;四、热点key应对措施 一、什么是热Key&#xff1f; 热 key 问题就是突然有几十万的请求去访问 redis 上的某个特定 key&#xff0c;那么这样会造成流量过于集中&#xff0c;…

Docker安装 ▎Docker详细讲解 ▎数据卷挂载 ▎Nginx安装理解

前言 Docker是一种容器化技术&#xff0c;简化软件的部署和管理。文章详细解释了Docker的架构、安装步骤和常用命令&#xff0c;帮助用户快速启动和管理容器。还介绍了Docker镜像命令和数据卷挂载的实例&#xff0c;增强对持久化存储的理解&#xff0c;并涵盖了Nginx的安装方法…

npm切换为淘宝镜像源

要切换 npm 的镜像源&#xff0c;您可以使用以下几种方法&#xff1a; 前言 然而&#xff0c;由于众所周知的网络环境问题&#xff0c;直接使用npm官方源下载依赖包时&#xff0c;常常会遇到速度慢甚至下载失败的情况。因此&#xff0c;使用更稳定、更快速的国内镜像源就显得尤…

C++ (进阶) ─── 多态

目录 1. 多态的概念 1.1 概念 2. 多态的定义及实现 2.1多态的构成条件 2.2 虚函数 2.3虚函数的重写 2.4 C11 override 和 final 2.5 重载、覆盖(重写)、隐藏(重定义)的对比 3. 抽象类 3.1 概念 3.2 接口继承和实现继承 试题&#xff1a; 1. 多态的概念 1.1 概念 …

计算机人工智能前沿进展-大语言模型方向-2024-09-18

计算机人工智能前沿进展-大语言模型方向-2024-09-18 1. The Application of Large Language Models in Primary Healthcare Services and the Challenges W YAN, J HU, H ZENG, M LIU, W LIANG - Chinese General Practice, 2024 人工智能大语言模型在基层医疗卫生服务中的应…

【算法】堆与优先级队列

【ps】本篇有 4 道 leetcode OJ。 目录 一、算法简介 二、相关例题 1&#xff09;最后一块石头的重量 .1- 题目解析 .2- 代码编写 2&#xff09;数据流中的第 K 大元素 .1- 题目解析 .2- 代码编写 3&#xff09;前K个高频单词 .1- 题目解析 .2- 代码编写 4&#xf…

什么是泛在智能?应用在哪些场景?

泛在智能是一个融合了多种技术概念和应用场景的综合性概念&#xff0c;其核心在于通过广泛嵌入的感知和计算设备&#xff0c;以及智能的人机交互界面&#xff0c;实现对环境、人和物的全面感知与智能响应。 定义与背景 泛在智能&#xff08;Ambient Intelligence&#xff09;是…

用Python画一个五星红旗

#codingutf-8 import turtle import mathdef draw_polygon(aTurtle, size50, n3): 绘制正多边形args:aTurtle: turtle对象实例size: int类型&#xff0c;正多边形的边长n: int类型&#xff0c;是几边形 for i in range(n):aTurtle.forward(size)aTurtle.left(360.0/n)de…

Koa (下一代web框架) 【Node.js进阶】

koa (中文网) 是基于 Node.js 平台的下一代 web 开发框架&#xff0c;致力于成为应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石&#xff1b; 利用 async 函数 丢弃回调函数&#xff0c;并增强错误处理&#xff0c;koa 没有任何预置的中间件&#xff0c;可快速…

DevExpress WinForms v24.1新版亮点:升级的HTML CSS支持

DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜…

mavlink源码编译及示例使用

1.克隆源码: git clone https://github.com/mavlink/mavlink.git --recursive 克隆成功: 2.克隆python3与pip已安装 3.安装依赖: python3 -m pip install -r pymavlink/requirements.txt

[JavaEE]———进程、进程的数据结构、进程的调度

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯&#xff0c;你们的点赞收藏是我前进最大的动力&#xff01;&#xff01;希望本文内容能帮到你&#xff01; 目录 一&#xff1a;操作系统 1&#xff1a;操作系统的定位和功能 2&#xff1a;多任务操作系统 3&#xff1a…

硬件开篇——体系架构

1、驱动开发分类&#xff1a; 裸机驱动&#xff08;无操作系统&#xff09;——由寄存器控制&#xff1b;Linux驱动。 硬件&#xff1a; 计算机系统&#xff1a; 计算机架构&#xff1a;①冯诺依曼&#xff08;指令、数据一起&#xff09;②哈佛&#xff08;指令、数据分开&a…

【BoF】《Bag of Freebies for Training Object Detection Neural Networks》

arXiv-2019 https://github.com/dmlc/gluon-cv 文章目录 1 Background and Motivation2 Related Work3 Advantages / Contributions4 Method4.1 Visually Coherent Image Mixup for Object Detection4.2 Classification Head Label Smoothing4.3 Data Preprocessing4.4 Traini…

如何使用ssm实现理财通的设计与实现

TOC ssm638理财通的设计与实现jsp 第一章 绪论 1.1 选题背景 目前整个社会发展的速度&#xff0c;严重依赖于互联网&#xff0c;如果没有了互联网的存在&#xff0c;市场可能会一蹶不振&#xff0c;严重影响经济的发展水平&#xff0c;影响人们的生活质量。计算机的发展&am…