您的位置:首页 > 编程语言 > C语言/C++

数据挖掘之Apriori算法c++实现

2017-10-22 08:39 645 查看
鉴于过程网上都有 ,这里就不再赘述详细过程,只说一下思路。

既然要用到集合,那么就可以考虑用容器存储(可以排序的那种)。

用以这里想到用 map<set<int> ,int> 来存k项集 具体实现请看代码 其实很容易理解的

我们老师给了88000+的数据记录,然后只能用文件去读,按照支持度。

大概跑以下的支持度的运行时间是这么多 但是要说下我的破电脑的运算速度。。。2.2Ghz。可能去游戏本跑可以更快

百分比    出现记录次数    时间

4.5%    4000           3s
2%      1760           15s
1.7%    1500           22s
1.1%    1000           97s
1%      800


#include<bits/stdc++.h>
using namespace std;
char d[90000][110];//读取数据记录 数据库
map <set<int>,int> m_f[30],m_op;//存储 频繁集
set <set<int> > m_d,m_dcopy;//存储 候选集
set <set<int> > ::iterator m_d_iter;
map <set<int>,int> ::iterator m_iter1,m_iter2;
set<int> one_set;//一项频繁集的容器
set<int> ::iterator one_set_iter;
int n=88162;//n条记录
int min_t = 1760;//最小支持度
/*
4.5% 4000 3s
2%   1760 15s
1.7% 1500 22s
1.1% 1000 97s
1%   800
*/
void init()
{
//	scanf("请输入记录数: %d",&n);

scanf("请输入数据记录:\n");
for(int i=1;i<=n;i++)
gets(d[i]);
}
void Apriori()
{
//遍历一遍数据库
map<int ,int> one_f;//一层频繁集
map<int ,int> ::iterator one_f_iter;
one_f.clear();
for(int i=1;i<=n;i++)
{
int len = strlen(d[i]);//每条记录的长度
int j = 0;
while(j< len)
{
if(d[i][j] == ' ')//是空格 跳过
{
j++;continue;
}
else
{
//计算数值
int value = 0;
while(d[i][j]!=' ')//直到出现空格或者结束为止
{
//开始 字符转数字
int x = 0;
x = d[i][j]-'0';
value = value * 10 + x;
j++;
if(j==len)
break;
}
one_f[value] ++;//记录次数
}
}
}
for(one_f_iter = one_f.begin();one_f_iter != one_f.end();)
{
if(one_f_iter->second<min_t)//删除
one_f.erase(one_f_iter++);
else
one_f_iter++;
}

m_op.clear();
cout<<"频繁一项集: "<<endl;
for(one_f_iter = one_f.begin();one_f_iter != one_f.end();one_f_iter++)
{
one_set.clear();
one_set.insert(one_f_iter->first);
m_op[one_set] = one_f_iter->second;
cout<<"{"<<*one_set.begin()<<"}  ";
//		cout<<" 出现次数: "<<m_op[one_set]<<endl;//频繁一项集合
}
cout<<endl;
m_f[1] = m_op;//一项集存储完成;
for(int i=1;m_f[i].size()!=0;i++)
{
m_op = m_f[i];//取出i项集
//接下来就是求解i+1项 候选集
/*
1. 先找出所有能俩俩连接的
*/
m_d.clear();//存候选集
for(m_iter1 = m_op.begin();m_iter1!=m_op.end();m_iter1++)
{
for(m_iter2 = m_op.begin();m_iter2!=m_op.end();m_iter2++)
{
if(m_iter1==m_iter2)
continue;//不找重复的
//判断是否可以俩俩相连
set<int> x_set,y_set;//
set<int> ::iterator x_iter,y_iter;
x_set = m_iter1->first ;//把其中一个复制过去 然后再把第二个插进去 判断长度是否只加了一
y_set = m_iter2->first ;
for(x_iter=x_set.begin();x_iter!=x_set.end();x_iter++)//x插入y中
y_set.insert(*x_iter);
if(y_set.size()==1+x_set.size())//说明俩俩可以连接
{
//开始对y剪枝  子集判断
//先找出子集 判断是否是频繁集
int flag = 0;
for(y_iter=y_set.begin();y_iter!=y_set.end();y_iter++)
{
x_set = y_set;
x_set.erase(*y_iter);//每次删掉当前的位置值
if(m_f[i].find(x_set)==m_f[i].end())//任意一个子集不在频繁集里面
{
flag = 1;
break;
}
}
if(flag==0)//是候选集
m_d.insert(y_set);
}
}
}
//对候选集m_d遍历数据库
m_dcopy = m_d;//复制一份候选集
m_op.clear();
for(int i1=1;i1<=n;i1++)//每遍历一条记录
{
//每条记录存 在map中
map<int ,int> mmp;
mmp.clear();
int len = strlen(d[i1]);
int j = 0;
while(j<len)//每条记录
{
//每次读取一个数
if(d[i1][j]==' ')
{
j++;continue;
}
int value = 0;
while(j<len&&d[i1][j]!=' ')
{
value = value*10 + d[i1][j] -'0';
j++;
}
mmp[value] = 1;
}
for(m_d_iter = m_d.begin();m_d_iter!=m_d.end();m_d_iter++)
{
int flag = 0;
set<int> x_set = *m_d_iter;//
set<int> ::iterator x_iter;
for(x_iter = x_set.begin();x_iter!=x_set.end();x_iter++)
{
if(mmp.find(*x_iter)==mmp.end())//没找到
{
flag = 1;
break;
}
}
if(flag ==0)//全部都在
m_op[x_set] ++;//记录加一
}
}
//删除支持度不满足的
for(m_iter1 = m_op.begin();m_iter1!=m_op.end();)
{
if(m_iter1->second<min_t)
m_op.erase(m_iter1++);
else
m_iter1++;
}
m_f[i+1] = m_op;
cout<<"频繁"<<i+1<<"项集: "<<endl;
for(m_iter1 = m_op.begin();m_iter1!=m_op.end();m_iter1++)
{
set<int> x_set = m_iter1->first;//
set<int> ::iterator x_iter;
cout<<"{";
for(x_iter = x_set.begin();x_iter!=x_set.end();x_iter++)
if(x_iter==x_set.begin())
cout<<*x_iter;
else
cout<<","<<*x_iter;
cout<<"}  ";

//			cout<<"次数: "<<m_iter1->second<<endl;
}
cout<<endl;
}
}
int main()
{
freopen("1.txt","r",stdin);
init();
Apriori();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: