[英]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]
一無所知,除了j
從l
開始(不是 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_element
和std::partition
以及它們可能的實現。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.