【算法大致描述】

Aprior算法主要有两个操作,扫描数据库+统计。计算每一阶频繁项集都要扫描一次数据库并且统计出满足支持度的n阶项集。

【算法主要步骤】

一、频繁一项集

算法开始第一步,通过扫描数据库,统计出每条记录中出现的每一个单独项并计数,数据库扫描完成,统计结束,根据支持度,选出满足条件的频繁一项集 L1。

二、连接

用 Lk-1自连接得到Ck。

方法,如果Lk-1中的两个元素的前K-2项都相同,只有最后一项不同,则自连接得到Ck中的一个元素。例如L3{(12,13,14),(12,13,15) }则可自连接得到C4{(12 13 14 15)}

三、修剪

对于自连接得到的Ck,其中有些元素是可以不用扫描数据库就可以确定它肯定不是频繁项集的。一个k-项集,如果它的一个k-1项集(它的子集 )不是频繁的,那它本身也不可能是频繁的。

例如L3{(12 ,13,14),(12,13,15)}自连接得到C4{(12,13,14,15)} 但是(13,14,15)不在L3中,所以可以肯定(12,13,14,15)不是频繁四项集,不用再去扫描数据库。

通过修剪,可以很快的减少Ck中的元素,减少数据库的扫描次数,大大加快效率。

四、扫描数据库得到频繁k项集Lk

将已经修剪过的Ck中的每一个元素拿到数据库中去找,统计出现次数,根据支持度得到结果。

C++源码

#include<bits/stdc++.h>
#include<string>
#include<vector>
#include<map>
using namespace std;
vector <string> result;
map<string,int>r1;
float suport;
vector<string> file;
void Getfile(){
ifstream ifile("D://retail.dat");
if(!ifile){
cout<<"open file error"<<endl;
}
else{
string temp;
while(getline(ifile,temp)){
file.push_back(temp);
}
}
ifile.close();
}
bool IsrealCk(vector<string>& Lk ,vector<string> &str){//判断str的子集是否在Lk-1中
string temp;
int i;
for( i=;i<str.size();i++){
temp.clear();
for(int j=;j<str.size();j++){//Cn 1
if(j!=i){
temp+=str[j];
temp.push_back(',');
}
}//生成一个子集
temp.erase(temp.size()-);
int k;
for( k=;k<Lk.size();k++){//
if(Lk[k]==temp)
break;
}
if(k>=Lk.size()){//不在Lk
break;
} }
if(i>=str.size())
return ;
else
return ;
}
vector<string> minCK(vector<string>& Lk,vector<string>& Ck){//剪枝 (12,45,32)
vector<string> minck;
vector<string> str;
for(int i=;i<Ck.size();i++){
string s;
str.clear();
for(int j=;j<Ck[i].size();j++){
while(Ck[i][j]!=','&&j<Ck[i].size()){
s.push_back(Ck[i][j]);
j++;
}
str.push_back(s);
s.clear();
}
if(IsrealCk(Lk,str)){
minck.push_back(Ck[i]);
}
}
return minck;
}
vector<string> GetL1_C2(){
vector <string> L1;
vector<int> count;
vector<string> l1;
vector<string> C2;
string temp;
int line=;
string lk;
for(int f=;f<file.size();f++){
temp=file[f];
line++;
int i;
for( i=;i<temp.size();i++){
while(temp[i]!=' '&&temp[i]!='\n'&&i!=temp.size()){
lk+=temp[i];
i++;
}
if(r1.find(lk)!=r1.end())
r1[lk]++;
else
r1[lk]=;
lk.clear();//
}
}
temp.clear();
map<string,int>::iterator it;
for(it=r1.begin();it!=r1.end();it++){//待删除
if(it->second>=ceil(suport*line)){
cout<<it->first<<" ("<<it->second<<")"<<endl;
result.push_back(it->first); }
}
for(int i=;i<result.size();i++){
for(int j=i+;j<result.size();j++){
string c2=result[i]+","+result[j];
C2.push_back(c2);
}
}
return C2;
}
vector<string> CK(vector<string>& L){
vector<string> Ck;//k+1候选像集
vector<string> minck;
for(int i=;i<L.size();i++){
for(int j=i+;j<L.size();j++){
if(i!=j){
string temp1,temp2;
int m1,m2;
for(m1=L[i].size()-;m1>;m1--){
if(L[i][m1]==',')
break;
}
temp1=L[i].substr(,m1+);
for(m2=L[j].size()-;m2>;m2--){
if(L[j][m2]==',')
break;
}
temp2=L[j].substr(,m2+);
if(temp1==temp2){//可以连接
string lk=temp1;
for(int x=m1+;x<L[i].size();x++) {
lk.push_back(L[i][x]);
}
lk.insert(lk.end(),',');
for(int x=m2+;x<L[j].size();x++) {
lk.push_back(L[j][x]);
}
Ck.push_back(lk);//加入候选项
}
}
}
}
// minck=minCK(L,Ck);
return minck=minCK(L,Ck);
} bool Isin(string& temp,string& str){
int j;
string s;
for( j=;j<temp.size();j++){//遍历temp
while(temp[j]!=' '&&j<temp.size()){
s.push_back(temp[j]);
j++;
}
if(s==str)
break;
s.clear();
}
if(j>=temp.size())
return ;
else
return ; }
vector<string> GetLk(vector<string>& Ck){
map<string,int> Lk;
string temp;
int flag=;
int line=;
for(int f=;f<file.size();f++){
temp=file[f];
line++;int t=;
vector<string> str;
for(int i=;i<Ck.size();i++){
string s;//记录单个元素 12,32 s=12
str.clear();
for( int j=;j<Ck[i].size();j++){//遍历 12,34
while(Ck[i][j]!=','&&j<Ck[i].size()){
s.push_back(Ck[i][j]);
j++;
}
str.push_back(s);
s.clear();
} int p;
for( p=;p<str.size();p++){
if(!Isin(temp,str[p]))
break;
}
if(p>=str.size()){//在temp中出现
if(Lk.find(Ck[i])!=Lk.end())
Lk[Ck[i]]++;
else
Lk[Ck[i]]=;
}
} }
/*********/
temp.clear();
vector<string> ck;
map<string,int>::iterator it;
for( it=Lk.begin();it!=Lk.end();it++){//待删除
if(it->second>=ceil(suport*line)){
ck.push_back(it->first);
}
}
return ck; }
void Apri(vector<string>& Ck){
if(Ck.size()<){
return ;
}
else{
vector<string> temp=GetLk(Ck);
if(temp.size()<)
return;
else{
for(int i=;i<temp.size();i++){
result.push_back(temp[i]);//记录Lk
}
vector<string>nextck= CK(temp);
Apri(nextck); }
}
}
int main(){
cout<<"请输入最小支持度"<<endl;
cin>>suport;
Getfile();
int c=;
vector<string> C2=GetL1_C2();
Apri(C2);
cout<<"频繁项集如下:"<<endl;
for(int i=;i<result.size();i++){
cout<<result[i]<<endl;
c++;
}
cout<<" count "<<c<<endl;
return ;
}

测试文件(有八万多条记录,测试代码建议跑0.1支持度)

https://pan.baidu.com/s/1Lp7LJOXksIRh3KBra2iVIw

数据挖掘Aprior算法详解及c++源码的更多相关文章

  1. 《Android NFC 开发实战详解 》简介+源码+样章+勘误ING

    <Android NFC 开发实战详解>简介+源码+样章+勘误ING SkySeraph Mar. 14th  2014 Email:skyseraph00@163.com 更多精彩请直接 ...

  2. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  3. Android事件传递机制详解及最新源码分析——ViewGroup篇

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 在上一篇<Android事件传递机制详解及最新源码分析--View篇>中,详细讲解了View事件的传递机制,没掌握或者掌握不扎实的小伙伴 ...

  4. 【详解】ThreadPoolExecutor源码阅读(三)

    系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) 线程数量的 ...

  5. 【详解】ThreadPoolExecutor源码阅读(二)

    系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) AQS在W ...

  6. 【详解】ThreadPoolExecutor源码阅读(一)

    系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) 工作原理简 ...

  7. SpringBoot Profile使用详解及配置源码解析

    在实践的过程中我们经常会遇到不同的环境需要不同配置文件的情况,如果每换一个环境重新修改配置文件或重新打包一次会比较麻烦,Spring Boot为此提供了Profile配置来解决此问题. Profile ...

  8. Python开发技术详解(视频+源码+文档)

    Python, 是一种面向对象.直译式计算机程序设计语言.Python语法简捷而清晰,具有丰富和强大的类库.它常被昵称为胶水语言,它能够很轻松的把用其他语言制作的各种模块(尤其是C/C++)轻松地联结 ...

  9. Android 网络框架之Retrofit2使用详解及从源码中解析原理

    就目前来说Retrofit2使用的已相当的广泛,那么我们先来了解下两个问题: 1 . 什么是Retrofit? Retrofit是针对于Android/Java的.基于okHttp的.一种轻量级且安全 ...

随机推荐

  1. java.lang.String中的replace方法到底替换了一个还是全部替换了。

    你没有看错我说的就是那个最常用的java.lang.String,String可以说在Java中使用量最广泛的类了. 但是我却发现我弄错了他的一个API(也可以说是两个API),这个API是关于字符串 ...

  2. VPS性能测试:CPU内存,硬盘IO读写,带宽速度,UnixBench和压力测试

    现在便宜的VPS主机越来越多了,一些美国的VPS主机甚至给出1美元一月的VPS,堪比虚拟主机还要便宜,巨大的价格优势吸引不少人购买和使用,而近些年来国内的主机商也开始意识到便宜的VPS对草根站长的诱惑 ...

  3. Struts1.3——登录案例的改进

    在上篇写的用户登录验证案例的基础上进一步改进. 1.在登录成功后的welcome.jsp页面显示登录成功的用户名 思路1:在LoginAction中,将username放入request的域对象中 因 ...

  4. Java内部类成员

    内部类可以访问其所有实例成员,实例字段和其封闭类的实例方法.参考如下实例 - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 2 ...

  5. 【小程序】获取到的e.target与e.currentTarget区别

    [小程序]获取到的e.target与e.currentTarget区别:https://blog.csdn.net/qq_33744228/article/details/80310294 使用e.t ...

  6. USACO 2014 US Open Fair Photography /// 技巧

    题目大意: 给定n头奶牛 给定n头奶头所在位置和品种 品种只有G H两种 求一段区间的长度 要求区间内包含的品种满足各品种的数量相同 将一个品种的值设为1 另一个设为-1 假设 i<j 而 1~ ...

  7. 多线程实现奇偶统计v1 - 暴力版

    #include <stdio.h> #include <stdlib.h> #include <time.h> #include "pthread.h& ...

  8. 循序渐进学.Net Core Web Api开发系列【17】:.Net core自动作业之Hangfire

    nuget搜索:Hangfire 安装即可,这里我选择的是 1.7.0-beta1 版本 我是用这个集成到了 mvc api里 这里需要在 Startup 文件里进行如下配置 在配置方法 Config ...

  9. 2018-8-10-win10-uwp-json

    title author date CreateTime categories win10 uwp json lindexi 2018-08-10 19:16:53 +0800 2018-2-13 1 ...

  10. JavaScript常用技巧之时间操作

    1.获取当前时间戳 +new Date Date.parse(new Date())