Apriori算法的C++实现

#include<bits/stdc++.h>
using namespace std;

/*
1.若X为频繁项目集,则X的所有子集都是频繁项目集
2.若X为非频繁项目集,则X的所有超集均为非频繁项目集
*/
int min_sup;//最小支持度
vector<set<string> > item;//存储最开始的事务及其项
map<set<string>, int> k_item;//频繁k项集
map<set<string>, int> houxuan;//候选
void pri_k_item(map<set<string>, int> k_i);

//用户输入事务
void getItem(){
    int itemSize;
    cout<<"请输入事务的数目"<<endl;
    cin>>itemSize;
    for(int i = 0; i < itemSize; i++){
        cout<<"请输入第"<<i + 1<<"个事务(输入#表示事务输入结束)"<<endl;
        string everyItem;
        set<string> everyItems;
        while(cin>>everyItem && everyItem != "#"){
            everyItems.insert(everyItem);
        }
        item.push_back(everyItems);
    }
}
//找出频繁1项集
void find_frequent_1(){
    map<string, int> zan;
    map<string, int>::iterator it;
    //候选1项集
    for(int i = 0; i < item.size(); i++){
        set<string>::iterator itemi = item[i].begin();
        for(itemi = item[i].begin(); itemi != item[i].end(); itemi++){
            if(zan.find(*itemi) != zan.end()){
                zan[*itemi]++;
            }else{
                zan[*itemi] = 1;
            }
        }
    }
    //频繁1项集
    for(it = zan.begin(); it != zan.end(); it++){
        if(it->second >= min_sup){
            set<string> e;
            e.insert(it->first);
            k_item[e] = it->second;
        }
    }

}
/*频繁项集**连接**得到候选项集合
返回1得到k+1候选项
返回0不能得到k+1候选项
*/
bool apriori_gen(int k){
    houxuan.clear();
    map<set<string>, int>::iterator i;
    map<set<string>, int>::iterator j;
    for(i = k_item.begin(); i != k_item.end(); i++){
        set<string> A = i->first;
        for(j = i; j != k_item.end(); j++){
            set<string> B = j->first;
            set<string> C;
            set_union(A.begin(), A.end(), B.begin(), B.end(), inserter(C, C.begin()));
            if(C.size() == k + 1){
                houxuan[C] = 0;
            }
        }
    }
    return houxuan.size() > 0;
}
/*剪枝得到频繁项集
返回1得到k+1候选项
返回0不能得到k+1候选项
*/
bool has_infrequent_sub(int k){
    map<set<string>, int>::iterator i;
    map<set<string>, int>::iterator j;
    map<set<string>, int> zank = houxuan;
    //判断候选项的子集是否频繁
    for(i = houxuan.begin(); i != houxuan.end(); i++){
        set<string> A = i->first;
        set<string>::iterator ii;
        for(ii = A.begin(); ii != A.end(); ii++){
            set<string> B = i->first;
            B.erase(*ii);//B是A的k项子集
            if(k_item.find(B) == k_item.end()){//子集非频繁,则剪枝
                zank.erase(i->first);
                break;
            }
        }
    }
    houxuan = zank;
    zank.clear();
    //扫描原数据,统计候选集的支持度
    for(i = houxuan.begin(); i != houxuan.end(); i++){
        set<string> A = i->first;
        int sum = 0;
        for(int j = 0; j < item.size(); j++){
            set<string> B = item[j];
            set<string> C;
            set_difference(A.begin(), A.end(), B.begin(), B.end(), inserter(C, C.begin()));
            if(C.size() == 0){
                sum++;
            }
        }
        if(sum >= min_sup){
            zank[A] = sum;
        }
    }
    if(zank.size() > 0){
        k_item.clear();
        k_item = zank;
        return 1;
    }
    return 0;
}
//输出频繁K项集
void pri_k_item(map<set<string>, int> k_i){
    cout<<"**********************************"<<endl;
    map<set<string>, int>::iterator it;
    for(it = k_i.begin(); it != k_i.end(); it++){
        set<string> e = it->first;
        set<string>::iterator ite;
        for(ite = e.begin(); ite != e.end(); ite++){
            cout<<*ite<<" ";
        }
        cout<<it->second<<endl;
    }
    cout<<"**********************************"<<endl;
}

int main(){
    cout<<"请输入最小支持度阈值"<<endl;
    cin>>min_sup;
    //输入事务
    getItem();
    //找1项频繁项集
    find_frequent_1();
    pri_k_item(k_item);
    int k = 0;
    while(true){
        k++;
        if(!apriori_gen(k)){
            break;
        }
        cout<<"候选"<<endl;
        pri_k_item(houxuan);
        if(!has_infrequent_sub(k)){

            break;
        }
        cout<<"频繁"<<endl;
        pri_k_item(k_item);
    }
    cout<<"最终结果"<<endl;
    pri_k_item(k_item);
}

样例:

请输入最小支持度阈值
2
请输入事务的数目
4
请输入第1个事务(输入#表示事务输入结束)
A C D #
请输入第2个事务(输入#表示事务输入结束)
B C E #
请输入第3个事务(输入#表示事务输入结束)
A B C E #


运行结果
这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值