隨機演算法 實現估算集合的勢
阿新 • • 發佈:2018-12-31
問題描述:估算一個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);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; }
總結反思:此題由於集合的元素是有序的整數,故元素的索引值和資料域值相同,其實索引值域可以捨去。