在估计一个集合的势(大小)时,如果不要求很高的精确度,却要求较快的运算效率。我们推荐使用概率算法来求解。
设X是具有n个元素的集合,我们有回放地随机,均匀和独立地从X中选取元素,设k是出现第1次重复之前所选出的元素数目,则当n足够大时,k的期望值趋近为β√n,
这里β=√(π/2),利用此结论可以得出估计|X|的概率算法:n=2k2/π 。
算法伪代码如下:
SetCount (X)SetCount (X) { k ← 0; S ← Ф; a ← uniform(X); do { k++; S ← S∪{a}; a ← uniform(X); } while (a ∉S) return 2k2/π; }C语言描述如下:
#include<stdio.h> #include<math.h> #include<stdlib.h> #include<time.h> #define N 100000 a[N]={0}; void main() { unsigned int a[N]; unsigned int i,j,n,k=0; unsigned int uniform; srand( (unsigned)time(NULL)); printf(" 输入集合大小:"); scanf("%d",&n); for(i=0;i<n;i++) {uniform=rand()*rand()%n; a[i]=uniform; for(j=0;j<i;j++) { if(a[j]==a[i]) goto result; } } result: k=i; printf("计算结果为%5.0f, 真实值为%d\n",2*k*k/3.14,n); }
执行结果如下:
结论:
1:此方法适用于快速计算集合的势(大小),不适用于精确计算
2:本文执行结果为作者筛选后的结果。在执行过程中还是会出现一些不好的结果,但此概率计数不失为一个好方法。