排序算法之冒泡排序

package com.example.demo.sort;

import java.util.Arrays;

/**
 * 冒泡排序
 * 相鄰元素兩兩比較,
 * 每一路結束後會在隊尾的有序區域多一個元素
 * 一共需要遍歷size-1輪
 * 時間複雜度O(n²)
 */
public class BubbleSortDemo {


    public static void main(String[] args) {
        int[] demo = {17, 5, 12, 8, 15, 6, 19, 10, 18, 10, 3, 9, 14, 2, 11, 4, 1, 16, 7, 13};
//        bubbleSortV1(demo);
//        bubbleSortV2(demo);
        bubbleSortV3(demo);
    }

    /**
     * v1  未優化
     *
     * @param demo
     */
    public static void bubbleSortV1(int[] demo) {
        long t1 = System.currentTimeMillis();
        for (int i = 0; i < demo.length - 1; i++) {
            for (int j = 0; j < demo.length - i - 1; j++) {
                //內層循環如果寫成demo.length-1也可以,只是相當於把隊尾的有序區域也拿進來參與比較了
                if (demo[j] > demo[j + 1]) {
                    int temp = demo[j];
                    demo[j] = demo[j + 1];
                    demo[j + 1] = temp;
                }
            }
        }
        System.out.println("V1用時:" + (System.currentTimeMillis() - t1));

        //輸出結果
        System.out.println(Arrays.toString(demo));
    }

    /**
     * 初步優化
     * 如果某一輪遍歷中沒有發生過交換,說明數組已經有序,剩下的遍歷可以不必進行
     *
     * @param demo
     */
    public static void bubbleSortV2(int[] demo) {
        long t1 = System.currentTimeMillis();
        for (int i = 0; i < demo.length - 1; i++) {
            //初始化一個標記,認爲當前數組是有序的
            boolean isSorted = true;
            for (int j = 0; j < demo.length - i - 1; j++) {
                if (demo[j] > demo[j + 1]) {
                    int temp = demo[j + 1];
                    demo[j + 1] = demo[j];
                    demo[j] = temp;
                    //如果發生了交換,說明數組是無序的
                    isSorted = false;
                }
            }
            //如果某一個回合遍歷結束之後數組是有序的,那麼直接結束遍歷
            if (isSorted) {
                System.out.println("在第" + (i + 1) + "輪遍歷後數組已經有序");
                break;
            }
        }
        System.out.println("V2用時:" + (System.currentTimeMillis() - t1));
        //輸出結果
        System.out.println(Arrays.toString(demo));
    }

    /**
     * 再次優化
     * 以上,第i輪遍歷後隊尾的i個元素是有序區域,這只是一般情況,實際有序元素的格式會大於i
     * 在每一輪遍歷時,最後發生交換的位置,就是實際有序區域開始的位置,再往後就都是有序的
     *
     * @param demo
     */
    public static void bubbleSortV3(int[] demo) {
        long t1 = System.currentTimeMillis();
        //定義無序區域的下標,內部循環中相鄰元素比較時只需要比較到這個位置
        int sortBorder = demo.length - 1;
        //定義最後一次交換的位置
        int lastExchangeIndex = 0;
        for (int i = 0; i < demo.length - 1; i++) {
            //初始化一個標記,認爲當前數組是有序的
            boolean isSorted = true;
            for (int j = 0; j < sortBorder; j++) {
                if (demo[j] > demo[j + 1]) {
                    int temp = demo[j];
                    demo[j] = demo[j + 1];
                    demo[j + 1] = temp;
                    //如果發生了交換,說明數組是無序的
                    isSorted = false;
                    //覆蓋最後交換位置
                    lastExchangeIndex = j;
                }
            }
            //將本次最後交換位置定義爲下一次遍歷的終點位置,即無序區域的結束位置
            sortBorder = lastExchangeIndex;
            //如果某一個回合遍歷結束之後數組是有序的,那麼直接結束遍歷
            if (isSorted) {
                System.out.println("在第" + (i + 1) + "輪遍歷後數組已經有序");
                break;
            }
        }
        System.out.println("V3用時:" + (System.currentTimeMillis() - t1));

        //輸出結果
        System.out.println(Arrays.toString(demo));

    }

    /**
     * 此外,還有雞尾酒排序
     * 是基於冒泡排序的改進,在每一輪遍歷中,是雙向進行比較交換的
     * 適用於數組元素大部分已經有序的情況
     */
}

 

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