apriori算法

#include<cstdio>
#include<algorithm>
using namespace std;
int n,k=1,maxi;
double mins;//最小支持度 
int d[15][15];//交易数据集 
struct item//项集类型 
{
    int cnt;//元素的个数 
    int a[15];//项集内的元素 
    double s;//支持度 
};
struct tab//列表类型 
{
    int cnt;//项集的个数 
    item it[1005];
}c[15],l[15];
int sia(int di,int x)//在第di个事务中寻找项集的一个单元素子集 
{
    for(int i=1;i<=d[di][0];i++)
    {
        if(d[di][i]==x) return 1;
    }
    return 0;
}
double si(item x)//在d中寻找任意一个项集出现的次数 
{
    double s=0;
    for(int i=1;i<=n;i++)
    {
        int flg=1;
        for(int j=1;j<=x.cnt;j++)
        {
            if(!sia(i,x.a[j])) flg=0; 
        }
        if(flg) s=s+1;
    }
    return s;
}
item link(item x,item y)//连接两个项集生成一个新的项集 
{
    item re;
    re.cnt=x.cnt+y.cnt;
    for(int i=1;i<=x.cnt;i++) re.a[i]=x.a[i];
    for(int i=1+x.cnt;i<=x.cnt+y.cnt;i++) re.a[i]=y.a[i-x.cnt];
    sort(re.a+1,re.a+x.cnt+y.cnt+1);//通过排序去除重复的元素 
    for(int i=1;i<re.cnt;i++)
    {
        if(re.a[i]==re.a[i+1])
        {
            for(int j=i+1;j<re.cnt;j++) re.a[j]=re.a[j+1];
            re.cnt--;
        }
    }
    re.s=si(re)/n;
    return re;
}
void cre(int x)//c[k]->l[k]
{
    for(int i=1;i<=c[x].cnt;i++)
    {
        if(c[x].it[i].s>=mins)
        {
            l[x].cnt++;
            l[x].it[l[x].cnt]=c[x].it[i];
            
        }
    }
    if(!l[x].cnt ) return;
    printf("第%d次迭代产生%d个频繁集:\n",k,l[x].cnt);
    for(int i=1;i<=l[x].cnt;i++)
    {
        for(int j=1;j<=l[x].it[i].cnt;j++) printf("%d ",l[x].it[i].a[j]);
        printf("\n");
    }
    printf("\n");
    return;
}
int ex(item t)//项集是否存在 
{
    int flg=0;//是否有重复的项集 
    for(int i=1;i<=c[k].cnt;i++)
    {
        int tf=1;//和第i个项集是否不同 
        for(int j=1;j<=t.cnt;j++)
        {
            if(t.a[j]!=c[k].it[i].a[j]) tf=0;//两个项集每一位都相同 
        }
        if(tf) flg=1;//有重复的项集
    }
    return flg;
}
int main()
{
    scanf("%lf",&mins);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int cnt=0,x;
        while(1)
        {
            scanf("%d",&x);
            if(x==-1) break;//输入-1代表事务结束 
            d[i][0]++;//d[i][0]表示第i个事务的商品数 
            d[i][d[i][0]]=x;
            if(x>maxi) maxi=x;//maxi表示不同的元素种类 
        }
    }
    for(int i=1;i<=maxi;i++)//生成初始的候选集c[1] 
    {
        double cnt=0;
        for(int j=1;j<=n;j++)
        {
            for(int p=1;p<=d[j][0];p++)
            {
                if(d[j][p]==i) cnt=cnt+1;
            }
        }
        c[1].it[i].s=0;
        c[1].it[i].a[1]=i;
        c[1].it[i].cnt=1;
        c[1].it[i].s=cnt/n;
        c[1].cnt++;
    }
    cre(1);
    while(k)//l[k-1]->c[k]
    {
        ++k;
        for(int i=1;i<l[k-1].cnt;i++)
        {
            for(int j=i+1;j<=l[k-1].cnt;j++)
            {
                item t=link(l[k-1].it[i],l[k-1].it[j]);
                if(t.cnt==k)
                {
                    if(ex(t)) continue;//去重
                    c[k].cnt++;
                    c[k].it[c[k].cnt]=t;
                }
            }
        }
        cre(k);
        if(!l[k].cnt) break;
    }
    return 0;
}
/*
样例数据 
0.2
9
1 2 5 -1
2 4 -1
2 3 -1
1 2 4 -1
1 3 -1
2 3 -1
1 3 -1
1 2 3 5 -1
1 2 3 -1
*/

 

posted @ 2022-05-27 20:14  Excim  阅读(44)  评论(0编辑  收藏  举报