簡體   English   中英

使用中間元素作為 Pivot C++ 計算快速排序中的比較次數

[英]Counting number of comparisons in Quick Sort using middle element as Pivot C++

我正在參加斯坦福大學提供的 Coursera 課程:“算法設計與分析”。 以隨機順序提供具有 10000 個不同整數的文本文件。 任務是在每次遞歸調用中使用中間元素作為樞軸執行快速排序后計算比較次數。

這是文本文件的鏈接: https ://drive.google.com/drive/u/0/folders/0B_WysIAkKMzzN3o4SEhoS0RjMUU

這就是我所做的:

#include <iostream>
#include <fstream>

using namespace std;

int partition(int arr[],int left,int pivot,int right);
int quickSort(int arr[], int left, int right);

int count = 0;

int partition(int arr[],int left,int pivot,int right) {
    int split = left + 1, tmp;

    for (int track = left + 1; track < right; track++) {
        if (arr[track] < pivot) {
            tmp = arr[track];
            arr[track] = arr[split];
            arr[split] = tmp;
            split++;
        }
    }

    tmp = arr[split - 1];
    arr[split - 1] = arr[left];
    arr[left] = tmp;
    return split - 1;
}


int quickSort(int arr[], int left, int right) {

    if (right <= left)
        return 0;

    int mid = (right + left - 1)/2;
    int pivot = arr[mid];
    arr[mid] = arr[left];
    arr[left] = pivot;
    int split = partition(arr,left,pivot,right);
    count += right - left - 1;

    quickSort(arr,left,split);
    quickSort(arr,split + 1,right);
    return count;
}

int main() {

    int ans;
    int arr[10001], i = 0;
    ifstream fin("QuickSort.txt");
    while (fin >> arr[i]) {
        i++;
    }
    fin.close();


    ans = quickSort(arr, 0, i);

    //To check if array is sorted
    for(int x = 0;x < i;x++) {
        cout<<arr[x]<<endl;
    }
    cout<<endl;

    cout << ans;
    return 0;
}

雖然數組排序很好,但計數是150657,這是錯誤的。 有人可以指出我是否在這里遺漏了什么? PS我已經做了好幾天了,所以如果有人幫助我,我會非常感激!

當你想計算某物時,直接的方法就是計算你正在計算的東西。 據我所知,您想計算以下行的執行次數:

if (arr[track] < pivot)

所以你需要做的就是把++count; 在那條線之前。 如果您想減少計算和/或了解更多,請考慮執行多少次:

編輯:當我寫下面的東西時,我真的沒有想到---。 這是錯誤的。 因此,直接計數與您計算計數的原始方法相匹配。 我測試了您的代碼,現在相信您正在計算正確的計數。 試着檢查一個小例子,並解釋為什么你認為巨大的計數是錯誤的。

我無法訪問您的數據文件,因此我無法確認或否認您的程序計算了該文件的正確計數。


for (int track = left + 1; track < right; track++)

該循環最多會執行它的主體 (right-left-2) 次。 既然你在那個時候知道 right>left,那么准確地說(而不是“最多”)right-left-2 是安全的。

我認為您的計數計算正確。 但是全局計數太不合適了,我認為必須糾正。 您可以通過更改以下內容完全消除該變量:

count += right - left - 1;

quickSort(arr,left,split);
quickSort(arr,split + 1,right);
return count;

return
   right - left - 1
+  quickSort(arr,left,split)
+  quickSort(arr,split + 1,right);

或將 count 設為本地,更改為:

int count = right - left - 1;

count += quickSort(arr,left,split);
count += quickSort(arr,split + 1,right);
return count;
  count += right - left - 1;

我覺得,在這里嘗試使用“右-左”。 由於“right-left+1”實際上是子數組的長度,這將給出您正在尋找的 M-1。 希望這可以幫助!

您選擇中間元素的中間索引不正確。 您沒有考慮到您將左右發送為數組中的某些點而不是 0 和 n。 例如,如果您有 [5,4,2,1,6,7] 並且您發送此數組的右半部分,那么您的左側將是 3,而右側將是 5(索引)。 該數組的中位數將是 6,但該數字的索引實際上是 4。您在此處的行將返回的是 (5 + 3 - 1)/2 = 3,這是不正確的。 注意:我假設正確是您的最后一個元素。

int mid = (right + left - 1)/2;

試試這個,而不是讓你的數組接受 left 作為 0 和 right 作為你的數組的長度,而不是中間嘗試:

int mid = ceil((right-left)/2) - 1 + left

您也可以使用 (right + left - 1)/2 的舊方法,但請確保您進行 ceil 並仔細檢查您是否真的選擇了正確的中位數。

暫無
暫無

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

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