排序算法二 归并排序和快速排序
目录
归并排序
快速排序
1 挖坑法编辑
2 Hoare法
快排的优化
快排的非递归方法
七大排序算法复杂度及稳定性分析
归并排序
归并排序是建立在归并操作上的一种有效的排序算法,将以有序的子序列合并,得到完全有序的序列,即先使每个子序列有序,在使子序列段间有序.若将两个有序的序列合并成一个有序表,成为二路归并.

归并排序的递归写法:
1: 首先建行区间一分为二,分裂点 : mid = ( left + right ) / 2;
2: 递归的对两个子区间array[left..mid] 和 array[mid+1 ... right]进行归并排序.递归的终止条件是子区间的长度为1.
3: 将两个子区间归并为一个有序的空间.但我们归并右树的时候不是从原来数组的0下标开始,所以我们在归并的时候要加上他原来数组所在的下标 即 array[i + start] = tmp[i];

代码:
public void mergeSort(int[] array) {sort(array,0,array.length-1)}private void sort(int[] array,int left,int right) {if(left >= right) {return;}int mid = (left + right) / 2;sort(array,left,mid);sort(array,mid+1,right);//合并merge(array,left,right,mid);}//合并private void merge(int[] array,int start,int end,int mid) {int s1 = start;int s2 = mid + 1;int[] tmp = new int[end - start + 1];int k = 0;while(s1 <= mid && s2 <= end) {if(array[s1] <= array[s2]) {tmp[k++] = array[s1++];} else {tmp[k++] = array[s2++];}}while(s1 <= mid) {tmp[k++] = array[s1++]}while(s2 <= end) {tmp[k++] = array[s2++];}for (int i = 0; i < tmp.length; i++) {array[i + start] = tmp[i];}}
}
归并排序的非递归写法:

首先将一组序列的每个元素看做一个单独的序列,进行比较之后排好序,然后在每两个一组进行比较,直到组数和和序列的个数相同,序列就拍好序了

归并排序的特性总结 :
归并排序的时间复杂度是O(N* log₂N),空间复杂度是O(N),稳定性是稳定的排序
快速排序
快速排序是一种二叉树结构的交换排序方法,其基本思想是任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序结合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后按照左右子序列重复该过程,直到所有元素排列在相应位置上位置.
动图展示

快速排序有很多方法,在这里我主要讲两种方法
1 挖坑法

首先我们在这个排序序列中随便找一个基准值,通常为了方便,以第一个数作为基准值,然后我们从后往前找比基准值小的元素,找到后把这个元素放到基准值的位置

然后我们从前往后找比基准值大的元素,然后把这个元素放到坑里.会出现一个新的坑

然后重复上面操作直到将left和right相遇,我们把基准值放到坑位里面.

代码展示

大家想想,我们在内层while循环中, <= 和 >=能换成> 和 < 吗?
答案是不可以的

当最后一个元素和第一个元素大小相等的时候,如果取 > 和 < 的情况下,是要进行和基准值交换的,当从后往前走完后,从前往后走,又满足交换条件,这样就成了死循环.
2 Hoare法

同样的方法我们先找一个基准,然后从后往前找比基准值小的,找到后从前往后找比基准值大的,找到后交换两个的位置
然后重复上面的操作直到lleft和right相遇

然后让array[left] 和基准值交换位置,我们发现比基准值小的都在基准值的左边,比基准值大的都在基准值的右边

根据两种方法的比较,我们会发现两种序列的顺序是不一样的,

当我们左边找基准值的时候,为什么要从右边先走呢?

以Hoare法为例,当我们先从左边走,在走右边,交换后right位置的值一定比基准值大,当Left和right相遇的时候,将左边的值和基准值交换,较大值就排到前面去了,就不满足基准值左边的都比基准值小的性质了
快速排序的基本特性
快速排序是一种二叉树结构的交换排序方法.
时间复杂度: 最好的情况 O(N * log₂ N) ,最坏的情况给的序列本来就有序,在递归的时候只会是一棵单支树,树的高度就为N,时间复杂度为O(N ^ 2),
空间复杂度: 最好情况: O(log₂ N), 最坏情况 : O(N)
稳定性: 不稳定的
快速排序需要再系统内部用一个栈来实现递归,每层递归调用时的指针和参数均需要用栈来存放,快速排序的递归过程可以用一颗二叉树来表示,当数据量较大时,在最坏的情况时,可能会发生栈溢出异常,所以我们要对快速排序进行优化.
快排的优化
三数取中法
在一组排序序列中,我们选取三个数,分别是第一个数,中间位置的数和最后一个数,在这三个数中选取中间大的数作为基准数. 这样就不会出现单支树的情况.
如何在三个数中找中间大的数呢?

快速排序是一种二叉树结构的交换排序方法.在二叉树中,层数越多,下面的节点数就越多,也趋于有序,在后面两层可以直接使用直接插入法进行排序,减少递归的次数.
public void quickSort(int[] array) {quick(array,0,array.length-1);}private void quick(int[]array,int start, int end) {if(start >= end) {return ;}if(end - start + 1 <= 14) {//插入排序insertSoft2(array,start,end);return;}int index = midThree(array,start,end);swap(array,index,start);int piovt = partition(array,start,end);quick(array,start,piovt-1);quick(array,piovt+1,end);}private int partition(int[] array,int left,int right) {int tmp = array[left];int i = left;while(left < right) {while(left < right && array[right] >= tmp) {right--;}array[left] = array[right];while(left < right && array[left] <= tmp) {left++;}swap(array,left,right);}swap(array,left,i);return left;}public static void insertSoft2(int[] array,int left,int right) {for(int i = left+1; i <= right;i++) {int tmp = array[i];int j = i -1;for(j =i-1; j >= left ;j--) {if(array[j] > tmp) {array[j+1] = array[j];} else {array[j+1] = tmp;break;}}array[j+1] = tmp;}}
快排的非递归方法
在第一次找到基准值之后,我们将基准值左边和右边的下标放到栈中,
第一次弹出栈顶元素给到right在弹出栈顶元素给left.重新找基准值,找到后把基准值左右两边重新入栈,重复上述操作但当基准值左右两边只有一个元素的时候,就不需要再入栈,此时已经是有序的了,把最开始的基准值右边的排完后,排基准值左边的.,直到栈为空的时候,排完序.
第一次弹出栈顶元素给到right在弹出栈顶元素给left.重新找基准值,找到后把基准值左右两边重新入栈,重复上述操作但当栈为空的时候排序完成
public void quickSort(int[] array) {Deque<Integer> stack = new LinkedList<>();int left = 0;int right = array.length - 1;int pivot = partition(array,left,right);if(pivot > left + 1) {stack.push(left);stack.push(pivot -1);}if(pivot < right- 1) {stack.push(pivot+ 1);stack.push(right);}while(!stack.isEmpty()) {right = stack.pop();left = stack.pop();pivot = partition(array,left,right);if(pivot > left + 1) {stack.push(left);stack.push(pivot -1);}if(pivot < right- 1) {stack.push(pivot+ 1);stack.push(right);}}
}
private int partition(int[] array,int left,int right) {int tmp = array[left];while(left < right) { while(left < right && array[right] >= tmp) {right--;}array[left] = array[right];while(left < right && array[left] <= tmp) {left++;}array[right] = array[left];}array[left] = tmp;return left;}}
七大排序算法复杂度及稳定性分析

相关文章:
排序算法二 归并排序和快速排序
目录 归并排序 快速排序 1 挖坑法编辑 2 Hoare法 快排的优化 快排的非递归方法 七大排序算法复杂度及稳定性分析 归并排序 归并排序是建立在归并操作上的一种有效的排序算法,将以有序的子序列合并,得到完全有序的序列,即先使每个子序列有序,在使子序列段间有序.若将两…...
活动回顾 | 暴雨也无法阻挡的奔赴,2023 Meet TVM · 深圳站完美收官!
2023 Meet TVM 深圳站于 2023 年 9 月 16 日在腾讯大厦成功举办,百余名参与者亲临现场,聆听讲师们的精彩分享。 作者 | xixi 编辑 | 三羊 本文首发于 HyperAI 超神经微信公众平台~ **由 MLC.AI 社区和 HyperAI超神经主办,Openbayes贝式计算…...
JAVA_多线程的实现方式
线程的状态 方式一: public class Thread1 extends Thread {Overridepublic void run() {synchronized (this) {for (int i 0; i < 100; i) {System.out.println(getName() "" i);}}} } Thread1 thread1 new Thread1(); thread1.start(); 方式二…...
Android AndroidStudro版本gradle版本对应
详情网站:Android studio版本对用的gradle版本和插件版本(注意事项)...
Windows所有的端口及端口对应的程序
Windows所有的端口及端口对应的程序 1.查询Windows的端口 在CMD窗口运行: netstat -ano 结果示例: 活动连接协议 本地地址 外部地址 状态 PIDTCP 0.0.0.0:135 0.0.0.0:0 LISTENING 1156T…...
【Kafka系列】(二)Kafka的基本使用
有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址[1] 文章更新计划[2] 系列文章地址[3] Kafka 线上集群部署方案怎么做 操作系统 先说结论,Kafka 部署在 Linux 上要比 Window…...
2023年下半年软考高级系统架构设计师论文指南(收藏)
由于今年下半年软考改为了机考,所以今年是看大家码字的速度了,但是好处还是有的,错了还能删除,之前纸质的 还有点不方便。 1、选择题目 (1)控制选题的时间。不要浪费太多时间在纠结选题上面。 ÿ…...
数据结构之【动态数组】
1. 线性表 概念:线性表是n个具有相同特性的数据元素的有限序列。 常见的线性表有:数组、链表、栈、队列、字符串…… 特点: 保存在这个结构中的元素都是相同的数据类型。元素之间线性排列,元素之间在逻辑上是连续的。 线性表…...
解答嵌入式和单片机的关系
嵌入式系统是一种特殊的计算机系统,用于特定任务或功能。而单片机则是嵌入式系统的核心部件之一,是一种在单个芯片上集成了处理器、内存、输入输出接口等功能的微控制器。刚刚好我这里有一套单片机保姆式教学,里面有编程教学、问题讲解、语言…...
利用Pycharm将python程序打包为exe文件(亲测可用)
最近做了一个关于py的小项目,对利用Pycharm将python文件打包为exe文件不是很熟悉,故学习记录之。 目录 一、下载pyinstaller库 二、打开Pycharm进行打包(不更改图标) 三、打开Pycharm进行打包(更改图标)…...
解决Vue设置图片的动态src不生效的问题
一、问题描述 在vue项目中,想要动态设置img的src时,此时发现图片会加载失败。在Vue代码中是这样写的: 在Vue的data中是这样写的: 我的图片在根目录下的static里面: 但是在页面上这个图片却无法加载出来。 二、解决方案…...
企业关键数据采集如何做
数据对于企业的重要性不言而喻,目前又处于大数据时代,企业对于数据的解读将是辅助决策最重要的一环。依据所掌握的数据信息,帮助企业做决策的优化。然而,在企业的关键数据采集并不是一项简单轻松的任务,他需要企业投入…...
抖音SEO矩阵系统源码开发搭建
1. 确定需求和功能:明确系统的主要目标和需要实现的功能,包括关键词研究、短视频制作、外链建设、数据分析、账号设置优化等方面。 2. 设计系统架构:根据需求和功能确定系统的架构,包括前端、后端、数据库等部分的设计࿰…...
20230925工作心得
1、如果使用map的时候,担心key重复,覆盖掉值 那么直接加个if/else判断就好了。 如果map.containsKey,那么就把值追加上去,否则就直接put。 2、list的removeAll方法 list.removeAll(list2);//list要removeAll谁,就是看list自己比…...
ESP32在CAN(TWAI)波特率不同时收发数据,导致总线错误无法恢复
问题描述: 总线上有两个设备,主机:100ms周期发送数据。从机:以不同波特率发送数据,再把从机波特率调节至主机波特率一致无法通信。 环境:VSCODE IDF-v5.0 问题分析: 我们先看下ESP32技术参…...
精简版背包问题|01背包、完全背包、多重背包
背包问题 01背包问题 有n个物品,它们有各自的体积w和价值v,现有给定容量W的背包,在总体积不超过背包承载上限的情况下,如何让背包里装入的物品具有最大的价值总和?(每个物品最多可使用一次) w(…...
五、核支持向量机算法(NuSVC,Nu-Support Vector Classification)(有监督学习)
和支持向量分类(Nu-Support Vector Classification),与 SVC 类似,但使用一个参数来控制支持向量的数量,其实现基于libsvm 一、算法思路 本质都是SVM中的一种优化,原理都类似,详细算法思路可以参考博文:三…...
个人废品回收小程序制作步骤详解
在当今的环保时代,个人废品回收小程序的发展显得尤为重要。为了满足这一需求,本文将详细介绍如何制作一个个人废品回收小程序。 第一步,进入乔拓云网后台,点击【轻应用小程序】进入设计小程序页面。在这个页面,你可以看…...
Python爬虫自动切换爬虫ip的完美方案
在进行网络爬虫时,经常会遇到需要切换爬虫ip的情况,以绕过限制或保护自己的爬虫请求。今天,我将为你介绍Python爬虫中自动切换爬虫ip的终极方案,让你的爬虫更加高效稳定。 步骤一:准备爬虫ip池 首先,你需要…...
IDEA新建.xml文件显示为普通文本
情况如下: 1. 在XML文件中添加*.xml的文件名模式 2. 在文本中,选中*.xml进行删除...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
