有时我们需要查找某个集合里某个特定次序的元素。如果先排序然后再获得该元素,显然效率相对较低。下面是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 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);
}
其中a为输入集合,p为起始元素,r为结束元素,i为要查找的次序。
测试代码为:
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();
}
... {
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();
}