有时我们需要查找某个集合里某个特定次序的元素。如果先排序然后再获得该元素,显然效率相对较低。下面是ITOA上的算法,时间复杂度为O(n)。
int
Partition(
int
*
a,
int
p,
int
r)

...
{
int x = a[r], i = p - 1;

for (int j = p; j < r; j++)

...{
if (a[j] <= x) swap(a[++i], a[j]);
}
swap(a[++i], a[r]);
return i;
}

int
RandomizedPartition(
int
a[],
int
p,
int
r)

...
{
srand((unsigned)time(NULL));

int i = p + rand() % (r - p + 1);
swap(a[r], a[i]);

return Partition(a, p, r);
}

int
RandomizedSelect(
int
a[],
int
p,
int
r,
int
i)

...
{
if (p == r) return a[p];
int q = RandomizedPartition(a, p, r);
int k = q - p + 1;
if (i == k) return a[q];
else if (i < k) return RandomizedSelect(a, p, q - 1, i);
else return RandomizedSelect(a, q + 1, r, i - k);
}
int
main()

...
{
const int SIZE = 1000000;
const int SELECT = 1000;
int *pnData = new int[SIZE];
int *pnSource = new int[SIZE];

srand((unsigned)time(NULL));
for (int i = 0; i < SIZE; i++)

...{
pnSource[i] = rand()%SIZE;
}
Print(pnSource, 10, "Data: ");

memcpy(pnData, pnSource, sizeof(int) * SIZE);
cout << "The minimum element is: " << Minimum(pnData, SIZE) << endl;
cout << "The " << SELECT << "th element is: " << RandomizedSelect(pnData, 0, SIZE - 1, SELECT) << endl;

Print(pnData, SIZE > 10 ? 10 : SIZE, "After select: ");

delete []pnData;
delete []pnSource;

return getchar();
}




































其中a为输入集合,p为起始元素,r为结束元素,i为要查找的次序。
测试代码为:


























