十大經典排序算法 ( 一 ) 冒泡排序


介紹 :
  冒泡排序(Bubble Sort),是一種計算機科學領域的較簡單的排序算法。
  它重復地走訪過要排序的元素列,依次比較兩個相鄰的元素,如果順序(如從大到小、首字母從Z到A)錯誤就把他們交換過來。走訪元素的工作是重復地進行直到沒有相鄰元素需要交換,也就是說該元素列已經排序完成。
  這個算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端(升序或降序排列),就如同碳酸飲料中二氧化碳的氣泡最終會上浮到頂端一樣,故名“冒泡排序”。

算法原理 :

  1. 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
  2. 對每一對相鄰元素做同樣的工作,從開始第一對到結尾的最后一對。在這一點,最后的元素應該會是最大的數。
  3. 針對所有的元素重復以上的步驟,除了最后一個。
  4. 持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。

動圖演示 :

算法穩定性 :

  冒泡排序就是把小的元素往前調或者把大的元素往后調。比較是相鄰的兩個元素比較,交換也發生在這兩個元素之間。所以,如果兩個元素相等,是不會再交換的;如果兩個相等的元素沒有相鄰,那么即使通過前面的兩兩交換把兩個相鄰起來,這時候也不會交換,所以相同元素的前后順序並沒有改變,所以冒泡排序是一種穩定排序算法。

時間復雜度 :

  1.如果我們的數據正序,只需要走一趟即可完成排序。所需的比較次數 C 和記錄移動次數 M 均達到最小值,即:Cmin=n-1 ; Mmin=0 ; 所以,冒泡排序最好的時間復雜度為 O(n) 。

  2.如果很不幸我們的數據是反序的,則需要進行 n-1 趟排序。每趟排序要進行 n-i 次比較 ( 1 ≤ i ≤ n-1 ),且每次比較都必須移動記錄三次來達到交換記錄位置。在這種情況下,比較和移動次數均達到最大值:

  

  綜上所述:冒泡排序總的平均時間復雜度為:O(n2) ,時間復雜度和數據狀況無關。

Java代碼 :

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.Arrays;

/**
 * 冒泡排序
 */
public class BubbleSort {
    private static Log log = LogFactory.getLog (BubbleSort.class);

    public static void main(String[] args) {
        int size = 10;// 數組長度(0 - 10)
        int value = 100;// 值大小(-100 - 100)
        int[] arr = generateRandomArray (size, value);
        // 對象拷貝:一維數組:深克隆(重新分配空間,並將元素復制過去) 
        int[] bubbleArr = arr.clone ();
        int[] sortArr = arr.clone ();

        StringBuilder arrStr = new StringBuilder ("原數組: ");
        for (int number : arr) {
            arrStr.append (number).append (" ");
        }
        log.info (arrStr);

        bubbleSort (bubbleArr);
        StringBuilder bubbleStr = new StringBuilder ("冒泡排序:");
        for (int bValue : bubbleArr) {
            bubbleStr.append (bValue).append (" ");
        }
        log.info (bubbleStr);

        // 絕對正確的方法,這個方法可以時間復雜度很差,但是要保證其准確性
        Arrays.sort (sortArr);// 調用系統的函數來進行驗證
        StringBuilder sortStr = new StringBuilder ("系統函數排序: ");
        for (int sValue : sortArr) {
            sortStr.append (sValue).append (" ");
        }
        log.info (sortStr);

        log.info (isEqual (bubbleArr, sortArr) ? "成功" : "失敗");
    }

    private static boolean isEqual(int[] arr1, int[] arr2) {
        for (int i = 0; i < arr1.length; i++) {
            if (arr1[i] != arr2[i]) {
                return false;
            }
        }
        return true;
    }

    //N個數字冒泡排序,總共要進行N-1趟比較,每趟的排序次數為(N-i)次比較
    private static void bubbleSort(int[] arr) {
        //判斷邊界條件
        if (arr == null || arr.length < 2) {
            return;
        }
        log.info ("數組長度: " + arr.length + ", 預計執行" + (arr.length - 1) + "輪排序");
        boolean flag = false;// 判斷是否發生交換
        for (int i = 0; i < arr.length - 1; i++) {
            log.info ("=========第" + (i+1) + "輪比較");
            for (int j = 0; j < arr.length - i - 1; j++) {
                // 開始進行比較,如果arr[j]比arr[j+1]的值大,那就交換位置
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    flag = true;// 發生交換
                }
                StringBuilder sb = new StringBuilder ();
                sb.append ("第").append (j+1).append ("次比較:");
                for (int number : arr) {
                    sb.append (number).append (" ");
                }
                log.info (sb);
            }
            if (!flag) {
                log.info ("flag為false,未發生交換,數組有序,退出冒泡排序");
                break;
            }
            flag = false;
        }
    }

    //生成一個對數器。產生一個隨機樣本的數組,數組的長度和值都是隨機的
    private static int[] generateRandomArray(int size, int value) {
        // 生成長度隨機的數組,數組的最大長度是size的長度
        int[] arr = new int[(int) ((size + 1) * Math.random ())];
        for (int i = 0; i < arr.length; i++) {
            //針對數組中的每個值都可以隨機一下,一個隨機數減去另外一個隨機數,可能產生正數,也可能產生負數
            arr[i] = (int) ((value + 1) * Math.random ()) - (int) (value * Math.random ());
        }
        return arr;
    }

}

 


免責聲明!

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



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