数据挖掘实验:Apriori算法实现C++

说起来数据挖掘这门课我还是蛮喜欢的,所以实验内容也都是自己实现的,第一个Apriori算法,思想很简单,什么都没有就是暴力,我加了一个Hash,总共也才写了100来行,具体内容代码注释中很清楚我就不多说了。以下附上主要函数的代码(省去部分)。


主要的东西呢就是把所有的事务映射成一个数字然后直接用string存储。好吧我承认我在偷懒,这个方法是有问题的,事务多了之后会出现歧义。会有错误。但是我不想改了hhhh让我当一条咸鱼吧。

#include <cstdio>
#include <iostream>
#include <set>
#include <map>
#include <algorithm>

using namespace std;
const int maxn = 105;///最大记录条数

int n;///记录条数
int min_sup;///最小支持度
bool flag;///产生新集的标记
map<string, int> m;///将项名Hash后存储
map<int, string> mp;///逆Hash
set<int> D[maxn];///事务数据库
set<string> fre;///频繁项集的集合(每个string存储一个频繁项集)
set<string> cand;///候选项集的集合(每个string存储一个候选项集)

char name[maxn];
string t;
int cnt, x;

///利用先验性质的剪枝
bool check(){
    string s;///获取候选项的子集
    for(int i = 0;i < t.size();i ++){
        s = t;
        s.erase(i, 1);
        if(!fre.count(s)) return false;///验证失败
    }
    return true;///验证成功
}

///获取候选项集
void get_cand(int num){
    cand.clear();
    for(set<string>::iterator i = fre.begin();i != fre.end();i ++)
        for(set<string>::iterator j = fre.begin();j != fre.end();j ++){
            t = *i;
            ///去重合并
            for(int k = 0;k < (*j).size();k ++)
                if(t.find((*j)[k]) == string::npos) t += (*j)[k];
            sort(t.begin(), t.end());
            if(t.size() != num) continue;
            if(check()) cand.insert(t);///剪枝
        }
    return;
}

///支持度计数,获取频繁项集
bool get_fre(int num){
    set<string> tfre;
    for(set<string>::iterator i = cand.begin();i != cand.end();i ++){
        t = *i;
        int sum = 0;
        for(int j = 0;j < n;j ++){
            bool f1 = true;
            ///判断是否所有项都存在
            for(int k = 0;k < t.size();k ++)
            if(!D[j].count(t[k] - 48)) {
                f1 = false;
                break;
            }
            if(f1) sum ++;///计数+
        }
        if(sum >= min_sup) tfre.insert(t);///满足最小支持度
    }
    if(tfre.size() == 0) return false;
    fre = tfre;
    return true;
}

int main(){
    //freopen("ap.txt", "r", stdin);

    printf("记录条数:");
    while(~scanf("%d", &n)){
        m.clear();
        cnt = 0;
        for(int i = 0;i < n;i ++){
            scanf("%d", &x);
            while(x --){
                scanf("%s", name);
                t = name;
                //利用Map的Hash部分和插入事务数据库部分省略...
            }
        }
        printf("最小支持度:");
        scanf("%d", &min_sup);

        ///获得频繁1项集
        for(int i = 0;i < cnt;i ++){
            int sum = 0;
            for(int j = 0;j < n;j ++)
                if(D[j].count(i)) sum ++;
            if(sum >= min_sup) {///计数完毕,满足最小支持度
                t = i + 48;
                fre.insert(t);
            }
        }
        flag = true;
        int num = 1;///候选项数
        while(flag){
            flag = false;
            get_cand(++ num);///获取候选项集
            if(get_fre(num))///获取频繁项集,空集返回false
                flag = true;
        }
        printf("最大项数:%d\n", num - 1);
        for(set<string>::iterator i = fre.begin();i != fre.end();i ++){
            printf("{");
            for(int j = 0;j < (*i).size();j ++)
                printf("%s%c", mp[(*i)[j] - 48].c_str(), j + 1 == (*i).size()?'}':',');
            printf("\n");
        }
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值