当前位置: 首页 > news >正文

排序算法二 归并排序和快速排序

目录

归并排序

快速排序

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循环中, <= 和 >=能换成> 和 < 吗?

答案是不可以的 

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

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 日在腾讯大厦成功举办&#xff0c;百余名参与者亲临现场&#xff0c;聆听讲师们的精彩分享。 作者 | xixi 编辑 | 三羊 本文首发于 HyperAI 超神经微信公众平台~ **由 MLC.AI 社区和 HyperAI超神经主办&#xff0c;Openbayes贝式计算…...

JAVA_多线程的实现方式

线程的状态 方式一&#xff1a; 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版本对应

详情网站&#xff1a;Android studio版本对用的gradle版本和插件版本&#xff08;注意事项&#xff09;...

Windows所有的端口及端口对应的程序

Windows所有的端口及端口对应的程序 1.查询Windows的端口 在CMD窗口运行&#xff1a; netstat -ano 结果示例&#xff1a; 活动连接协议 本地地址 外部地址 状态 PIDTCP 0.0.0.0:135 0.0.0.0:0 LISTENING 1156T…...

【Kafka系列】(二)Kafka的基本使用

有的时候博客内容会有变动&#xff0c;首发博客是最新的&#xff0c;其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址[1] 文章更新计划[2] 系列文章地址[3] Kafka 线上集群部署方案怎么做 操作系统 先说结论&#xff0c;Kafka 部署在 Linux 上要比 Window…...

2023年下半年软考高级系统架构设计师论文指南(收藏)

由于今年下半年软考改为了机考&#xff0c;所以今年是看大家码字的速度了&#xff0c;但是好处还是有的&#xff0c;错了还能删除&#xff0c;之前纸质的 还有点不方便。 1、选择题目 &#xff08;1&#xff09;控制选题的时间。不要浪费太多时间在纠结选题上面。 &#xff…...

数据结构之【动态数组】

1. 线性表 概念&#xff1a;线性表是n个具有相同特性的数据元素的有限序列。 常见的线性表有&#xff1a;数组、链表、栈、队列、字符串…… 特点&#xff1a; 保存在这个结构中的元素都是相同的数据类型。元素之间线性排列&#xff0c;元素之间在逻辑上是连续的。 线性表…...

解答嵌入式和单片机的关系

嵌入式系统是一种特殊的计算机系统&#xff0c;用于特定任务或功能。而单片机则是嵌入式系统的核心部件之一&#xff0c;是一种在单个芯片上集成了处理器、内存、输入输出接口等功能的微控制器。刚刚好我这里有一套单片机保姆式教学&#xff0c;里面有编程教学、问题讲解、语言…...

利用Pycharm将python程序打包为exe文件(亲测可用)

最近做了一个关于py的小项目&#xff0c;对利用Pycharm将python文件打包为exe文件不是很熟悉&#xff0c;故学习记录之。 目录 一、下载pyinstaller库 二、打开Pycharm进行打包&#xff08;不更改图标&#xff09; 三、打开Pycharm进行打包&#xff08;更改图标&#xff09…...

解决Vue设置图片的动态src不生效的问题

一、问题描述 在vue项目中&#xff0c;想要动态设置img的src时&#xff0c;此时发现图片会加载失败。在Vue代码中是这样写的&#xff1a; 在Vue的data中是这样写的&#xff1a; 我的图片在根目录下的static里面&#xff1a; 但是在页面上这个图片却无法加载出来。 二、解决方案…...

企业关键数据采集如何做

数据对于企业的重要性不言而喻&#xff0c;目前又处于大数据时代&#xff0c;企业对于数据的解读将是辅助决策最重要的一环。依据所掌握的数据信息&#xff0c;帮助企业做决策的优化。然而&#xff0c;在企业的关键数据采集并不是一项简单轻松的任务&#xff0c;他需要企业投入…...

抖音SEO矩阵系统源码开发搭建

1. 确定需求和功能&#xff1a;明确系统的主要目标和需要实现的功能&#xff0c;包括关键词研究、短视频制作、外链建设、数据分析、账号设置优化等方面。 2. 设计系统架构&#xff1a;根据需求和功能确定系统的架构&#xff0c;包括前端、后端、数据库等部分的设计&#xff0…...

20230925工作心得

1、如果使用map的时候&#xff0c;担心key重复&#xff0c;覆盖掉值 那么直接加个if/else判断就好了。 如果map.containsKey&#xff0c;那么就把值追加上去&#xff0c;否则就直接put。 2、list的removeAll方法 list.removeAll(list2);//list要removeAll谁,就是看list自己比…...

ESP32在CAN(TWAI)波特率不同时收发数据,导致总线错误无法恢复

问题描述&#xff1a; 总线上有两个设备&#xff0c;主机&#xff1a;100ms周期发送数据。从机&#xff1a;以不同波特率发送数据&#xff0c;再把从机波特率调节至主机波特率一致无法通信。 环境&#xff1a;VSCODE IDF-v5.0 问题分析&#xff1a; 我们先看下ESP32技术参…...

精简版背包问题|01背包、完全背包、多重背包

背包问题 01背包问题 有n个物品&#xff0c;它们有各自的体积w和价值v&#xff0c;现有给定容量W的背包&#xff0c;在总体积不超过背包承载上限的情况下&#xff0c;如何让背包里装入的物品具有最大的价值总和&#xff1f;&#xff08;每个物品最多可使用一次&#xff09; w(…...

五、核支持向量机算法(NuSVC,Nu-Support Vector Classification)(有监督学习)

和支持向量分类(Nu-Support Vector Classification)&#xff0c;与 SVC 类似&#xff0c;但使用一个参数来控制支持向量的数量&#xff0c;其实现基于libsvm 一、算法思路 本质都是SVM中的一种优化&#xff0c;原理都类似&#xff0c;详细算法思路可以参考博文&#xff1a;三…...

个人废品回收小程序制作步骤详解

在当今的环保时代&#xff0c;个人废品回收小程序的发展显得尤为重要。为了满足这一需求&#xff0c;本文将详细介绍如何制作一个个人废品回收小程序。 第一步&#xff0c;进入乔拓云网后台&#xff0c;点击【轻应用小程序】进入设计小程序页面。在这个页面&#xff0c;你可以看…...

Python爬虫自动切换爬虫ip的完美方案

在进行网络爬虫时&#xff0c;经常会遇到需要切换爬虫ip的情况&#xff0c;以绕过限制或保护自己的爬虫请求。今天&#xff0c;我将为你介绍Python爬虫中自动切换爬虫ip的终极方案&#xff0c;让你的爬虫更加高效稳定。 步骤一&#xff1a;准备爬虫ip池 首先&#xff0c;你需要…...

IDEA新建.xml文件显示为普通文本

情况如下&#xff1a; 1. 在XML文件中添加*.xml的文件名模式 2. 在文本中&#xff0c;选中*.xml进行删除...

linux的三剑客

1、grep命令 grep全称是Global Regular Expression Print&#xff0c;表示全局正则表达式版本&#xff0c;它的使用权限是所有用户。它是Linux系统中一种强大的文本搜索工具&#xff0c;它能使用正则表达式搜索文本&#xff0c;并把匹配的行打印出来。 shell脚本中也经常使用g…...

微信小程序部分知识点总结【2】

微信小程序的原理是什么 微信小程序的原理是基于一种轻量级的应用程序模型&#xff0c;它允许开发者在微信客户端内部创建和运行应用程序。微信小程序采用了类似网页的技术栈&#xff0c;主要由两部分组成&#xff1a;前端和后端。 前端部分使用HTML、CSS和JavaScript等标准的…...

基于springboot+vue的云南旅游网(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…...

后缀表达式求值

后缀表达式&#xff0c;又称逆波兰式&#xff0c;指的是不包含括号&#xff0c;运算符放在两个运算对象的后面&#xff0c;所有的计算按运算符出现的顺序&#xff0c;严格从左向右进行。 运用后缀表达式进行计算的具体做法&#xff1a; 建立一个操作数栈S。然后从左到右读表达…...

基于springboot+vue的信息技术知识赛系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…...

基于YOLOv8模型的垃圾满溢检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOv8模型的垃圾满溢检测系统可用于日常生活中检测与定位车辆垃圾&#xff08;garbage&#xff09;、垃圾桶&#xff08;garbage_bin&#xff09;和垃圾满溢&#xff08;overflow&#xff09;目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等…...

面试算法14:字符串中的变位词

题目 输入字符串s1和s2&#xff0c;如何判断字符串s2中是否包含字符串s1的某个变位词&#xff1f;如果字符串s2中包含字符串s1的某个变位词&#xff0c;则字符串s1至少有一个变位词是字符串s2的子字符串。假设两个字符串中只包含英文小写字母。例如&#xff0c;字符串s1为&quo…...

中国社科院大学-美国杜兰大学金融管理硕士暨能源管理硕士项目2023年毕业典礼

中国社科院大学-美国杜兰大学金融管理硕士暨能源管理硕士项目2023年毕业典礼 2023年9月16日&#xff0c;中国社会科学院大学-美国杜兰大学金融管理硕士项目暨能源管理硕士项目2023年毕业典礼在我校望京校区成功举办。 张波副校长致辞 中国社会科学院大学副校长张波教授、杜兰大…...

蓝桥杯 题库 简单 每日十题 day10

01 最少砝码 最少砝码 问题描述 你有一架天平。现在你要设计一套砝码&#xff0c;使得利用这些砝码 可以出任意小于等于N的正整数重量。那么这套砝码最少需要包含多少个砝码&#xff1f; 注意砝码可以放在天平两边。 输入格式 输入包含一个正整数N。 输出格式 输出一个整数代表…...

聊聊并发编程——多线程之synchronized

目录 一.多线程下数据不一致问题 二.锁和synchronized 2.1 并发编程三大特性 2.2引入锁概念 三.synchronized的锁实现原理 3.1 monitorenter和monitorexit 3.2synchronized 锁的升级 3.2.1偏向锁的获取和撤销 3.2.2轻量级锁的加锁和解锁 自适应自旋锁 轻量级锁的解锁…...