DGIM算法c语言实现

        DGIM算法能够使用O(log2N)位的情况下表示N位窗口,将估计得错误率降到任意大于0得数。

    流中每位都有时间戳,我们将窗口划分为多个桶,每个桶中包含

    1、最右部得时间戳(最近的时间戳)

    2、桶的大小(桶中1的个数,是2的幂)


此时桶必须遵循6条规则:

1、桶的最右部的位置总是1;

2、每个1的位置都在桶内、

3、一个位置只能属于一个桶

4、桶的大小从小到大,相同的桶的个数只有一到r个

5、从远到近扫描,桶的大小不会减少



算法过程,每次流中来1的时候,新建一个大小为1的桶,当相同桶的个数达到r+1个的时候,将最前面两个桶合为一个桶,并把过期的桶删除(时间戳大于当前时间-窗口大小)。当我要输出某时刻当前窗口1的个数,即将最早的桶的大小*50%+后面每个桶的大小。

此时误差:假设最左边桶的大小为2的j次(后面用2j代替吧),真实的至少为1+(r-1)(2的j-1次+2的j-2次+。。。+1)=(r-1)(2j - 1)。

最大误差:  (2的j-1次-1)/(1+(r-1)(2的j次-1))



c语言实现,建立双向循环链表,用来存储桶

#include <iostream>
#include <cstdio>
#include <cstdlib>
#define MaxSize 100010

using namespace std;

typedef struct node
{
    int bsize;
    int btime;
    struct node *next;
    struct node *pior;
}Bucket,*pBucket;

void addItem(pBucket h,int t)                    //添加新的桶
{
    pBucket p;
    p=(pBucket)malloc(sizeof(Bucket));
    p->bsize=1;
    p->btime=t;
    p->next=h;
    p->pior=h->pior;
    h->pior->next=p;
    h->pior=p;

}
void Delete(pBucket h,int t,int size_win)          //删除过期桶
{
    pBucket p;
    while(1)
    {
        p=h->next;
        if(p->btime<(t-size_win))
           {
               h->next=p->next;
               p->next->pior=h;
               free(p);
           }
        else
            break;

    }

}

void Merge(pBucket h,int max_num )          //合并
{
    int i,t,size,same;
    pBucket p,q;
    q=h->pior;
    while(q!=h)
    {
        same=1;
		p=q;
            for(i=1;i<=max_num;i++)
            {
                if(p->pior->bsize!=p->bsize || p->pior==h)
                {
                    same=0;
                    break;

                }
				p=p->pior;
            }
            if(same==1)
            {

                for(i=0;i<max_num;i++)              //找到要合并的桶
                {
                    q=q->pior;
                }
                p=q->next;                      //找到要删除的桶
                t=p->btime;
                size=(p->bsize)*2;
                p->pior->next=p->next;
                p->next->pior=p->pior;
                free(p);

 /*               for(i=1;i<max_num;i++)
                {
                    p=q->pior;
                    p->pior->next=p->next;
                    p->next->pior=p->pior;
                    free(p);

                }

  */
                q->bsize=size;
                q->btime=t;
            }
        else
            break;
    }
}


int Print_estimate(pBucket h,int max_num)
{
    pBucket p;
    int total_num=0;
    p=h->next;
    total_num+=p->bsize*(1.0/max_num);
    printf("size : %d, time:%d\n",p->bsize,p->btime);
    p=p->next;
    while(p!=h)
    {
        printf("size : %d, time:%d\n",p->bsize,p->btime);
        total_num+=p->bsize;
        p=p->next;
    }
    printf("estimate total: %d\n",total_num);
    return total_num;
}
int Prin_real(int window[],int size_win)
{
    int i,num=0;
    for(i=0;i<size_win;i++)
        num+=window[i];
    printf("real total:%d\n",num);
    return num;
}

int main()
{
    FILE *fp;
    int temp;//临时变量,用来记录该时刻的数集,1或0
    int t_now=0,t_need,max_num_buc;
    int window[MaxSize]={0},size_win;
    int est_num,real_num;
    pBucket Buc;
    Buc=(pBucket)malloc(sizeof(Bucket));
    Buc->next=Buc;
    Buc->pior=Buc;              //头指针初始化
    if(!(fp=fopen(".\\01stream.txt","r")))
        printf("FAIL TO OPEN FILE");
    printf("请输入滑动窗口大小:\n");
    scanf("%d",&size_win);
    printf("请输入想获取数据的时间:\n");
    scanf("%d",&t_need);
    printf("请输入精度:\n");
    scanf("%d",&max_num_buc);


    while(fscanf(fp,"%d",&temp)!=EOF && t_need!=t_now)
    {
        window[t_now%size_win]=temp;
        if(temp==1)
            {

                addItem(Buc,t_now);//新建一个桶;
                Delete(Buc,t_now,size_win);
				Merge(Buc,max_num_buc );

            }
        t_now++;
    }
    fclose(fp);
    est_num=Print_estimate(Buc,max_num_buc);
    real_num=Prin_real(window,size_win);
    printf("误差:%f\n",(float)(est_num-real_num)/(float)real_num);

    return 0;
}



猜你喜欢

转载自blog.csdn.net/qq_36834256/article/details/79922869