這次終於有人把冒泡排序算法給說清楚了

前言

本文是第一站,大戰冒泡排序。你還在爲每次寫排序算法的時候發愁嗎?
喝了本專欄,保證你能手擼冒泡排序。

在這裏插入圖片描述

一、冒泡排序

1、冒泡排序原理

原理:

比較兩個相鄰的元素,符合要求(看自己的需求是從小到大,還是從大到小)即交換兩個元素的位置。

2、圖解冒泡排序原理

輸入一個數組,按小到大順序排列。

input:[5,4,6,1,3,2]

output:[1,2,3,4,5,6]

咱們就以這個題爲例子,來講解和演示一下冒泡排序的過程。

初始值就是:
在這裏插入圖片描述

我們最終通過冒泡排序要得到的結果

在這裏插入圖片描述

第一趟冒泡:

第1次:

5與4相比,5>4,所以換位置

在這裏插入圖片描述

第2次:

5與6相比,5< 6,所以不換位置

在這裏插入圖片描述

第3次:

6與1相比,6>1,所以換位置

在這裏插入圖片描述

第4次:

6與3相比,6>3,所以換位置

在這裏插入圖片描述

第5次:

6與2相比,6>2,所以換位置

在這裏插入圖片描述

第6次:

此時已經到達了第一趟的最後一個元素了,所以第一趟結束。

在這裏插入圖片描述

第一趟結束,得到第一趟冒泡的結果:

[4,5,1,3,2,6]

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

以此類推,最終就得到了:

[1,2,3,4,5,6]

3、思路

例如有一個數組:A=[5,2,3];

1、第1次比較,首先比較第1和第2個數,(如果A[1]>A[2],則交換位置)將大的數放在後面,將小的數放在前面;

2、第2次比較,比較第2和第3個數,如果第2個大於第3個數,則交換位置。

以此類推,每一趟都減少一次。

4、代碼實現冒泡排序

註釋的很清楚了,看明白應該是沒問題的。

package 排序算法.冒泡排序;

import java.util.Arrays;

/**
 * @Auther: truedei
 * @Date: 2020 /20-6-2 20:15
 * @Description:冒泡排序
 */
public class BubbleSort {

    public static int[] sort(int A[]){

        //一共冒泡A.length趟排序  如果有6個元素要排序,那麼就需要6次
        for (int i = 0; i < A.length; i++) {

            //第二層循環爲什麼是(A.length -i -1)
            // 減i是:每趟都忽略已經排好
            // 減1是:每次一趟的每一次到最後一個元素了
            for (int j = 0; j < A.length -i - 1  ; j++) {
                //比較i和j+1

                //例如有:[3,2,5,4,...] 現在遍歷到第1個了,A[j]=3;  A[j+1]=2 
                if(A[j] > A[j+1]){// 3 > 2  符合要求,則進入交換
                    int temp = A[j]; //定義一個臨時變量,用於交換數據
                    A[j] = A[j+1];
                    A[j+1] = temp;
                }

            }
        }

        return A;
    }


    public static void main(String[] args) {
        System.out.println(Arrays.toString(sort(new int[]{3,9,4,1,6})));
    }
}

運行之後,就可以得到結果:

[1, 3, 4, 6, 9]

上面這是從小到大排序的,下面這個是從大到小排序的:

只需要修改一下判斷條件: if(A[j] < A[j+1]){ } 即可

package 排序算法.冒泡排序;

import java.util.Arrays;

/**
 * @Auther: truedei
 * @Date: 2020 /20-6-2 20:15
 * @Description:冒泡排序
 */
public class BubbleSort {

    public static int[] sort(int A[]){

        //一共冒泡A.length趟排序  如果有6個元素要排序,那麼就需要6次
        for (int i = 0; i < A.length; i++) {

            //第二層循環爲什麼是(A.length -i -1)
            // 減i是:每趟都忽略已經排好
            // 減1是:每次一趟的每一次到最後一個元素了
            for (int j = 0; j < A.length -i - 1  ; j++) {
                //比較i和j+1

                //例如有:[3,2,5,4,...] 現在遍歷到第1個了,A[j]=3;  A[j+1]=2 
                if(A[j] < A[j+1]){// 3 < 2  符合要求,則進入交換
                    int temp = A[j]; //定義一個臨時變量,用於交換數據
                    A[j] = A[j+1];
                    A[j+1] = temp;
                }

            }
        }

        return A;
    }


    public static void main(String[] args) {
        System.out.println(Arrays.toString(sort(new int[]{3,9,4,1,6})));
    }
}

5、冒泡排序的時間複雜度分析

分析算法的時間複雜度,通常都是分析最壞的時間複雜度的情況。讓程序在最壞的情況下,也能保證流暢的服務。這纔是分析的目的。

對於冒泡排序的最壞的情況就是逆序的情況。

例如:[6,5,4,3,2,1]

每一次比較,都去交換元素

對於這個排序算法:在做分析的時候,通常不會把for循環拿出來做分析的

public static int[] sort(int A[]){
    for (int i = 0; i < A.length; i++) {
        for (int j = 0; j < A.length -i - 1  ; j++) {
            //比較j和j+1
            if(A[j] < A[j+1]){
                int temp = A[j]; 
                A[j] = A[j+1];
                A[j+1] = temp;
            }

        }
    }
    return A;
}

而真正實現排序的是下面這段代碼:

if(A[j] < A[j+1]){
    int temp = A[j]; 
    A[j] = A[j+1];
    A[j+1] = temp;
}

就拿:[6,5,4,3,2,1] 來說

第一趟:

6與5比較,然後交換

6與4比較,然後交換

6與3比較,然後交換

6與2比較,然後交換

6與1比較,然後交換

第二趟:

5與4比較,然後交換

5與3比較,然後交換

5與2比較,然後交換

5與1比較,然後交換

第三趟:

4與3比較,然後交換

4與2比較,然後交換

4與1比較,然後交換

以此類推

元素比較的次數爲:

(N1)+(N2)+(N3)+...+2+1 (N-1)+(N-2)+(N-3)+...+2+1

=
(N1)/2 N*(N-1)/2
推導過後,得出冒泡排序時間複雜度是:
O(N2) O(N^{2})

6、小技巧:常用時間複雜度

(1) O(1)

(1)O(1) 這個針對的是常數;對於一個N,不管這個N是如何增長,這個時間是不變的。

例如下面這些代碼的時間複雜度都是O(1):

/**
 * @Auther: truedei
 * @Date: 2020 /20-6-2 22:01
 * @Description:
 */
public class Test {

    public static void main(String[] args) {
        System.out.println("你好,我叫鄭暉");
        System.out.println("你好,我叫鄭暉");
        System.out.println("你好,我叫鄭暉");
        System.out.println("你好,我叫鄭暉");
    }
    
}

還有這種:

我有一個數組,我知道了我需要的這個數據所在的索引,然後去拿這個值,咋這種也是O(1)

/**
 * @Auther: truedei
 * @Date: 2020 /20-6-2 22:01
 * @Description:
 */
public class Test {

    public static void main(String[] args) {
        String[] names = {"小明","小紅","鄭暉"};

        System.out.println("你好,我叫"+names[2]);
    }

}

(2) O(n)

O(n)是一個線性增長的。

經常用在for()循環當中

例如下面這種代碼:


/**
 * @Auther: truedei
 * @Date: 2020 /20-6-2 22:01
 * @Description:
 */
public class Test {

    public static void main(String[] args) {
        String[] names = {"小明","小紅","鄭暉"};

        for (int i = 0; i < names.length; i++) {
            System.out.println("你好,我叫"+names[i]);
        }
    }

}

(3) O(n^2)

是一個平方級的的增長。經常出現在兩層for循環

例如本文所寫的:

public static int[] sort(int A[]){
    for (int i = 0; i < A.length; i++) {
        for (int j = 0; j < A.length -i - 1  ; j++) {
           .....
        }
    }
    return A;
}

(4) O(n^3)

是一個立方級的增長。經常出現在遍歷一個三層的for循環

 for (...) {
     for (...) {
         for (...) {
             .....
         }
     }
 }

(5) O(lg n)

是一個對數級。

在二分查找法裏就是O(lg n)

每次執行N是以一個倍數的形式是遞減的:

比如第1次:1/2

比如第2次:1/4

比如第3次:1/8

比如第4次:1/16

快速的讓N的規模變小。

(6) O(n lg n)

在排序中經常見到的

(7) O(2^n)

指數級的

7、附:常用的排序算法的時間複雜度和空間複雜度

排序法 最差時間分析 平均時間複雜度 穩定度 空間複雜度
冒泡排序 O(n^2) O(n^2) 穩定 O(1)
快速排序 O(n^2) O(n*log2n) 不穩定 O(log2n)~O(n)
選擇排序 O(n^2) O(n^2) 不穩定 O(1)
二叉樹排序 O(n^2) O(n*log2n) 不穩定 O(n)
插入排序 O(n^2) O(n^2) 穩定 O(1)
堆排序 O(n*log2n) O(n*log2n) 不穩定 O(1)
希爾排序 O O 不穩定 O(1)

二、小鄭有話說

如果對你有幫助,可以分享給你身邊的朋友。或者給俺點個大大的贊和大大的評論,點贊和評論就是給我最大的支持,感謝。
水平有限,難免會有疏漏或者書寫不合理的地方,歡迎交流討論。
作者:TrueDei
作者主頁:https://truedei.blog.csdn.net/(https://truedei.blog.csdn.net/article/details/106269373)
轉載說明:如需轉載請註明原地址和作者名。

如果喜歡我的文章,還沒看夠可以關注我,我會用心寫好每一篇文章。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章