随机算法(随机枢轴选择)每次运行程序时都会给出不同的输出

时间:2021-04-01 17:51:04

标签: c++ random quicksort random-seed

我正在处理一个大数据集,所以我决定实现从快速排序算法派生的线性选择算法,因为它在几乎线性的时间内给出数组中的第 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 函数的方式有问题,还是我的算法有其他问题?

提前致谢

1 个答案:

答案 0 :(得分:0)

partition中,当arr[j]arr[i]arr[i] < pi交换,但我们对arr[j]一无所知,除了{{1} } 从 j 开始(不是 1, l。请不要使用单个 l 作为变量名,这很容易引起误解)。

给定OP的签名并保持几乎相同的算法,它可以像下面这样写。

l

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

请注意,您实际上并不需要传递数组/分区的大小(元素数),可以通过其极端情况来推断。

另请注意,在标准库中,通常将范围的值作为一对迭代器(或实际的 std::range,因为 C++20)进行传递。见例如std::nth_elementstd::partition 以及它们可能的实现。