宁肯像种子一样等待 也不愿像疲惫的陀螺 旋转得那样勉强

 

可以看出在这趟冒泡中,最大的泡泡6已经到达最高的位置,要让集合中所有元素都有序,还要继续冒泡,如下图:

代码

 package com.jackie.algo.geek.time.chapter11_sort;  /**  * @Author: Jackie  * @date 2019/1/12  */ public class BubbleSort {     public static void main(String[] args) {         int[] arr = new int[]{100,82,74,62,54,147};         bubbleSort(arr);         bubbleSort2(arr);     }     /**      * 外层i的循环代表比较的趟数,内层j的循环代表的元素位置      *  a[0],a[1],a[2],a[3],a[4],a[5]      *  第一趟走完,最大的元素冒泡到最后a[5]的位置,需要比较的位置即为:      *  a[0],a[1],a[2],a[3],a[4]      *  所以可以看到j的终止条件是动态变化的,与i的位置相关,趟数每增加一次,终止的位置就往前挪一个,因为每次都能固定一个元素      *      *  注意这里的边界条件,是<还是<=      *  第一层是小于,因为是从0开始,对于上面的例子来说,是比较length-1=6-1=5趟,因为总共6个元素,只要5趟就能比较完成      *  好比有两个元素,只要一趟就能比较完成      *  第二层是同样的道理,假设在i=0时,length-i-1=6-0-1=5,      *  但是这里<,所以只会到j=4,乍一看你会觉得之比较到了a[j]=a[4],最后a[5]是不是就丢了      *  其实不是,仔细看下面的比较条件就会发现有a[j+1]即a[5]      *  所以,综上内层和外层都是从0开始,且都是<而不是<=      */     public static void bubbleSort(int[] arr) {         int length = arr.length;         if (length <= 0) {             return;         }         int temp;         for (int i = 0; i < length - 1; i++) {             boolean flag = false;             for (int j = 0; j < length - i - 1; j++) {                 if (arr[j] > arr[j+1]) {                     temp = arr[j];                     arr[j] = arr[j+1];                     arr[j+1] = temp;                      flag = true;                 }             }             if (!flag) {                 System.out.println("total loop: " + (i+1) + " times, stop at index:" + i);                 break;             }         }         for (int i = 0; i < length; i++) {             System.out.print(arr[i] + " ");         }         System.out.println();     }     /**      * 和上面的不同之处在于,上面的是保证数组从后往前有序,这里的是保证从前往后的有序      * 上面的做法如下所示,每次要遍历的元素如下      * a[0],a[1],a[2],a[3],a[4],a[5]      * a[0],a[1],a[2],a[3],a[4]     (这里不再遍历a[5]的位置,因为a[5]在第一轮遍历已是最大,不需要参与遍历,下面遍历同理)      * a[0],a[1],a[2],a[3]      * a[0],a[1],a[2]      * a[0],a[1]      * a[0]      *      * 下面的做法如下所示,每次要遍历的元素如下      * a[0],a[1],a[2],a[3],a[4],a[5]      *      a[1],a[2],a[3],a[4],a[5]   (这里不再遍历a[0]的位置,因为a[0]在第一轮遍历已是最小,不需要参与遍历,下面遍历同理)      *           a[2],a[3],a[4],a[5]      *                a[3],a[4],a[5]      *                     a[4],a[5]      *                          a[5]      */     public static void bubbleSort2(int[] arr) {         int length = arr.length;         if (length <= 0) {             return;         }         int temp;         for (int i = 0; i < length - 1; i++) {             boolean flag = false;             for (int j = length - 1; j > i; j--) {                 if (arr[j] < arr[j-1]) {                     temp = arr[j];                     arr[j] = arr[j-1];                     arr[j-1] = temp;                      flag = true;                 }             }             if (!flag) {                 System.out.println("total loop: " + (length - i - 1) + " times, stop at index:" + i);                 break;             }         }         for (int i = 0; i < length; i++) {             System.out.print(arr[i] + " ");         }         System.out.println();     } }

写这类算法对于边界判定、起始条件和结束条件要非常谨慎,比如是用<还是用<=;是从0开始还是从1开始;是到length结束还是到length-1结束。

看似惺忪平常,有时候弄错一个符号就无法得到正确的排序结果。

冒泡排序的这些注意事项已经写在代码的注释中,参见如上代码。

同时,代码已经上传至Github

各项指标

1、是否是原地排序

是,因为冒泡排序只涉及两两元素交换,空间复杂度为O(1)

2、是否是稳定排序

是,对于元素相等的情况,不会交换顺序

3、时间复杂度

平均时间复杂度是O(n2), 这里是n的平方

插入排序

原理

对于给定集合,从左至右,依次保证当前元素的左边集合有序。然后依次顺延当前位置,直至遍历完所有集合元素,保证整个集合有序。

有点抽象,没有关系,看举例。

举例

借用文章https://www.cnblogs.com/bjh1117/p/8335628.html中的例子说明插入排序的过程。

 待比较数据:7, 6, 9, 8, 5,1      第一轮:指针指向第二个元素6,假设6左面的元素为有序的,将6抽离出来,形成7,_,9,8,5,1,从7开始,6和7比较,发现7>6。将7右移,形成_,7,9,8,5,1,6插入到7前面的空位,结果:6,7,9,8,5,1      第二轮:指针指向第三个元素9,此时其左面的元素6,7为有序的,将9抽离出来,形成6,7,_,8,5,1,从7开始,依次与9比较,发现9左侧的元素都比9小,于是无需移动,把9放到空位中,结果仍为:6,7,9,8,5,1      第三轮:指针指向第四个元素8,此时其左面的元素6,7,9为有序的,将8抽离出来,形成6,7,9,_,5,1,从9开始,依次与8比较,发现8<9,将9向后移,形成6,7,_,9,5,1,8插入到空位中,结果为:6,7,8,9,5,1      第四轮:指针指向第五个元素5,此时其左面的元素6,7,8,9为有序的,将5抽离出来,形成6,7,8,9,_,1,从9开始依次与5比较,发现5比其左侧所有元素都小,5左侧元素全部向右移动,形成_,6,7,8,9,1,将5放入空位,结果5,6,7,8,9,1。      第五轮:同上,1被移到最左面,最后结果:1,5,6,7,8,9。 

代码


                        
关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信