簡體   English   中英

有人可以向我解釋這個快速排序算法嗎?

[英]Can someone explain this quicksort algorithm to me?

我對快速排序有點困惑。 例如,該算法取自 programcreek.com,使用中間元素作為 pivot 點:

public class QuickSort {
    public static void main(String[] args) {
        int[] x = { 9, 2, 4, 7, 3, 7, 10 };
        System.out.println(Arrays.toString(x));
 
        int low = 0;
        int high = x.length - 1;
 
        quickSort(x, low, high);
        System.out.println(Arrays.toString(x));
    }
 
    public static void quickSort(int[] arr, int low, int high) {
        if (arr == null || arr.length == 0)
            return;
 
        if (low >= high)
            return;
 
        // pick the pivot
        int middle = low + (high - low) / 2;
        int pivot = arr[middle];
 
        // make left < pivot and right > pivot
        int i = low, j = high;
        while (i <= j) {
            while (arr[i] < pivot) {
                i++;
            }
 
            while (arr[j] > pivot) {
                j--;
            }
 
            if (i <= j) {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
                i++;
                j--;
            }
        }
 
        // recursively sort two sub parts
        if (low < j)
            quickSort(arr, low, j);
 
        if (high > i)
            quickSort(arr, i, high);
    }
}

有人可以解釋底部的 2 個遞歸調用,以及為什么需要創建一個ij變量來復制左右標記。

另外,有人可以解釋使用中間元素的快速排序算法與使用第一個或最后一個元素作為 pivot 點之間的區別嗎? 代碼在某種意義上看起來不同,使用最后一個/第一個元素作為 pivot 點通常是用分區方法而不是上面的代碼編寫的。

謝謝!

快速排序基於分治法,首先我們取一個 pivot 元素並將所有小於這個 pivot 元素的元素放在左邊,所有大於這個 pivot 元素的元素放在右邊和之后pivot 的兩側相同,用於左側 Quicksort(array,low,pivot-1) 用於右側 Quicksort(array,low,pivot+1)

這是你第一個問題的答案

現在選擇中間元素或第一個元素作為 pivot 有什么區別所以當我們選擇第一個元素作為 pivot 排序后當 i 大於 j 時我們交換 pivot 元素與 j 元素pivot 出現在所有小於它的元素都出現在左側,所有大於它的元素都出現在右側的位置。

當我們選擇中間元素為 pivot 時,它已經在中間,所以不需要交換它。

這是 Hoare 分區方案的一種變體。 在與 pivot 進行比較之前,“經典”Hoare 分區方案增加 i 並減少 j。 此示例和問題示例都包括主 function 中的分區邏輯。

void quickSort(int a[], size_t lo, size_t hi)
{
    int pivot = a[lo+(hi-lo)/2];
    int t;
    if(lo >= hi)
        return;
    size_t i = lo-1;
    size_t j = hi+1;
    while(1)
    {
        while (a[++i] < pivot);
        while (a[--j] > pivot);
        if (i >= j)
            break;
        t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
    QuickSort(a, lo, j);
    QuickSort(a, j+1, hi);
}

與 pivot 比較后,問題代碼遞增 i 和遞減 j。

分區邏輯拆分一個分區,使得左側 <= pivot,右側 >= pivot。 pivot 和等於 pivot 的元素可以在任一側的任何位置結束,並且可能不會以它們的排序 position 結束,直到達到大小為 1 的子陣列的基本情況。

為 pivot 使用中間元素的原因是,如果數組已經排序或反向排序,則為 pivot 選擇第一個或最后一個元素將導致 O(n^2) 的最壞情況時間復雜度。 如果最后一個元素用於 pivot,則此答案中的示例將失敗(但問題示例不會)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM