1. 程式人生 > >排序算法的簡單實現(冒泡和快排)

排序算法的簡單實現(冒泡和快排)

boolean nlogn pub 內部 amp 中心 程序 strong 大循環

排序算法

冒泡排序

原理:把相鄰的元素兩兩比較,根據大小來交換元素的位置。

原始的冒泡排序是穩定排序。由於該排序的每一輪要遍歷所以元素,輪轉的次數和元素數量相當,所以時間復雜度是 O(N^2)。

java代碼表達如下:

import java.util.Arrays;

public class BubbleSort{
    private static void sort(int array[]){
        int tmp = 0;
        for (int i = 0; i < array.length; i++){
            for (int j = 0; j < array.length - i - 1;j++) {
                if (array[j] > array[j+1]) {
                    tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                }
            }
        }
    }

    public static void main(String[] args){
        int[] array = new int[]{5,8,6,3,9,2,1,7};
        sort(array);
        System.out.println(Arrays.toString(array));
    }
}

(使用雙循環來進行排序。外部循環控制所有的回合,內部循環代表每一輪的冒泡處理,先進行元素比較,再進行元素交換。)

冒泡優化(一)

判斷出數列已經有序,並且做出標記,剩下的幾輪排序就可以不必執行,提早結束工作。

代碼如下:

import java.util.Arrays;

public class BubbleSort{
    private static void sort(int arrray[]){
        int tmp = 0;
        for (int i = 0; i < arrray.length; i++) {
            //有序標記,每一輪的初始是true
            boolean isSorted = true;
            for (int j = 0; j < arrray.length - i - 1; j++ ) {
                if(arrray[j] > arrray[j+1]) {
                    tmp = arrray[j];
                    arrray[j] = arrray[j+1];
                    arrray[j+1] = tmp;

                    //有元素交換,所以不是有序,標記變為false
                    isSorted = false;
                }
            }
            if(isSorted){
                break;
            }
        }
    }

    public static void main(String[] args){
        int[] arrray = new int[]{5,8,6,3,9,2,1,7};
        sort(arrray);
        System.out.println(Arrays.toString(arrray));
    }
}

利用布爾變量 isSorted作為標記。如果在本輪排序中,元素有交換,則說明數列無序;如果沒有元素交換,說明數列已然有序,直接跳出大循環。

冒泡優化(二)

如果元素排序前面無序,後面無序,我們可以設定排序邊界,這樣當遍歷到有序數組時,跳出循環,結束程序。

思路:我們在每一輪排序的最後,記錄下最後一次元素交換的位置,那個位置也就是無序數列的邊界,再往後就是有序區了。

代碼如下:

import java.util.Arrays;

public class BubbleSort {
    private static void sort(int array[]) {
        int tmp = 0;
        // 記錄最後一次交換的位置
        int lastExchangeIndex = 0;
        // 無序數列的邊界,每次比較只需要比到這裏為止
        int sortBorder = array.length - 1;
        for (int i = 0; i < array.length; i++) {
            // 有序標記,每一輪的初始是true
            boolean isSorted = true;
            for (int j = 0; j < sortBorder; j++) {
                if (array[j] > array[j+1]) {
                    tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                    // 有元素交換,所以不是有序,標記為false
                    isSorted = false;
                    // 把無序數列的邊界更新為最後一次交換元素的位置
                    lastExchangeIndex = j;
                }
            }

            sortBorder = lastExchangeIndex;
            if (isSorted) {
                break;
            }
        }
    }

    public static void main(String[] args) {
        int[] array = new int[]{3,4,2,1,5,6,7,8};
        sort(array);
        System.out.println(Arrays.toString(array));
    }
}

sortBorder 就是無序數列的邊界。每一輪排序過程中,sortBorder 之後的元素就完全不需要比較了,肯定是有序的。

快速排序

快速排序跟冒泡排序一樣,都屬於交換類排序,通過采用不斷的比較和移動元素來實現排序。

快速排序利用了 ”分治法“ 的思想, 通過設置基準數 key ,將比基準數大的數從前面移動到後面,比基準數小的數從後面移動到前面,將數組分為兩部分,其中以 key 為中心, key 左邊的數比 key 小,key 右邊的數比 key 大,然後對這兩部分分別重復這個排序的過程,直到整個有序。

由於采取 ”分治法“ ,我們可以很容易的得出快速排序的平均時間復雜度為:O(nlogn)

快速排序的簡單實現:

import java.util.Arrays;

public class QuickSort {
    private static void quickSort(int[] a, int low, int high) {
        //1.找到遞歸算法的出口
        if (low > high) {
            return;
        }
        //2. 存
        int i = low;
        int j = high;
        //3. key
        int key = a[low];
        //4,完成一趟排序
        while(i < j) {
            //4.1 從右往左找到第一個小於key的數
            while(i<j && a[j] > key){
                j--;
            }
            //4.2 從左往右找到第一個大於key的數
            while (i<j && a[i] <= key) { 
                i++;
            }
            //4.3 交換
            if(i < j){
                int p = a[i];
                a[i] = a[j];
                a[j] = p;
            }
        }
        //4.4 調整key的位置
        int p = a[i];
        a[i] = a[low];
        a[low] = p;
        //5. 對key左邊的數快排
        quickSort(a, low, i - 1);
        //6. 對key右邊的數快排
        quickSort(a, i + 1, high);
    }

    public static void quickSort(int[] a){
        if (a.length>0) {
            quickSort(a, 0, a.length - 1);
        }
    }

    public static void main(String[] args) {
        int[] a = {1,2,4,5,7,4,5,3,9,0};
        quickSort(a);
        System.out.println(Arrays.toString(a));
    }

}

排序算法的簡單實現(冒泡和快排)