冒泡排序詳解


概述:

一種將數組中無序元素按照大小規則依次排列的方法。
最小或最大的元素會像水中的氣泡一樣"漂浮"到數組的一端,故得名"冒泡排序"。


原理:

對數組中的元素兩兩相比,根據比較的結果,將大小不同的元素通過第三變量互換、分開放置。當上述過程重復足夠多次時,便實現對所有元素的有序排列。
我們也可以用一句話概括冒泡排序原理:相鄰元素比較大小,交換位置,重復上述過程。


實現冒泡排序代碼的流程結構:

按照我們之間學過的流程結構,我們可以確定冒泡排序需要用到的結構有:

順序結構:用於實現交換位置的功能。
選擇結構:用於實現判斷相鄰元素大小的功能。
循環結構:用於重復執行選擇結構和順序結構的功能。


冒泡排序的子功能

我們來按照功能依次展開說明:

1.交換位置功能:
我們先創建一個數組,在數組中放入元素。

        int[] arr = {1,2,3,5,4};//數組的靜態初始化

我們可以把數組看成一列火車,每個下標對應的位置都是一節車廂,一節車廂裝着一個元素。

我們可以得到數組下標位置和元素的關系如下:

arr[0] arr[1] arr[2] arr[3] arr[4]
1 2 3 5 4

我們現在要交換5和4元素的位置,使數組的順序變成{1,2,3,4,5},怎么交換?

常見的方法是定義一個臨時變量,用這個臨時變量保存兩個元素中的一個,相當於做了個備份,再將兩個元素中的沒有備份的賦值給另一個,把臨時變量保存的元素、備份的賦值給那個一開始沒有備份的元素,這樣就完成了交換。

我們用圖片來看更直觀:

用代碼實現就是這樣:

    int temp = arr[3];
    arr[3] = arr[4];
    arr[4] = temp;

可能有細心的小伙伴們好奇,如果我備份的是4不是5呢?
圖片安排:

用代碼實現就是這樣:

    int temp = arr[4];
    arr[4] = arr[3];
    arr[3] = temp;

看好了哈,臨時變量的選取不影響互換結果。

2.判斷相鄰元素的大小功能:
我們使用if條件語句判斷相鄰元素大小關系是否滿足條件。
在兩相鄰元素關系中,我習慣稱下標位置小的元素為"左元素",下標位置大的元素為"右元素"。
根據冒泡排序原理,我們會先比較相鄰元素大小,只有滿足大小關系的兩元素才交換位置。

如果"左元素"大於"右元素"

我們使用交換位置功能交換相鄰位置的數據,"左右元素的大小關系"會反轉,那么大的元素會在右邊,小的元素會在左邊。

"右元素"大於"左元素"同理。

3.重復執行和遍歷元素的功能
不計交換位置的次數,
假如數組中只有2個元素,兩兩相較我們最少比較1次才實現整個數組的排序。
假如數組中有3個元素,兩兩相較,我們最少需要比較3次才實現整個數組的排序。

比較次數 arr[0] arr[1] arr[2]
初始值 1 2 3
1次 2 1 3
2次 2 3 1
3次 3 2 1
假如數組中有4個元素,兩兩相較,我們最少需要比較6次才能實現整個數組的排序
比較次數 arr[0] arr[1] arr[2]
:-: :-: :-: :-:
初始值 6 7 8
1次 7 6 8
2次 7 8 6
3次 7 8 9
4次 8 7 9
5次 8 9 7
6次 9 8 7

通過觀察數組下標位置和比較次數的變化,可以得出關系:

數組中有2個元素,比較並交換1次,即可完成排序。

數組中有3個元素,比較並交換2次,數組下標的循環變量需要回歸到0,此時數組中有1個數處在最終位置,不需要交換。
剩下需要比較的元素,相當於只有2個元素數組的情況,數組下標的循環變量需要回歸到0,只要比較並交換1次,整個數組即可完成排序,整個過程中數組下標的循環變量需要歸零1次。

數組中有4個元素,比較並交換3次,數組下標的循環變量需要回歸到0,此時數組中有1個數處在最終位置,不需要交換。
剩下需要比較的元素,相當於只有3個元素數組的情況,數組下標的循環變量需要回歸到0,比較並交換2次,剩下需要比較的元素,相當於只有2個元素數組的情況,數組下標的循環變量需要回歸到0,只要比較並交換1次,整個數組即可完成排序,整個過程中數組下標的循環變量需要歸零3次。

也就是說,長度為x的數組,比較並交換(x-1)次,數組下標的循環變量需要回歸到0,需要比較並交換(x-2)次,數組下標的循環變量需要回歸到0,比較並交換(x-n)=1次,整個數組即可完成排序,整個過程中數組下標的循環變量需要歸零(x-1)次,每次歸零后比較並交換的次數要比上一次小1。

我們可以用嵌套for循環實現重復執行和遍歷數組元素的功能,根據嵌套循環【1次外循環,1輪內循環】的特點:

外循環變量最小值【i = 0】、最大值【i = 數組長度 - 1】。由於【每次歸零后比較並交換的次數要比上一次小1】且外循環變量有自增1的特點,因此內循環變量最小值【j = 0】、最大值【j = 數組長度 - 1 - i】。

所以我們可以寫出代碼:

        int[] arr = {6,7,8,9};
        System.out.print("初始順序:");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+",");
        }
        System.out.print("目標順序:9,8,7,6");
        System.out.println("\n-----------------");

        int temp = 0;
        int count = 0;
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - i - 1; j++) {

                System.out.println("第"+(i + 1)+"輪第"+(j + 1)+"次");

                //后小前大,倒序
                if (arr[j + 1] > arr[j]){

                    System.out.print("互換前:");
                    for (int k :
                            arr) {
                        if (k == arr[j])
                            System.out.print("["+k+",");
                        else if(k == arr[j + 1])
                            System.out.print(k+"],");
                        else
                            System.out.print(k+",");
                    }

                    temp = arr[j + 1];
                    arr[j + 1] = arr[j];
                    arr[j] = temp;

                    System.out.print("互換后:");
                    for (int k :
                            arr) {
                        if (k == arr[j])
                            System.out.print("["+k+",");
                        else if(k == arr[j + 1])
                            System.out.print(k+"],");
                        else
                            System.out.print(k+",");
                    }
                    System.out.println();
                }else{
                    System.out.println("不滿足條件,沒有互換");
                }
                count++;
            }
        }
        System.out.println("-----------------");
        System.out.println("總共比較"+count+"次");

運行結果:

初始順序:6,7,8,9,目標順序:9,8,7,6
-----------------
第1輪第1次
互換前:[6,7],8,9,互換后:[7,6],8,9,
第1輪第2次
互換前:7,[6,8],9,互換后:7,[8,6],9,
第1輪第3次
互換前:7,8,[6,9],互換后:7,8,[9,6],
第2輪第1次
互換前:[7,8],9,6,互換后:[8,7],9,6,
第2輪第2次
互換前:8,[7,9],6,互換后:8,[9,7],6,
第3輪第1次
互換前:[8,9],7,6,互換后:[9,8],7,6,
-----------------
總共比較6次


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM