这是第一篇公众号文章,所以内容打算写的浅简一点。

这篇文章将主要介绍两种非常普遍的排序方式:冒泡排序和快速排序。内容包括两种排序的原理,代码剖析,以及时间复杂度分析。

因为注意到很多快排的文章在介绍完原理之后并没有去解释这么做的原因,以及没有从宏观上去看代码所实现的功能,也就是没有很详细的说明这么写代码的原因,看完之后会产生一些疑问,所以我打算以个人的浅见去解释以上的问题。由于本人是一个普通人,水平有限,所以有任何质疑或者想法,欢迎留言。

那下面我们也以扑克牌来引入这个排序问题吧~

假设有一堆乱序的扑克牌,如果是你,你打算如何将这些乱序的扑克牌变成正序呢?

冒泡排序的思路:

从第二个扑克开始和它前面相邻的扑克比较,比它大则不动,比它小交换位置。这样我们在第一轮排序中可以得到最大的扑克牌,因为最大值是一直在向后传递,直到传到最后,那个值必然是扑克牌中最大的值。

(柱形图比扑克更直观点,第一次自己做的gif水平有限)

可以看到,最后一个值是最大的值。通过不断的循环这一操作,我们总是可以把第二大,第三大...第n大的值放到正确的位置,直到所有的排序全部正确。

冒泡排序示例代码1:

public class BubbleSortTest1 {  public static void main(String[] args) {    int[] arr = new int[]{-12,3,2,3,5,8,1};    //冒泡排序    //i循环:进行i次排序动作    for(int i = 0;i < arr.length-1;i++){      //内部j循环:进行内部排序,每次将目前最大值放置正确位置      for(int j = 0;j -1-i;j++){        if(arr[j] >arr[j+1]){          int temp = arr[j];          arr[j] = arr[j+1];          arr[j+1] = temp;        }      }    }    //遍历    for (int i = 0; i < arr.length; i++) {      System.out.println(arr[i]+"\t");    }  }}

冒泡排序复杂度:

    上面的代码我们可以看到嵌套循环了两次,最好的情况是整个数组是有序的,不用排序,那么它的最优复杂度=n-1+n-2+.....+(n-(n-1))=n^2-(1+n-1)(n-1)/2=n*(n-1)/2也就是n^2,但是肯定有同学有疑问,为什么有的资料说他的最优时间复杂度为O(n)? 其实示例1的代码有可以优化的地方,聪明或者傻乎乎的你发现了吗?当内部循环排序没有做置换操作的时候,其实就说明,整个序列是有序的,无需再继续循环下去,这个时候可以直接退出程序得到结果。我们可以通过一个标志位来标识是否进行了置换操作。

改进的冒泡排序示例代码2:

public class BubbleSortTest2{    public static void main(String[] args) {    int[] arr = new int[]{1,2,3,4,5,6};    //用于判断是否发生置换操作    boolean flag;    //i循环:进行i次排序动作    for(int i = 0;i < arr.length-1;i++){      flag = false;      //内部j循环:进行内部排序,每次将目前最大值放置正确位置        for(int j = 0;j -1-i;j++){            if(arr[j] >arr[j+1]){            int temp = arr[j];            arr[j] = arr[j+1];            arr[j+1] = temp;          flag = true;   //有发生置换,就置为true            }          }      if(!flag) break;    }    //遍历    for (int i = 0; i < arr.length; i++) {        System.out.println(arr[i]+"\t");      }    }}

‍这个时候最优时间复杂度为O(n),最差时间复杂度除了上述的n*(n-1)/2比较次数外,还需要计算置换次数,每次置换次数=3,所以总的最差时间复杂度=3*n(n-1)/2,为O(n^2),所以平均复杂度=[1+2+......n*(n-1)/2]/(n*(n-1)/2)=O(n^2)

冒泡排序效率略低,我们来看一看面试问的很多,应用用的很广,人如其名的快速排序。

快速排序的思路:

随机选择一个基准,比如第一个数,将其他数和这个数做比较,比他小则放在基准左边,比他大则放到基准右边。然后对基准左边的数和基准右边的数重复上面的动作。这么说,有些抽象,我们还是来看一下动态图。Talk is cheap,我们把上述思路转成代码。

快速排序代码示例代码:

import java.util.Arrays;public class QuickSort {    public static void quicksort(int[] arr, int low, int high){         //key为基准         int i,j,key;         //低位指针         i= low;         //高位指针         j =high;         //递归迭代时,判断是否还要进行排序。         if(i             key=arr[i];             //排序终止条件             while(i                 //说明高位数字位置正确                 while(arr[j]>=key && j>i)j--;       //如果跳出循环,则说明比key小的数值处在高位,需要置换到低位,此时低位正好是key的值,相当于是个空位                 arr[i]=arr[j];                 //低位数字位置正确                 while(arr[i]<=key && i       //如果跳出循环,则说明比key大的数值处在低位,需要置换到高位                 arr[j]=arr[i];      //然后再从高位指针开始新的循环比较,直到两个指针相遇则一轮比较结束             }             //此时key处于正确位置             arr[i]=key;             quicksort(arr,low,i-1);             quicksort(arr,i+1,high);         }}    public static void main(String[] args) {        int[] arr={6, 1, 2, 7, 9, 3, 4, 5, 10, 8};        quicksort(arr,0,arr.length-1);        System.out.println(Arrays.toString(arr));    }}

快速排序复杂度:

快排需要注意指针越界还有递归能终止的问题。快速排序最好情况是每次都恰好可以对半分,一次递归共需比较n次,递归深度为lgn,复杂度为nlgn(2为底),最差情况为已排序数组,每次的排序次数=n+n-1+n-2+.....1=n(n+1)/2~1/2n^2,平均复杂度最终结果=O(nlgn),这个证明有点复杂,这里不做赘述(主要是因为水平有限)。

Bye.

冒泡和快速排序的时间复杂度_凡人能看懂的冒泡排序和快速排序相关推荐

  1. 冒泡排序代码_凡人能看懂的冒泡排序和快速排序(附动态图和代码详解))

    这是第一篇公众号文章,所以内容打算写的浅简一点. 这篇文章将主要介绍两种非常普遍的排序方式:冒泡排序和快速排序.内容包括两种排序的原理,代码剖析,以及时间复杂度分析. 因为注意到很多快排的文章在介绍完 ...

  2. 冒泡和快速排序的时间复杂度_十大经典排序算法——快速排序

    目录 1.1.排序分类 1.2.排序的定义: 对一序列对象根据某个关键字进行排序. 1.3.术语说明 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面. 不稳定:如果a原本在b的前面,而a ...

  3. angular 字符串转换成数字_一文看懂Python列表、元组和字符串操作

    好文推荐,转自CSDN,原作星辰StarDust,感觉写的比自己清晰-大江狗荐语. 序列 序列是具有索引和切片能力的集合. 列表.元组和字符串具有通过索引访问某个具体的值,或通过切片返回一段切片的能力 ...

  4. 冒泡和快速排序的时间复杂度_八大排序算法性能分析及总结

    一.排序算法说明 排序的定义:对一个无序的序列进行排序的过程. 输入:n个数:a1,a2,a3,-,an. 输出:n个数的排列:a1,a2,a3,-,an,使得a1<=a2<=a3< ...

  5. 冒泡和快速排序的时间复杂度_「排序」冒泡排序、快速排序—图解+手撕

    前言 无论是日后面试还是笔试的,排序在数据结构与算法中有着举足轻重的地位,所以还是决定把数据结构这个专题好好写写,多研究研究!今天和大家一起学习交换类排序--冒泡和快排详解! 在排序中,冒泡和快排是考 ...

  6. 冒泡和快速排序的时间复杂度_排序算法学习分享(二)交换排序---冒泡排序与快速排序...

    排序,也称为排序算法,可以说是我们学习算法的过程中遇到的第一个门槛,也是实际应用中使用得较为频繁的算法,我将自己对所学的排序算法进行一个归纳总结与分享,如有错误,欢迎指正! 排序算法学习分享(一)选择 ...

  7. 冒泡和快速排序的时间复杂度_常用排序算法之冒泡排序

    周末无事,带娃之余看到娃娃在算数,想到了排序-尝试着把几种常用的排序算法跟大家聊一聊,在分析的后面我会用GoLang.PHP和JS三种语言来实现下. 常见的基于选择的排序算法有冒泡排序.插入排序.选择 ...

  8. 冒泡和快速排序的时间复杂度_各种排序算法总结

    各种排序算法的稳定性,时间复杂度和空间复杂度总结: 我们比较时间复杂度函数的情况: 时间复杂度函数O(n)的增长情况: 所以对于n较大的排序记,一般的选择都是时间复杂度为O(nlog2n)的排序方法. ...

  9. 冒泡和快速排序的时间复杂度_三分钟快速记住冒泡排序算法

    冒泡排序名字由来: 是因为越小的元素会经由交换慢慢"浮"到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名"冒泡排序". ...

最新文章

  1. 麦肯锡发布调研,揭开“那些引入人工智能的企业都怎么了 ”
  2. 第六讲:软考中高项06_质量管理、人力资源管理
  3. 深入了解jquery中的键盘事件
  4. 九州云陈沙克:OpenStack的成功源于自身的开放
  5. 线程池中阻塞队列的作用?为什么是先添加列队而不是先创建最大线程?线程池中线程复用原理
  6. vue与php接口对接,怎样使用vue项目中api接口
  7. delphi 停电文本数据丢失_概述DCS系统正确停电和上电的步骤
  8. Spring框架入门:(非原著,转载)
  9. html5快捷键自动对齐,【答疑】pr自动对齐的快捷键是什么 - 视频教程线上学
  10. 如何添加Cydia源?如何通过Cydia下载软件?如何卸载软件?
  11. img.shape[0]、[1]、[2]到底代表什么(转)
  12. 设置view 的MarginTop
  13. DSP TMS320C5509A 控制DDS AD9854芯片进行FSK调制
  14. 班级校园网页设计作业 静态HTML我的班级网页 DW班级网站模板 大学生简单班级网页作品代码 我的大学网页制作 学生班级网页设计作业
  15. P3545 [POI2012]HUR-Warehouse Store
  16. mediacodec mp4v2应用
  17. c#怎么连接MySQL
  18. 华三防火墙添加web用户_H3C F1000-C-G防火墙开web功能
  19. android 实现自动拍照,Android:调用系统相机实现拍照+裁切(兼容7.0以上系统)
  20. 通信算法之九十八:4G LTE通信系统 PCFICH信道处理流程

热门文章

  1. tomcat服务器启动失败的解决方法
  2. 超话显示服务器有点累,周杰伦新歌1小时900万,服务器崩溃!但这12个彩蛋你绝对没注意...
  3. 如何解决web端图片加载慢卡顿的问题???
  4. 贵州丹寨民众赶制特色“鸟笼”灯笼迎新春
  5. java多线程的创建和启动
  6. [Spark基础]-- spark并行度和partion联系
  7. 阿里资深架构师整理2022年秋招最新面试题汇总:208页核心体系
  8. 我是一个教师,是一个会长,是一个RL也是一个普通的WOWER
  9. 丢猫千万别找设计师
  10. 【玩转嵌入式屏幕显示】(一)显示器概述(常见显示器及其显示原理)