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

news/2024/9/19 4:54:59 标签: 排序算法, 算法, 数据结构, java, 笔记

目录

插入排序

直接插入排序

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

选择排序

选择排序

堆排序

交换排序

冒泡排序

快速排序

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.niftyadmin.cn/n/5665012.html

相关文章

大数据新视界 --大数据大厂之探索ES:大数据时代的高效搜索引擎实战攻略

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

828 华为云征文|华为 Flexus 云服务器部署 RustDesk Server,打造自己的远程桌面服务器

&#x1f4bb;在当今数字化时代&#xff0c;远程桌面服务器的需求日益增长。华为 Flexus 云服务器凭借其强大的性能和稳定性&#xff0c;为部署 RustDesk Server 提供了理想的平台。在 2024 年 9 月 14 日这个特别的日子里&#xff0c;我们将一起探索如何在华为 Flexus 云服务器…

OpenCV运动分析和目标跟踪(2)累积操作函数accumulateSquare()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 将源图像的平方加到累积器图像中。 该函数将输入图像 src 或其选定区域提升到2的幂次方&#xff0c;然后加到累积器 dst 中&#xff1a; dst ( …

弹性负载均衡ELB 详解和设置方法

一、弹性负载均衡ELB 详解 1. 定义与概念 弹性负载均衡&#xff08;Elastic Load Balancing&#xff0c;简称ELB&#xff09;是一种将访问流量自动分发到多台云服务器的流量分发控制服务。它通过在多个后端服务器之间均衡分配请求&#xff0c;提高应用程序的可用性、可扩展性…

在 Linux 系统中目录架构说明

在 Linux 系统中&#xff0c;根目录&#xff08;/&#xff09;是整个文件系统的起点&#xff0c;其下有许多重要的目录&#xff0c;以下是对一些主要目录的说明&#xff1a; 一、/bin 存放着最常用的二进制可执行命令&#xff0c;例如 ls、cat、cp、mv 等。普通用户和超级用户…

24年蓝桥杯及攻防世界赛题-MISC-2

11 Railfence fliglifcpooaae_hgggrnee_o{cr} 随波逐流编码工具 分为5栏时&#xff0c;解密结果为:flag{railfence_cipher_gogogo} 12 Caesar rxms{kag_tmhq_xqmdzqp_omqemd_qzodkbfuaz} mode1 #12: flag{you_have_learned_caesar_encryption} 随波逐流编码工具 13 base64…

计算机视觉——基于OpenCV和Python进行模板匹配

模板匹配是计算机视觉中的一项基本技术&#xff0c;它用于在较大的图像中寻找与给定模板图像最匹配的区域。在OpenCV中&#xff0c;这一过程可以通过matchTemplate函数轻松实现。本文将详细介绍模板匹配的原理、方法以及如何在Python中使用OpenCV进行模板匹配。 模板匹配原理 …

ArcGIS Pro SDK (十五)共享

ArcGIS Pro SDK (十五)共享 文章目录 ArcGIS Pro SDK (十五)共享1 ArcGIS 项目管理器:获取当前活动门户2 ArcGIS 项目管理器:获取所有门户的列表3 ArcGIS 项目管理器:将门户添加到门户列表4 ArcGIS 项目管理器:获取门户并登录,将其设置为活动状态5 ArcGIS 程序管理器:…