冒泡和快速排序的时间复杂度_「排序」冒泡排序、快速排序—图解+手撕
前言
无论是日后面试还是笔试的,排序在数据结构与算法中有着举足轻重的地位,所以还是决定把数据结构这个专题好好写写,多研究研究!今天和大家一起学习交换类排序——冒泡和快排详解!
在排序中,冒泡和快排是考察最多的了,当然在实行上面冒泡要相比快排简单很多。理解起来也算得上是最简单的排序算法,而快排的话很多面试笔试都是要求手撕的,所以重要性不言而喻!当然,对于排序算法我当初首次接触学习的时候只是萌萌懂懂的,只是大概了解,死记了模板,能将快排手写出来,刷题用。后来我发现我太傻吊了,,java中明明有Arrays.sort()这个api可以直接调用我为啥要憨呼呼的手写?多个条件排序重写下comparator接口就OK为啥还要憨呼呼的手写?。。。自此,就踏上了不手写快排的不归路。。。
后来,渐渐的,这个排序思想用的少,被我成功的遗忘。。现如今,被我重新拾起,深入理解下,防止哪一天又那个大佬让我手撕下不会就尴尬了哈哈,把学习过程分享给大家!
冒泡排序
介绍
冒泡排序,又称起泡排序。他是一种基于交换的排序典型,也是快排思想的基础。对于冒泡排序名字的由来,百度百科这么说:
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。
当然,冒泡排序是一种稳定排序算法,时间复杂度位O(n^2^).基本思想是:从前往后把大元素往后调(或者从后向前把小元素往前调)。
分析
具体思想为(把大元素往后调):
- 从第一个元素开始往后跑,每到一个位置判断是否比后面的元素大,如果比后面元素大,那么就交换两者大小,然后继续向后,否则就直接向后前进,这样的话进行一轮之后就可以保证最大的那个数一直被交换交换到最末的位置可以确定。
- 那么第二次同样从开始起向后判断着前进,如果当前位置比后面一个位置更大的那么就和他后面的那个数交换。但是有点注意的是,这次并不需要判断到最后,只需要判断到倒数第二个位置就行(因为第一次我们已经确定最大的在倒数第一,这次的目的是确定倒数第二)
- 同理,后面的操作也是如此,直到第一个元素使得整个元素有序。
拿个例子来说,比如2,8,9,3,7,6,12,4这个序列的冒泡排序来说。会有多趟(7)排序,每一趟要执行多(8-k)次。
对于它的第一趟排序来说是这样的:
而多次排序每次的结果是这样的:
它的动态执行顺序为:
代码
在具体实现的时候,要分清是从小到大还是从大到小,还有次数也要注意,谨防越界!
至于冒泡排序的关键代码为:
private static void maopaosort(int[] a) { // TODO Auto-generated method stub for(int i=a.length-1;i>=0;i--) { for(int j=0;ja[j+1]) { int team=a[j]; a[j]=a[j+1]; a[j+1]=team; } } } }
快速排序
介绍
快速排序是对冒泡排序的一种改进,采用递归分治的方法进行求解。而快排相比冒泡是一种不稳定排序,时间复杂度最坏是O(n^2^),平均时间复杂度为O(nlogn),最好情况的时间复杂度为O(nlogn)。
分析
对于快排来说,基本思想是这样的
快排需要将序列变成两个部分,就是序列左边全部小于一个数,序列右面全部大于一个数,然后利用递归的思想再将左序列当成一个完整的序列再进行排序,同样把序列的右侧也当成一个完整的序列进行排序。
其中这个数在这个序列中是可以随机取的,可以取最左边,可以取最右边,当然也可以取随机数。但是通常我们取最左边的那个数。当然,为了实现这个目标,实现方式可能不一样,但是我这里采取的是大众常规的方式和方法。!
这里的一个难题就是如何处理将比第一个数K小的全部放左面,把比K大的全部放右面!如果没有什么技巧,直接硬性往里面塞,你肯定要一个额外存储空间先把整个先存了。然后遍历比较然后放入目标区域。当然这样太浪费空间内存了。我们为了节省计算机资源,采取这样的方法:
- 先用一个空间标记这个最左侧的数K。然后先从右往左high--先找到一个比这个K小的数a[high],把这个a[high]放到a[low]位置(因为这个a[low]的初始K已经被额外空间记录过,不用担心)。
- 这样右侧不符合要求小于K的已经调到最左侧了,我们再从左侧向右low++一直到a[low]>K.也就是找到第一个比K大的数,它在左侧不符合要求所以我们把它移动到右侧,而我们刚刚所说的a[high]已经被赋值移到左侧,所以我们把这个a[low]大于K的数值移动到右端a[high]处,这样又保证high右侧全部大于K,low左侧全部小于K。
- 就又开始重复第一步啦一直到low>high为止(即所有左侧都小于K,右侧都大于K)。
对于一个序列的2,8,3,7,6,9,4,12来说,它的执行过程图解大致是这样的:
1 . 首先2是最小的,采用递归分治时候左侧相当于为空,只需要把右侧再进行排序。
2 .对于右侧序列来说,先用K储存a[low]=8我们先从右侧找到第一个小与8的数字4。
3 .我们将它放到low位置替换,然后从low位置向右找到第一个大于k=8的再同样放到右侧。我们找到9,把9赋值给high位置。
4 .重复上面步骤直到high
5 .就这样重复下去,直到整个序列有序即可!
代码
在书写代码的时候,要注意一些顺序,防止数组越界情况,可以写好debug一遍其实就很好理解了!当写代码遇到错误时候,不要急着就去找正确答案,能有时间自己发现错误,可以借助断点查看程序执行流程,这样对自己的收益是最大的!
至于快排的代码,是这样的:
private static void quicksort(int [] a,int left,int right) { int low=left; int high=right; //下面两句的顺序一定不能混,否则会产生数组越界!!!very important!!! if(low>high)//作为判断是否截止条件 return; int k=a[low];//额外空间k,取最左侧的一个作为衡量,最后要求左侧都比它小,右侧都比它大。 while(low=k)//右侧找到第一个小于k的停止 { high--; } //这样就找到第一个比它小的了 a[low]=a[high];//放到low位置 while(low
测试与总结
对于完整的代码,为
package 八大排序;import java.util.Arrays;public class 交换类排序 { public static void main(String[] args) { int a[]= {2,8,9,3,7,6,12,4}; maopaosort(a); System.out.println(Arrays.toString(a)); int b[]= {2,8,9,3,7,6,12,4}; quicksort(b, 0, b.length-1); System.out.println(Arrays.toString(b)); } private static void maopaosort(int[] a) { // TODO Auto-generated method stub for(int i=a.length-1;i>=0;i--) { for(int j=0;ja[j+1]) { int team=a[j]; a[j]=a[j+1]; a[j+1]=team; } } } } private static void quicksort(int [] a,int left,int right) { int low=left; int high=right; //下面两句的顺序一定不能混,否则会产生数组越界!!!very important!!! if(low>high) return; int k=a[low];//取最左侧的一个作为衡量,最后要求左侧都比它小,右侧都比它大。 while(low=k) { high--; } //这样就找到第一个比它小的了 a[low]=a[high]; while(low
运行结果:
好了这个交换类排序就总结到这里了。总之,冒泡是很基础和容易,但是要注意这种简单排序所属的范畴(交换类)要和插入类等做好区分;而快排板子很好记,深入理解需要点时间消化吧。一次不行再来第二次,不行再来第三次,。。。
当然,如果感觉不错或者对你有所帮助,欢迎点赞收藏转发哈!如果感觉有问题或者纰漏还请指正哈!当然,笔者长期致力于<>这个专栏的更新和维护,欢迎大家关注一波哈!
最后,欢迎关注笔者微信公众号(bigsai),头条号(一直码农一直爽)!
冒泡和快速排序的时间复杂度_「排序」冒泡排序、快速排序—图解+手撕相关推荐
- 冒泡和快速排序的时间复杂度_java 八大排序算法 冒泡排序 快速排序 堆排序 归并排序 等...
八大排序算法 一.直接插入 1.基本思路 在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的.如此反复循环 ...
- 冒泡和快速排序的时间复杂度_八大排序算法性能分析及总结
一.排序算法说明 排序的定义:对一个无序的序列进行排序的过程. 输入:n个数:a1,a2,a3,-,an. 输出:n个数的排列:a1,a2,a3,-,an,使得a1<=a2<=a3< ...
- 冒泡和快速排序的时间复杂度_各种排序算法总结
各种排序算法的稳定性,时间复杂度和空间复杂度总结: 我们比较时间复杂度函数的情况: 时间复杂度函数O(n)的增长情况: 所以对于n较大的排序记,一般的选择都是时间复杂度为O(nlog2n)的排序方法. ...
- 冒泡和快速排序的时间复杂度_常用排序算法之冒泡排序
周末无事,带娃之余看到娃娃在算数,想到了排序-尝试着把几种常用的排序算法跟大家聊一聊,在分析的后面我会用GoLang.PHP和JS三种语言来实现下. 常见的基于选择的排序算法有冒泡排序.插入排序.选择 ...
- 学美术还是计算机好,「热门」学画画是手绘还是电脑绘画好?
原标题:「热门」学画画是手绘还是电脑绘画好? 学画画是手绘还是电脑绘画好?这个问题得凑个热闹,板绘和手绘的不足,体验最深刻的就是改改改!改作品就变成一件非常苦逼的事情!!! 手绘除了重画几乎无法拯救, ...
- 冒泡和快速排序的时间复杂度_排序算法学习分享(二)交换排序---冒泡排序与快速排序...
排序,也称为排序算法,可以说是我们学习算法的过程中遇到的第一个门槛,也是实际应用中使用得较为频繁的算法,我将自己对所学的排序算法进行一个归纳总结与分享,如有错误,欢迎指正! 排序算法学习分享(一)选择 ...
- 冒泡和快速排序的时间复杂度_十大经典排序算法——快速排序
目录 1.1.排序分类 1.2.排序的定义: 对一序列对象根据某个关键字进行排序. 1.3.术语说明 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面. 不稳定:如果a原本在b的前面,而a ...
- 【八大排序详解~C语言版】直接插入排序-希尔排序- 直接选择排序-堆排序-冒泡排序-快速排序-归并排序-计数排序
八大排序 1.直接插入排序 2.希尔排序 3.直接选择排序 直接选择排序改进 4.堆排序 1.建堆 2.利用堆删除思想来进行排序 5.冒泡排序 6.快速排序 递归实现 非递归实现 7.归并排序 递归实 ...
- 七大排序算法—图文详解(插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序)
作者:渴望力量的土狗 博客主页:渴望力量的土狗的博客主页 专栏:数据结构与算法 工欲善其事必先利其器,给大家介绍一款超牛的斩获大厂offer利器--牛客网 点击免费注册和我一起刷题吧 目录 插入排序: ...
最新文章
- C语言结束输入(两种方法)
- mxnet symbol图的 变量 shape
- Beyond Compare 3 许可证密钥被撤销
- 树莓派dht11上云_树莓派使用 DHT11 / DHT22 温湿度传感器
- 2019贵州大学计算机研究生,贵州大学2019年硕士研究生招生拟录取名单公示(一)...
- ExtJS和AngularJS比较
- ADO.NET_07_OracleDataAdapter
- qt——QFileDialog使用对话框选取本地文件
- 山东科技职业学院单招计算机,山东科技职业学院单招
- 浏览器了解(五)资源加载顺序
- java学习 hibernate 持久态和瞬时态
- 阿里巴巴矢量图标库的引入——symbol类型的使用——阿里图标组件封装
- STM32CubeMx开发之路—13使用SPI读写W25Q64
- PTA离散数学集合论自测(无答案版)
- 高斯(Gaussian)拟合的实现
- 英特尔服务器主板g41性能,英特尔g41显卡好用吗 英特尔g41显卡评测【详解】
- 秦九韶算法以及大数取余应用
- 计算机系的学生的未来计划,学生未来计划.doc
- yii mysql 查询 类型转换_yii2 数据库查询结果字段类型的问题
- 【笔记】基于TF-IDF 算法的文本相似度以衡量技术革新