Apriori关联分析 C++实现

Apriori算法:

如果小的项集比较频繁,那么由它组成的大的项集也可能是频繁的;
如果小的项集不频繁,那么由它组成的大的项集必然不频繁。
所以,可以先排除小的不频繁项集,减少搜索空间。

#include "iostream"
#include "vector"
#include "set"
#include "string"
#include "map"
#include "algorithm"
using namespace std;

//准备数据集
set< set<char> > loadDataSet()
{
    set< set<char> > s;

    char s1[] = {'1', '3', '4'};
    char s2[] = {'2', '3', '5'};
    char s3[] = {'1', '2', '3', '5'};
    char s4[] = {'2', '5'};

    set<char> ss1(s1, s1 + sizeof(s1) / sizeof(char));
    set<char> ss2(s2, s2 + sizeof(s2) / sizeof(char));
    set<char> ss3(s3, s3 + sizeof(s3) / sizeof(char));
    set<char> ss4(s4, s4 + sizeof(s4) / sizeof(char));

    s.insert(ss1);
    s.insert(ss2);
    s.insert(ss3);
    s.insert(ss4);

    return s;
}

//构造长度为1的侯选集
//data为原始数据库
set< set<char> > createC1(set< set<char> > &data)
{
    set< set<char> > C1;
    set<char> s;
    set< set<char> >::iterator it1;
    set<char>::iterator it2;

    for(it1 = data.begin(); it1 != data.end(); it1++)
    {
        for(it2 = (*it1).begin(); it2 != (*it1).end(); it2++)
        {
            s.insert(*it2);
        }
    }

    set<char>::iterator it;
    for(it = s.begin(); it != s.end(); it++)
    {
        set<char> tmp;
        tmp.insert(*it);
        C1.insert(tmp);
    }
    return C1;
}

//从候选集Ck中删除支持度小的项
//data为原始数据库
//Ck为侯选集
//suportData为输出向
set< set<char> > scanD(set< set<char> > &data, set< set<char> > &Ck, double minSupport)
{
    //得到每个候选项的支持量
    int n = data.size();
    map< set<char>, int> ssCnt;
    set< set<char> >::iterator it, it1;
    for(it=Ck.begin(); it != Ck.end(); it++)
        ssCnt[*it] = 0;
    for(it=data.begin(); it != data.end(); it++)
    {
        for(it1=Ck.begin(); it1 != Ck.end(); it1++)
        {
            vector<char> tmp;
            set_difference((*it1).begin(), (*it1).end(), (*it).begin(), (*it).end(), back_inserter(tmp));
            if(tmp.size() == 0)  //如果当前侯选项在dataset[i]中
            {
                ssCnt[(*it1)] += 1;
            }
        }
    }

    //用支持量/原始数据条目数,得到支持度
    set< set<char> > retList;
    map< set<char>, int>::iterator it2;
    for(it2 = ssCnt.begin(); it2 != ssCnt.end(); it2++)
    {
        double sup = (double)(it2->second) / (double)n;  
        if(sup >= minSupport)
        {
            retList.insert(it2->first);
        }
    }
    return retList;
}

//创建Ck,也就是将Lk中的元素组合,得到更大的侯选集Ck,Ck中的每个项长度为k
set< set<char> > aprioriGen(set< set<char> > &Lk, int k)
{
    set< set<char> > retList;
    int lenLk = Lk.size();  
    set< set<char> >::iterator it, it1;
    for(it=Lk.begin(); it != Lk.end(); it++)
    {
        for(it1=it; it1 != Lk.end(); it1++)
        {
            if(it != it1)
            {
                vector<char> tmp;
                set_union((*it).begin(), (*it).end(),(*it1).begin(),(*it1).end(), back_inserter(tmp));
                set<char> L(tmp.begin(), tmp.end());
                retList.insert(L);
            }
        }
    }
    return retList;
}

//输出所有的频繁项集
vector< set< set<char> > > Apriori(set< set<char> > &dataset, double minSupport)
{
    vector< set< set<char> > > L;
    set< set<char> > C1 = createC1(dataset);  //生成长度为1的候选项集
    set< set<char> > L1;
    L1 = scanD(dataset, C1, minSupport);         //生成长度为1的频繁项集
    L.push_back(L1);
    int k = 2;
    while(L[k-2].size() > 0)
    {
        set< set<char> > Ck = aprioriGen(L[k-2], k);          //生成长度为k的候选项集
        set< set<char> > Lk = scanD(dataset, Ck, minSupport); //生成长度为k的频繁项集
        L.push_back(Lk);
        k++;
    }
    return L;
}

int main()
{
    set< set<char> >::iterator it;
    set<char>::iterator it1;
    set< set<char> > data = loadDataSet();
    cout << "原始数据为:\n";
    for(it = data.begin(); it != data.end(); it++)
    {
        for(it1 = (*it).begin(); it1 != (*it).end(); it1++)
            cout << *it1;
        cout << " ";
    }
    cout << endl;

    vector< set< set<char> > > L = Apriori(data, 0.7);
    cout << "支持度为70%的频繁候选项集为:\n";
    for(int k=0; k<L.size(); k++)
    {
        for(it = L[k].begin(); it != L[k].end(); it++)
        {
            for(it1 = (*it).begin(); it1 != (*it).end(); it1++)
                cout << *it1;
            cout << " ";
        }
        cout << endl;
    }

    cout << endl;
    return 0;
}

这里写图片描述

这里写图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值