一.冒泡排序介紹

冒泡排序是我們得最多的排序方式之一,原因是簡(jiǎn)單易實(shí)現(xiàn),且原理易懂。顧名思義,冒泡排序,它的排序過(guò)程就像水中的氣泡一樣,一個(gè)一個(gè)上浮到水面。

二.冒泡排序原理分析

三.冒泡排序代碼實(shí)現(xiàn)

/**
 * @Author {LearnAndGet}
 * @Time 2019年1月8日
 * @Discription:
 */
package com.sort;

import java.util.Arrays;

public class MaopaoSort {
    
    static int[] array = {3,2,4,1,5,0};
    
    public static void maopaoSort(int[] a) 
    {
        //外層循環(huán),是需要進(jìn)行比較的輪數(shù),一共進(jìn)行5次即可
        for(int i=0;i1;i++) 
        {
            //內(nèi)存循環(huán),是每一輪中進(jìn)行的兩兩比較
            for(int j=0;j1;j++) 
            {
                if(a[j] > a[j+1]) 
                {
                    int temp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = temp; 
                }
            }
            System.out.println("第"+(i+1)+"輪排序后的數(shù)組為: "+Arrays.toString(a));
        }
    }
    
    public static void main(String[] args) {
        maopaoSort(array);
    }
}

輸出結(jié)果

1輪排序后的數(shù)組為: [2, 3, 1, 4, 0, 5]2輪排序后的數(shù)組為: [2, 1, 3, 0, 4, 5]3輪排序后的數(shù)組為: [1, 2, 0, 3, 4, 5]4輪排序后的數(shù)組為: [1, 0, 2, 3, 4, 5]5輪排序后的數(shù)組為: [0, 1, 2, 3, 4, 5]

四.冒泡排序的優(yōu)化

1 .觀察上述代碼和運(yùn)行結(jié)果,我們可以發(fā)現(xiàn),當(dāng)?shù)谝惠喗Y(jié)束后,最后一個(gè)數(shù)字一定是數(shù)組中最大的元素,那么我們?cè)谶M(jìn)行第二趟的兩兩比較時(shí),實(shí)際上是沒(méi)有必要再對(duì)第5個(gè)和第6個(gè)進(jìn)行比較的。那么我們可以修改代碼如下:

public static void maopaoSort(int[] a) 
{
    //外層循環(huán),是需要進(jìn)行比較的輪數(shù),一共進(jìn)行5次即可
    for(int i=0;i1;i++) 
    {
        //內(nèi)存循環(huán),是每一輪中進(jìn)行的兩兩比較
        //并且每一輪結(jié)束后,下一次的兩兩比較中可以少比較一次
        for(int j=0;j1;j++) 
        {
            if(a[j] > a[j+1]) 
            {
                int temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp; 
            }
        }
        System.out.println("第"+(i+1)+"輪排序后的數(shù)組為: "+Arrays.toString(a));
    }
}

繼續(xù)運(yùn)行后,可以發(fā)現(xiàn)運(yùn)行結(jié)果是一樣的。

2 .當(dāng)我們用數(shù)組:{1,2,0,3,5,4}來(lái)測(cè)試上述冒泡排序時(shí),運(yùn)行結(jié)果如下:

1輪排序后的數(shù)組為: [1, 0, 2, 3, 4, 5]2輪排序后的數(shù)組為: [0, 1, 2, 3, 4, 5]3輪排序后的數(shù)組為: [0, 1, 2, 3, 4, 5]4輪排序后的數(shù)組為: [0, 1, 2, 3, 4, 5]5輪排序后的數(shù)組為: [0, 1, 2, 3, 4, 5]

可以看到,在第2輪排序完成后,其實(shí)我們就已經(jīng)的到了排好序的數(shù)組,但是我們的程序并不知道,仍然進(jìn)行了后續(xù)的無(wú)用工作。那么,我們?nèi)绾蝸?lái)讓程序知道已經(jīng)完成好排序了呢?

這里可以想到,當(dāng)某一輪的兩兩比較中,如果都沒(méi)有發(fā)生數(shù)組元素的互換,那么其實(shí)排序工作已經(jīng)完成了,所以我們可以考慮在程序中加入一個(gè)flag,默認(rèn)為false,含義是該輪比較中是否發(fā)生了元素互換,當(dāng)程序中執(zhí)行到元素互換時(shí),將該flag置為true,當(dāng)該輪比較結(jié)束時(shí),若flag為flase,則說(shuō)明該輪比較未發(fā)生元素互換,那么排序完成,若flag為true,說(shuō)明本輪比較仍然有元素互換,需要繼續(xù)進(jìn)行下輪排序。代碼實(shí)現(xiàn)如下:

/**
 * @Author {LearnAndGet}
 * @Time 2019年1月8日
 * @Discription:
 */
package com.sort;

import java.util.Arrays;

public class MaopaoSort {
    
    static int[] array = {1,2,0,3,5,4};
    
    public static void maopaoSort(int[] a) 
    {
        //外層循環(huán),是需要進(jìn)行比較的輪數(shù),一共進(jìn)行5次即可
        for(int i=0;i1;i++) 
        {
            boolean flag = false;
            //內(nèi)存循環(huán),是每一輪中進(jìn)行的兩兩比較
            for(int j=0;j1;j++) 
            {
                if(a[j] > a[j+1]) 
                {
                    int temp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = temp;
                    flag = true;
                }
            }
            System.out.println("第"+(i+1)+"輪排序后的數(shù)組為: "+Arrays.toString(a));
            if(flag == false)
            {
                System.out.println("本輪中的兩兩比較未發(fā)生元素互換,排序已經(jīng)完成啦");
                return;
            }
        }
    }
    
    public static void main(String[] args) {
        maopaoSort(array);
    }
}

運(yùn)行結(jié)果:

1輪排序后的數(shù)組為: [1, 0, 2, 3, 4, 5]2輪排序后的數(shù)組為: [0, 1, 2, 3, 4, 5]3輪排序后的數(shù)組為: [0, 1, 2, 3, 4, 5]
本輪中的兩兩比較未發(fā)生元素互換,排序已經(jīng)完成啦

五.冒泡排序的時(shí)間復(fù)雜度

冒泡排序是一種用時(shí)間換空間的排序方法,最壞情況是把順序的排列變成逆序,或者把逆序的數(shù)列變成順序。在這種情況下,每一次比較都需要進(jìn)行交換運(yùn)算。舉個(gè)例子來(lái)說(shuō),一個(gè)數(shù)列 5 4 3 2 1 進(jìn)行冒泡升序排列

第一輪的兩兩比較,需要比較4次;得到 4 3 2 1 5
第二輪的兩兩比較,需要比較3次;得到 3 2 1 4 5
第三輪的兩兩比較,需要比較2次;得到 2 1 3 4 5
第四輪的兩兩比較,需要比較1次;得到 1 2 3 4 5

所以總的比較次數(shù)為 4 + 3 + 2 + 1 = 10次
對(duì)于n位的數(shù)列則有比較次數(shù)為 (n-1) + (n-2) + ... + 1 = n * (n - 1) / 2,這就得到了最大的比較次數(shù)。
而O(N^2)表示的是復(fù)雜度的數(shù)量級(jí)。舉個(gè)例子來(lái)說(shuō),如果n = 10000,那么 n(n-1)/2 = (n^2 - n) / 2 = (100000000 - 10000) / 2,相對(duì)10^8來(lái)說(shuō),10000小的可以忽略不計(jì)了,所以總計(jì)算次數(shù)約為0.5 * N^2。用O(N^2)就表示了其數(shù)量級(jí)(忽略前面系數(shù)0.5)。

綜上所述,冒泡排序的時(shí)間復(fù)雜度為:O(n²)