快速排序的性能和名字一样优秀
前言
上次分享的冒泡排序虽然比较简单、容易理解,但每一次冒泡的过程都需要依次比较相邻的元素,然后交换,可见性能还是有很大的优化空间,只要能减少比较次数,性能自然就上去啦;快速排序便是一个很不错的选择~~~
正文
1.1 快速排序算法思想
快速排序(Quicksort)是对上一次分享的冒泡排序算法的一种改进,主要是减少比较次数,以此来提高排序性能;也属于交换排序的一种。
算法思想
在待排序列表中任取一个元素作为基准值;
将剩下的元素和基准值依次比较,小于的放左边,大于的放右边,最后通过一趟排序将待排序列表分为左右两部分,这个过程称为一次“划分”;
然后用同样的方法分别在左右两部分中取基准值进行排序,依次递归,直到划分的每部分内只有一个元素或空为止,则排序结束。
1.2 快速排序算法实现与解析
算法实现
划分代码实现,每一次取对应部分的首位元素作为基准值,然后通过依次比较,将对应数据又在细分为左右两部分,如下实现:
image-20210506133026759
使用递归进行划分排序,直到只有一个元素或为空为止:
image-20210506133313691
运行效果
image-20210506133449121
步骤解析(升序):
image-20210506135153320
上图步骤说明:
上图演示是针对数组array进行升序排序,第一次以全部数据为一组,low为0,high为5,选择low位元素2为基准值(即第一个元素),开始进行比较:
第1.1步:由于刚开始选择low位的元素为基准值(可以认为这个位置空了),所以接下来开始从high位开始遍历比较,high位元素3大于2,不用交换位置,high减1,继续比较;
第1.2步:此时low为0,high为4,high位元素9大于2,不用交换位置,high减1,继续比较;
第1.3步:此时low为0,high为3,high位元素1小于2,需要将high位元素1放到基准值的左边,则将元素1放到low指向的位置;
第1.4步:此时low为0,high为3,由于high位已经交换过了(可以认为这个位置空了),所以这次开始到low位进行遍历比较,low位元素是刚交换过来的,所以不用交换位置;low加1继续比较,此时low为1,对应位置的元素5大于基准值2,所以需要将元素5放到基准值的右边,则将元素5放到high指向位置;
第1.5步:此时low为1,high为3,由于low位已经交换过了(可以认为这个位置空了),所以这次又回到high位进行遍历比较,high位元素是刚交换过来的,所以不用交换位置;high减1继续比较,此时high为2,对应位置元素6大于基准值2,所以不用交换位置,high减1,继续比较;
第1.6步:此时low为1,high为1,此时代表第一次划分排序完成,则将基准值放到这个位置;最终将原始数据分为左右两部分,左部分只有一个元素1,不用再划分了,右部分有6,5,9,3四个元素,继续对于右部分进行划分;
第2.1步:由于右部分是从索引位2开始,所以此时low为2,high为5,基准值为low为的元素6;
第2.2步:由于刚开始选择low位的元素为基准值(可以认为这个位置空了),接下来从high为开始遍历比较,high为元素3小于基准元素6,需要将其放到基准元素的左边,则将元素3放到low指向的位置。
第2.3步:此时low为2,high为5,由于high位已经交换过了(可以认为这个位置空了),所以这次开始到low位进行遍历比较,low位元素是刚交换过来的,所以不用交换位置;low加1继续比较,此时low为3,对应位置的元素5小于6,不需要交换元素,则low加1,继续比较;
第2.4步:此时low为4,high为5,low位对应的元素9大于基准值6,所以需要将其放到基准元素的右边,则将元素9放到high指向的位置。
第2.3步:此时low为4,high为5,由于low位已经交换过了(可以认为这个位置空了),所以这次开始到high位进行遍历比较,high位元素是刚交换过来的,所以不用交换位置;high减1继续比较,此时high为4,此时low和high都为4,找到此次划分基准值的位置,则将基准元素6的放到4位置;到这又将原来的右部分6,5,9,3四个元素划分为左右两部分,右边只有一个元素9,不用继续划分;左边有元素3和5,继续划分排序;(这里就不重复演示)
最终通过递归划分排序的方式,直到每个划分部分内只有一个元素或空为止,即可获得最后的排序结果。
1.3 快速排序算法分析
时间复杂度
从上面解析步骤得知,每一次排序都是只需要处理剩下未排序的元素,每一次排序时间复杂度不会超过O(n),但由于是通过递归进行划分排序,所以快速排序的整体时间复杂度和递归层数有关,即总的时间复杂度为O(n*递归层数);
通过上面演示得知,其实最终将待排序数据划分为一个二叉树结构,在这二叉树的高度就代表递归的层数(后续会专门分享这块内容),如下图:
关于n个元素的二叉树的最小高度为(log2n)+1,最大高度为n,如果待排序数据已经有序或逆序,如果每次都选择每部分的首个元素为基准值,这样就会导二叉树高度增加,即递归深度就会增加;所以快速排序的时间复杂度最好为O(nlog2n),最坏为O(n2);
这样以为快速排序就不行了吗?当然不是,可以随机选一个元素做为基准值,这样不管待排序数据为有序还是逆序,都不会导致递归深度太深。所以最后快速排序的平均时间复杂度为O(nlog2n)
空间复杂度
空间复杂度在每次递归当中,用到的变量都是固定的(pivot,low,high),则最终影响空间复杂度的因素还是递归层数,则快速排序空间复杂度为O(递归层数), 最好为O(log2n),最坏为O(n)。
稳定性
由于是用待排序数据和基准值进行比较,所以最终元素交换位置不是固定的,则不能保证两个相等元素原有顺序不变,则快速排序是不稳定的。如下图:
如果取low位置的元素3作为基准值,最终会和元素2进行交换,最后就不能保证原来相等元素的前后顺序了。
综上所述,快速排序的时间复杂度为O(nlog2n),空间复杂度为O(log2n),是不稳定算法;
总结
快速排序有效的解决了冒泡排序的缺陷,减少了比较次数,提升了排序性能。但当待排序列表为有序或逆序时,如果单纯的取第一个元素或最后一个元素作为基准值,排序性能并没有提升。所以实现排序算法的关键是需要选个好的基准值,比如可以随机选择,也可以定义一个规则选择,看小伙伴的实现方式咯。
感谢小伙伴的:点赞、收藏和评论,下期继续~~~
一个被程序搞丑的帅小伙,关注"Code综艺圈",跟我一起学~~~
快速排序的性能和名字一样优秀相关推荐
- 数据结构(八):排序 | 插入排序 | 希尔排序 | 冒泡排序 | 快速排序 | 简单选择排序 | 堆排序 | 归并排序 | 基数排序 | 外部排序 | 败者树 | 置换-选择排序 | 最佳归并树
文章目录 第八章 排序 一.排序的基本概念 (一)什么是排序 (二)排序的应用 (三)排序算法的评价指标 (四)排序算法的分类 (五)总结 二.插入排序 (一)算法思想 (二)算法实现 (三)算法效率 ...
- java jdk实现快速排序_Java实现快速排序过程分析
快速排序过程 没有既不浪费空间又可以快一点的排序算法呢?那就是"快速排序"!光听这个名字是不是就觉得很高端呢. 假设我们现在对"52 39 67 95 70 8 25 5 ...
- Go 编码建议——性能篇
文章目录 常用数据结构 1.反射虽好,切莫贪杯 1.1 优先使用 strconv 而不是 fmt 1.2 少量的重复不比反射差 1.3 慎用 binary.Read 和 binary.Write 2. ...
- C语言——十四种内部排序算法【直接插入排序-冒泡排序-选择排序-插入排序-希尔排序-归并排序-快速排序-堆排序-折半插入排序-二分查找-路插入排序-表插入排序-简单选择排序-直接选择排序-树形选择】
目录: 一:插入排序 A:直接插入排序 1.定义: 2.算法演示 实例1: 3.基本思想 4.排序流程图 实例1: B:希尔排序 1.定义: 2.算法演示 实例2: C:其他插入排序 a:折半插入排序 ...
- c语言的qsort快速排序函数
目录 qsort的介绍 测试 排序int类型 排序char类型 排序结构体类型 qsort的介绍 c语言中有很多排序,比如常见的选择排序,冒泡排序,插入排序,但是c语言的库函数中,有一个qsort() ...
- 《数据结构与算法》(二十五)- 排序算法:快速排序
目录 前言 1. 快速排序 1.1 快速排序算法 1.2 快速排序算法复杂度分析 1.3 快速排序优化 2. 总结 原文地址:https://program-park.github.io/2021/1 ...
- 快速排序算法(基于Java实现)
title: 快速排序算法(基于Java实现) tags: 快速排序算法 快速排序算法的原理与代码实现: 一.快速排序算法的原理 快排算法的思想是: 如果需要排序数组中下标从p到r之间的一组数据,我们 ...
- Android性能优化之运算篇
原文转自 Techfox IT技术论坛 运算篇 1) Intro to Compute and Memory Problems Android中的Java代码会需要经过编译优化再执行的过程.代码的不同 ...
- UWA官方Demo新增《小米超神》,全面揭秘重度手游的性能表现!
还记得UWA[博观约取]专栏推荐的<小米超神>吗?作为一款重度的MOBA手游,它在不同配置的移动设备上,无论是画面表现力,还是性能开销都非常优秀.我们曾公布过该游戏的主要性能数据,当然其出 ...
最新文章
- 利用PHP-ExcelReader实现PHP导入Excel数据[不通过CSV]
- 理解Android Binder机制(1/3):驱动篇
- 100亿人口会挨饿吗?人工智能迎击全球粮食问题
- LeetCode 885. 螺旋矩阵 III
- 程序员为什么想进大厂,看看年终奖你们就知道了
- 被卡性能的时候要care数据类型(洛谷P5594TLE+RE的经历,Java语言描述)
- ElementUI table组件,表格组件,单击单元格可编辑逻辑
- tensorflow: 图像处理模块 tf.image
- 国产计算机设备,国产计算机报价
- ES查询结果全局高亮
- 电脑开机没反应如何解决?
- 搭建自己的存储服务器NAS
- 【仿真建模】第四课:AnyLogic入门基础课程 - 轨道交通仿真入门讲解
- 网鼎杯半决赛 pwn1
- 如何在 MacOS Monterey 菜单栏上显示电池百分比
- Vcc、Vee、Vdd、Vss傻傻分不清楚?
- C语言程序设计Bjarne特别版,C语言程序设计(2013深色背景).ppt
- MTK原厂,MT6771参考设计最新资料
- fdsfdsfdsfsd
- hibernate的快照更新