常見的排序演算法:冒泡、快排、歸併

Yfeil發表於2024-04-20

氣泡排序:

氣泡排序就像水裡的氣泡一樣,輕的氣泡會一點一點地浮到水面。在這個演算法中,我們將待排序的元素比喻成氣泡,透過比較相鄰元素的值,讓較大的元素慢慢“浮”到陣列的末端。

具體步驟如下:

  1. 比較相鄰的兩個元素,如果前一個比後一個大(假設我們要從小到大排序),就交換它們的位置。
  2. 對每一對相鄰元素做同樣的工作,從開始第一對到結尾的最後一對。這步做完後,最後的元素會是最大的數。
  3. 針對所有的元素重複以上的步驟,除了最後已經排序好的元素。
  4. 持續每次對越來越少的元素重複上面的步驟,直到沒有任何一對數字需要比較。
public static void bubbleSort(int[] arr) {
    int n = arr.length;
    boolean swapped;
    for (int i = 0; i < n - 1; i++) {
        swapped = false;
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                // 交換 arr[j] 和 arr[j + 1]
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                swapped = true;
            }
        }
        // 如果內層迴圈沒有發生交換,說明陣列已經有序,可以提前結束排序
        if (!swapped) {
            break;
        }
    }
}

快速排序:

快速排序的思想是找一個基準值(pivot),將陣列分為兩部分,左邊都比基準值小,右邊都比基準值大。然後對這兩部分再遞迴地進行同樣的操作。

具體步驟如下:

  1. 選擇一個基準值,通常是陣列的中部或最後一個元素。
  2. 將陣列分為兩部分,小於基準值的元素放到左邊,大於基準值的元素放到右邊。
  3. 對左右兩個子陣列重複步驟1和2,直到每個子陣列的元素數量不超過1。
public static void quickSort(int[] arr) {
    if (arr == null || arr.length < 2) {
        return;
    }
    quickSort(arr, 0, arr.length - 1);
}

private static void quickSort(int[] arr, int low, int high) {
    if (low < high) {
        // 找到基準元素的正確位置
        //之前:{2, 9, 3, 6, 4, 1, 8, 7, 5}
        int pivotIndex = partition(arr, low, high);
        //之後:{2, 3, 4, 1, →5←, 6, 8, 7, 9} 5號歸位
        // 對基準左邊和右邊的子陣列進行快速排序
        quickSort(arr, low, pivotIndex - 1);//排序 {2, 3, 4, 1}
        quickSort(arr, pivotIndex + 1, high);//排序 {6, 8, 7, 9}
    }
}

private static int partition(int[] arr, int low, int high) {
    // 選擇最後一個元素作為基準
    int pivot = arr[high];
    int i = low;
    for (int j = low; j < high; j++) {
        // 將小於基準的元素放到左邊
        if (arr[j] < pivot) {
            swap(arr, i++, j);
        }
    }
    // 將基準放到正確的位置
    swap(arr, i, high);
    return i;
}

private static void swap(int[] arr, int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

歸併排序:

歸併排序是採用分治法的一個非常典型的應用。它的思想是將陣列分成若干個小陣列,對每個小陣列進行排序,然後將小陣列合併成較大的陣列,直到最後只有一個排序完成的大陣列。

具體步驟如下:

  1. 把陣列分成若干個小陣列,直到每個小陣列只有一個元素。
  2. 將相鄰的小陣列合併成較大的陣列,合併時對陣列進行排序。
  3. 重複步驟2,直到最後只有一個排序完成的大陣列。
public static void mergeSort(int[] arr) {
    if (arr == null || arr.length < 2) {
        return;
    }
    int mid = arr.length / 2;
    int[] left = new int[mid];
    int[] right = new int[arr.length - mid];

    System.arraycopy(arr, 0, left, 0, mid);
    System.arraycopy(arr, mid, right, 0, arr.length - mid);

    mergeSort(left);
    mergeSort(right);
    merge(arr, left, right);
}

private static void merge(int[] arr, int[] left, int[] right) {
    int i = 0, j = 0, k = 0;
    while (i < left.length && j < right.length) {
        if (left[i] <= right[j]) {
            arr[k++] = left[i++];
        } else {
            arr[k++] = right[j++];
        }
    }
    while (i < left.length) {
        arr[k++] = left[i++];
    }
    while (j < right.length) {
        arr[k++] = right[j++];
    }
}

總結:

這三種排序演算法各有特點,氣泡排序簡單但效率較低,快速排序效率高但需要額外的儲存空間,歸併排序則是效率和穩定性都比較好的排序演算法。在實際應用中,根據不同的需求選擇合適的排序演算法是很重要的。

相關文章