簡體   English   中英

每次我運行程序時,隨機算法(隨機 pivot 選擇)都會給出不同的 output

[英]Randomized algo (randomized pivot selection) gives different output everytime i run the program

我正在處理一個大數據集,所以我決定實現從快速排序算法派生的線性選擇算法,因為它在幾乎線性的時間內給出了數組中的第 n 個最小元素。 這是我的實現:

long Random(long lower, long upper)
{
    long num = (rand() % (upper - lower + 1)) + lower;
    return num;
}
long partition(long arr[], long l, long r, long pivot)
{
    long j = l;
    long pi = arr[pivot];
    swap(&arr[pivot], &arr[r]);
    for (int i = l; i < r; i++)
    {
        if ((arr[i] < pi) && (j != i))
        {
            swap(&arr[j], &arr[i]);
            j++;
        }
    }
    swap(&arr[r], &arr[j]);
    return j;
}

long select(long arr[], long l, long r, long n, int i)
{
    if (n == 1)
    {
        return arr[0];
    }
    long pivot = Random(l, r);
    long x = partition(arr, l, r, pivot);
    if (x == i)
    {
        return arr[x];
    }
    else if (x > i)
    {
        return select(arr, l, x, (x - 1), i);
    }
    else
    {
        return select(arr, x, r, (n - x), (i - x));
    }
}

int main(void)
{
    srand(time(0));
    FILE *f;
    f = fopen("integers.txt", "r");
    long arr[SIZE];

    for (int i = 0; i < SIZE; i++)
    {
        fscanf(f, "%ld", &arr[i]);
    }
    fclose(f);

    long in;
    cout << "Enter the index you want to find - ";
    cin >> in;
    cout << select(arr, 0, (SIZE - 1), SIZE, (in - 1)) << endl;
}

它不僅給出不正確的答案,而且每次給出不同的答案。 我不知道為什么,我使用 srand 和 rand 函數的方式有問題,還是我的算法有其他問題?

先感謝您

partition中,當arr[i] < pi時, arr[j]arr[i]交換,但我們對arr[j]一無所知,除了jl開始(不是 1,l。請不要' t 使用單個l作為變量名,容易產生誤解)。

給定 OP 的簽名並保持幾乎相同的算法,它可以寫成如下。

long partition(long arr[], long left, long right, long pivot_index)
{
    using std::swap;
    
    // "Protect" the pivotal value moving it to the right.
    long pivot = arr[pivot_index];
    swap(arr[right], arr[pivot_index]);

    // Find the first element of the right partition.
    long j = left;
    while ( arr[j] < pivot  &&  j < right)
        ++j;
    
    // Corner case, the pivot is the max value too.
    if ( j == right)
        return j;

    // Move all the elements less than the pivotal value to the left.
    for (long i = j + 1; i < right; ++i)
    {
        if ( arr[i] < pivot )
        {
            swap(arr[j], arr[i]);
            // j is the index of the first element not less than the pivot.
            ++j;
        }
    }

    // Put the pivot "back" in place.
    swap(arr[j], arr[right]);
    return j;
}

select需要一些調整。

// ...
if (x == i)
{
    return arr[x];
}
else if (x > i)
{
    return select(arr, left, x - 1, x - left, i);
    //                       ^^^^^  ^^^^^^^^
    // Given that x > i, I know that x is wrong and that x > left
}
else
{
    return select(arr, x + 1, right, right - x, i);
    //                 ^^^^^         ^^^^^^^^^  ^
    // 'i' must be passed untouched, it refers to the whole array
}

請注意,您實際上並不需要傳遞數組/分區的大小(元素數),它可以通過它的極端來推斷。

另請注意,在標准庫中,通常將一系列值作為一對迭代器(或實際的std::range ,自 C++20 以來)傳遞。 參見例如std::nth_elementstd::partition以及它們可能的實現。

暫無
暫無

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

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