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

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

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

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

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

冒泡排序的思路:

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

(柱形图比扑克更直观点,第一次自己做的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)

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

快速排序的思路:

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

上面的动态图展示了一轮快排,初始顺序为array={2,5,3,1,4}:

step 1:选择第一个数2作为基准key,定义低位指针low,和高位指针high,此时low位于0,high位于4;

step 2:从高位开始和基准比较,首先是4,4>2,符合高位定义,4保持不动;

step 3:high指针-1=3,array[3]=1<2,此时1需换到低位,和array[0]置换位置,此时的数组为{1,5,3,1,4};

step 4:low指针+1=1,array[1]=5>2,此时5需换到高位,和array[3]置换位置,此时数组为{1,5,3,5,4};

step 5:high指针-1=2,array[2]=3>2,3保持不变,此时数组为{1,5,3,5,4};

step 6:high指针-1=1,此时high指针==low指针,结束第一轮内循环比较,将key=2放置array[1]的位置,此时数组为{1,2,3,5,4}。

然后会对2之前的数{1}以及2之后的数{3,5,4}递归,继续按照上述规则排序直到所有的子数组都排序完成。

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. 深度:一文看懂Linux内核,Linux内核架构和工作原理详解

    简介 作用是将应用层序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址.目前支持模块的动态装卸(裁剪).Linux内核就是基于这个策略实现的.Linux进程1.采用层次结构,每个 ...

  3. 一文看懂Linux内核!Linux内核架构和工作原理详解

    linux内核相关视频解析: 5个方面分析linux内核架构,让你对内核不再陌生 90分钟了解Linux内存架构,numa的优势,slab的实现,vmalloc的原理 手把手带你实现一个Linux内核 ...

  4. 深度:一文看懂Linux内核!Linux内核架构和工作原理详解

    简介 作用是将应用层序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址.目前支持模块的动态装卸(裁剪).Linux内核就是基于这个策略实现的.Linux进程1.采用层次结构,每个 ...

  5. 一文看懂:史上最通俗的视频编码技术详解

    1.引言 如今我们所处的时代,是移动互联网时代,也可以说是视频时代.从快播到抖音,从"三生三世"到"延禧攻略",我们的生活,被越来越多的视频元素所影响. 而这一 ...

  6. 牛顿法python代码_一文看懂牛顿法(附Python实现)

    这是一个数据分析师的在线笔试编程题:不能使用数学库函数,求出一个数的算术平方根 是不是看的一脸懵逼? 这里就需要用到一个很常用的求解方法了 -- 牛顿迭代法,也被称作牛顿法 (Newton's Met ...

  7. mysql某个表被行锁了_一文搞懂MySQL行锁、表锁、间隙锁详解

    准备工作 创建表 tb_innodb_lock drop table if exists test_innodb_lock; CREATE TABLE test_innodb_lock ( a INT ...

  8. 10个常用的代码简写技术,看懂一种是入门,全部看懂是大神!

    前言: 人工智能时代,python编程语言站在风口起飞,2018年7月的世界编程语言排行榜跃居于编程语言前三,2018年的IEEE顶级编程语言交互排行榜中Python屠榜,彻底火了python,也相继 ...

  9. 写html前端代码的软件_你能看懂高贵的前端程序员的工作内容?

    高贵的前端程序猿们: 如何在前端开发这种高精尖的技术领域找到心仪的工作?实现在咖啡馆喝喝咖啡敲敲代码就能升职加薪.买房买车.迎娶白富美走上人生巅峰的职业梦想?这篇<进化论:从0到100,前端猿茁 ...

最新文章

  1. 微信公众平台开发(十一) 功能整合
  2. 设置datagridview的数据源为(DATASET)SQL查寻结果
  3. AndroidAnnotations框架简单使用方法
  4. Oracle同义词创建及其作用(转载)
  5. angular 应为声明或语句_“允许”员工自愿降薪后,多益网络再发声:声明降薪非自愿者奖 3 万...
  6. 通过日志恢复MSSQL数据案例
  7. vue中数组长度_如何在Vue.js中获取计算数组的长度
  8. 布局中文件中【控件间距参数详解以及单位选择】
  9. Swift -- 7.5 类型属性,方法
  10. 使用extract-text-webpack-plugin提取css文件
  11. Python入门之面向对象module,library,package之间区别
  12. 计算机操作系统第一章测试题及答案
  13. MKVToolNix v7.4.0 正式版
  14. hysys动态模拟教程_(转载)HYSYS-过程模拟软件-稳态模拟-第一部分(一)
  15. win10计算机记录,Win10新版计算器用法介绍
  16. 【Willy Susilo 学术报告】Public-Key Encryption with Multi-Ciphertext Equality Test in Cloud Computing
  17. mac os监听扬声器、麦克风的音量、静音
  18. zblog php getlist,zblog使用getlist方法调用置顶文章
  19. signature=f2fd61184b3328e471644f6fd3617f29,IPSEC-×××-CA
  20. GeoJson数据合并

热门文章

  1. Windows 7系统mac地址修改攻略
  2. koa2+koa-views示例
  3. Memcached 及 Redis 架构分析和比较
  4. Asp.Net Web API 2第十七课——Creating an OData Endpoint in ASP.NET Web API 2(OData终结点)...
  5. View-client自动登录
  6. 图解使用Win8Api进行Metro风格的程序开发十二----上下文菜单
  7. Windows Server 2008 多元密码策略配置
  8. 细说Activity与Task(任务栈)
  9. 课堂练习之购书最低价格
  10. hdu 2069 1 5 10 25 50 这几种硬币 一共100个(母函数)