随机算法 实现估算集合的势

本文介绍了如何使用随机算法来估算1到N整数集合的势。通过随机、均匀和独立地选择元素,发现在出现第一次重复之前所选元素的平均数k接近于β√n,其中β为√(π/2)。据此,提出了一种概率算法,当n足够大时,可通过公式n=2k²/π来估计集合的大小。并提供了相应的C语言项目实现伪代码。

问题描述:估算一个1—N 整数集合的势


思路:设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/π;
         }
 复杂度:注意:∵k 的期望值是β√n,∴上述算法 n 需足够大,且运行多次后才能确定 n=|X|,即取多次运行后的平均值才能是 n。该算法的时间和空间均为θ(√n),因为k = θ(√n)


c语言项目实现:


#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include<stdbool.h>
#define Pi 3.1415926

typedef int ElemType;
typedef struct Node
{
        ElemType data;  //元素值
        int index;  //索引
        struct Node *next;
}Node,*Linklist;  //用单链表来表示集合

Linklist  LinkedListInit(); //单链表初始化
Linklist LinkedListCreat(int n);// 创建一个1-n的单链表集合
void append(Linklist L,int s);//往集合中添加一个元素,链表尾部添加一个值为S的元素

int findIndex(Linklist L,int index);//在集合找到索引为index的元素的值
bool  checkElem(Linklist L,int x); //判断x是否在集合中 
int SetCount(Linklist L,int n); //求集合L的势

int main()
{
        printf("随机算法估计整数子集1~n的大小:\n");
        printf("输入n的值");
        int m,n,i,answer;
        while(scanf("%d",&n) != EOF)
        {
                Linklist L;
                L = LinkedListCreat(n);
                answer =0;
                for(i=0;i<70;i++) //重复计算70次取平均
                {
                        m = SetCount(L,n);
                        answer += m;
                }
                printf("集合的势为:%d\n", answer/70);
        }
        return 0;
}

Linklist  LinkedListInit()
{
    Node *L;
    L = (Node *)malloc(sizeof(Node));   //申请结点空间 
    if(L == NULL)                       //判断是否有足够的内存空间 
        printf("申请内存空间失败\n");
    L->next = NULL;                  //将next设置为NULL,初始长度为0的单链表 
 return L;
}

Linklist LinkedListCreat(int n) //尾插法建表
{
        Node *L,*p;
        L = (Node*)malloc(sizeof(Node));
        L->next = NULL;
        Node  *current ;
        current = L;
        int i;
        for(i=1;i<=n;i++){
                p = (Linklist)malloc(sizeof(Node));
                p->data = i;
                p->index = i;
                current->next = p;
                current = p;
        }
        return L;
}

void append(Linklist L,int s)
{
        int n = 1;
        Linklist p,q;
        p = L;
        while(p->next)
                {
                        p = p->next;
                        n++;
                }
         q = (Linklist)malloc(sizeof(Node));
         q->data = s;
         q->index = n+1;
         p->next = q;

}

int findIndex(Linklist L,int a)
{
        Linklist p;
        p = L;
        int i;
        for(i=1;i<=a;i++)
                p = p->next;
        return p->data;
}

bool  checkElem(Linklist L,int x)
{
        Linklist p ;
        p = L;
        while(p->next != NULL)
        {
                p = p->next;
                if (p->data == x)
                        return true;
        }
        return false;
}
                                 
int SetCount(Linklist L,int n) //用随机算法求集合L的势
{
        int k = 0;
        int result,x,num,answer;
        Linklist p,q;
        p = L;
        q = LinkedListInit();

        srand((unsigned)time(NULL));
        x = rand()%n+1; //n个元素 n个索引 随机选取一个

        num = findIndex(p,x);
         do{
                k++;
                append(q,num);

                x = rand()%n+1; //n个元素 n个索引 随机选取一个
                num = findIndex(p,x);
         }while(!checkElem(q,num));

        answer = (int) ((2*k*k)/Pi);
        return answer;
}
                                                                                                                         
               

总结反思:此题由于集合的元素是有序的整数,故元素的索引值和数据域值相同,其实索引值域可以舍去。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值