现在的位置: 首页 > 综合 > 正文

Aprior算法的实现

2018年03月20日 ⁄ 综合 ⁄ 共 6340字 ⁄ 字号 评论关闭

        终于把Aprior的算法过程看懂了,Aprior算法的原理其实很简单,但是当真正写起代码来还是比较麻烦,在百度文库了,下了一个C++版的Aprior算法,用来研究。

       算法思想:1,先对样本数据,用二维数组保存。2,找一元频繁集,先遍历一下样本数组,保存成一列的形式cur[n][],然后再扫描那一列,提取不重复元素保存起来curL1[][],再次遍历样本列,把每个不重复元素的个数记录下来,也就是CountL1[],3找二元频繁集,for循环数组,对每一行分析:对其中元素进行排列组成成2元形式,进行保存cur[n][],提取不重复元素保存起来curL2[][],再次遍历样本列,把每个不重复元素的个数记录下来,也就是CountL2[],3,三元,四元类似分析.....4,关联规则:先是通过支持度删选,对于已经满足条件的三元数据进行分析,对三元数据求其真子集,然后对子集中长度为1,和长度为2的组合求其置信率;5,最后对其进行筛选。

算法源码:(参考别人的代码)

//支持度不小于2,置信度不小于0.8
#include "stdio.h"
#include "iostream.h"
#include "string.h"
//定义全局变量
char curL1[20][2];//实现出现的一维子集
int countL1[10];//找到各一维频繁子集出现的次数。

char curL2[20][3];  //出现的二维子集
int countL2[10];    //各二维频繁子集出现的次数

char curL3[20][4];  //出现的三维子集
int countL3[10];    //各三维频繁子集出现的次数

char cur[50][4];//临时二维数组,用于保存中间产生的变量
//定义int SizeStr(char* m) 得到字符串的长度。实现代码如下:
int SizeStr(char* m)
{
	int i=0;
	while(*(m+i)!=0)
	{
		i++;
	}
	return i;
}
//比较两个字符串,如果相等返回true,否则返回false
bool OpD(char* x,char* y)
{
	int i=0;
	if(SizeStr(x)==SizeStr(y))
	{
		while(*(x+i)==*(y+i))
		{
			i++;
			if(*(x+i)==0 && *(y+i)==0)
				return true;
		}
	}
	return false;
}
//通过void LoadItemL1(char **p) 得到所有1元的字串和各自出现的次数
void LoadItemL1(char **p)//p二维指针保存二维样本数组
{
	int i,j,n=0,k=0;
	char ch;
	char* s;
	int f;
	memset(cur,0,sizeof(cur));
	for(i=0;i<20;i++)
	{
		curL1[i][0]=0;
		curL1[i][1]=0;
	}
	for(j=0;j<10;j++)
		countL1[j]=0;
	//将样本数组中的数值提取出来,保存在cur[n][0]中,相当于把所有样本保存成一列;
	for(i=0;i<10;i++)
	{
		for(j=0;j<4;j++)
		{
			ch=*(*(p+i)+j);
			if(ch==0)
				break;
			cur[n][0]=ch;
			//printf("%c",cur[n][0]);
			n++;
			
		}
	}
//	printf("\n");
	curL1[0][0]=cur[0][0];
	curL1[0][1]=cur[0][1];
	k=0;
	//放篮子:将cur[n][0]中数据不重复的放入curL1中
	for(i=0;i<50;i++)
	{
		if(cur[i]==0)
			break;
		s=cur[i];
		f=1;
		for(j=0;j<=k;j++)
		{
			if(OpD(s,curL1[j]))//与已经放入curL1集合的字符做比较
			{
				f=0;
				break;
			}
		}
		if(f==1)
		{
			++k;
			curL1[k][0]=cur[i][0];
			curL1[k][1]=cur[i][1];
		}
	}
	//for(i=0;i<=k;i++)
	//{
	//	printf("%c",curL1[i][0]);
	//}
	//printf("\n");
	//curL1[]已经把数提取出来,根据curL1[]值查找cur[n][],对比,计数(就是支持度)
	for(i=0;i<20;i++)
	{
		for(j=0;j<50;j++)
		{
			char* m;
			m=curL1[i];
			if(*m==0)
				break;
			if(OpD(m,cur[j]))
				countL1[i]++;
		}
	}
	printf("L1: \n ");
	printf("项集   支持度计数\n");
	for(i=0;i<10;i++)
	{
		if(curL1[i]==0)
			break;
		if(countL1[i]>=2)
			printf("{I%s}:       %d\n",curL1[i],countL1[i]);
	}
}
//通过void SubItem2(char **p) 得到所有的2元子串
void SubItem2(char **p)
{
	int i,j,k,n=0;
	char* s;
	memset(cur,0,sizeof(cur));
	for(i=0;i<20;i++)
	{
		curL2[i][0]=0;
		curL2[i][1]=0;
		curL2[i][2]=0;
	}
	for(i=0;i<10;i++)
		countL2[i]=0;
	for(k=0;k<10;k++)
	{
		s=*(p+k);
		if(SizeStr(s)<2)
			continue;//如果字符串长度小于2,跳出本次循环
		//每个事务的ID都进行组合,例如1,2,5可以形成:12(cur[0]),15(cur[1]),25(cur[2])
		//提取二元,就需要二层循环,三元,则三层循环
		for(i=0;i<SizeStr(s);i++)
		{
			for(j=i+1;j<SizeStr(s);j++)
			{
				if(*(s+j)==0)
					break;
				*(cur[n]+0)=*(s+i);
				*(cur[n]+1)=*(s+j);
				*(cur[n]+2)=0;
				*(cur[n]+3)=0;
				printf("%c%c\n",*(cur[n]+0),*(cur[n]+1));
				n++;
			}
		}
	}
	//结果得到的cur[][]数组是排列组合项,里面有很多重复项
	
}
//通过void LoadItemL2(char **p) 得到各个2元频繁子串出现的次数
void LoadItemL2(char **p)
{
	int k,i,j;
	char* s;
	int f;
	SubItem2(p);
	//curL2就相当于一个篮子(集合),先把12组合放进去
	curL2[0][0]=cur[0][0];
	curL2[0][1]=cur[0][1];
	curL2[0][2]=cur[0][2];
	k=0;
	for(i=0;i<50;i++)
	{
		if(cur[i]==0)
			break;
		s=cur[i];
		f=1;
		for(j=0;j<=k;j++)
		{
			if(OpD(s,curL2[j]))
			{
				f=0;
				break;
			}
		}
		if(f==1)
		{
			++k;
			curL2[k][0]=cur[i][0];
			curL2[k][1]=cur[i][1];
			curL2[k][2]=cur[i][2];
		}
	}	//将cur[][]精简就得到curL2[][],里面没有重复的二元元素
	for(i=0;i<20;i++)
	{
		for(j=0;j<50;j++)
		{
			s=curL2[i];
			if(*s==0)
				break;
			if(OpD(s,cur[j]))
				countL2[i]++;
		}
	}
	printf("L2: \n");
	printf("项集       支持度计数\n");
	for(i=0;i<10;i++)
	{
		if(curL2[i]==0)
			break;
		if(countL2[i]>=2)
			printf("{I%c,I%c}:       %d\n",curL2[i][0],curL2[i][1],countL2[i]);
	}
}
//通过定义void SubItem3(char **p) 得到所有3元的子串
void SubItem3(char **p)
{
	char *s;
	int i,j,h,m;
	int n=0;
	memset(cur,0,sizeof(cur));
	for(j=0;j<20;j++)
	{
		curL3[j][0]=0;
		curL3[j][1]=0;
		curL3[j][2]=0;
		curL3[j][3]=0;
	}
	for(i=0;i<10;i++)
		countL3[i]=0;
	for(m=0;m<10;m++)
	{
		s=*(p+m);
		if(SizeStr(s)<3)
			continue;
		for(i=0;i<SizeStr(s);i++)
		{
			for(j=i+1;j<SizeStr(s);j++)
			{
				for(h=j+1;h<SizeStr(s);h++)
				{
					if(*(s+h)==0)
						break;
					*(cur[n]+0)=*(s+i);
					*(cur[n]+1)=*(s+j);
					*(cur[n]+2)=*(s+h);
					*(cur[n]+3)=0;
					n++;
				}
			}
		}
	}
	
}
//⑨同样我们要得到得到各个3元频繁子串出现的次数
void LoadItemL3(char** p)
{
	int k,i,j;
	char* s;
	int f;
	SubItem3(p);
	curL3[0][0]=cur[0][0];
	curL3[0][1]=cur[0][1];
	curL3[0][2]=cur[0][2];
	curL3[0][3]=cur[0][3];
	k=0;
	for(i=0;i<50;i++)
	{
		if(cur[i]==0)
			break;
		s=cur[i];
		f=1;
		for(j=0;j<=k;j++)
		{
			if(OpD(s,curL3[j]))
			{
				f=0;
				break;
			}
		}
		if(f==1)
		{
			++k;
			curL3[k][0]=cur[i][0];
			curL3[k][1]=cur[i][1];
			curL3[k][2]=cur[i][2];
			curL3[k][3]=cur[i][3];
		}
	}
	for(i=0;i<20;i++)
		for(j=0;j<50;j++)
		{
			s=curL3[i];
			if(*s==0)
				break;
			if(OpD(s,cur[j]))
				countL3[i]++;
		}
		printf("L3: \n");
		printf("项集          支持度计数\n");
		for(i=0;i<10;i++)
		{
			if(curL3[i]==0)
				break;
			if(countL3[i]>=2)
				printf("{I%c,I%c,I%c}:       %d\n",curL3[i][0],curL3[i][1],curL3[i][2],countL3[i]);
		}
}
//⑩定义void LoadItemL4(char** p) 得到各个3元子串出现的次数
void LoadItemL4(char** p)
{
	int i;
	char* s;
	int j=0;
	for(i=0;i<10;i++)
	{
		s=*(p+i);
		if(SizeStr(s)==4)
			j++;
	}
	printf("四维子集出现的次数:  %d\n",j);
	printf("没有四维的频繁子集,算法结束! \n");
}
//11通过void Support(char* w,int g) 得到关联规则,并输出结果
void Support(char* w,int g)
{
	printf("Support\n");
	int i,j,k,n=0;
	char* s;
	float c=0.8,d=0;
	memset(cur,0,sizeof(cur));
	s=w;
	for(i=0;i<SizeStr(s);i++)
	{
		*(cur[n]+0)=*(s+i);//cur[0][0]=1;cur[1][0]=2;cur[2][0]=5;
		*(cur[n]+1)=0;
		*(cur[n]+2)=0;
		*(cur[n]+3)=0;
		n++;
	}
	for(i=0;i<SizeStr(s);i++)
	{
		for(j=i+1;j<SizeStr(s);j++)
		{
			if(*(s+j)==0)
				break;
			*(cur[n]+0)=*(s+i);//cur[3][0]=1;cur[3][1]=2;cur[4][0]=1;cur[4][1]=5;cur[5][0]=2;cur[5][1]=5;
			*(cur[n]+1)=*(s+j);
			*(cur[n]+2)=0;
			*(cur[n]+3)=0;
			n++;
		}
	}
	for(i=0;i<10;i++)
	{
		if(SizeStr(cur[i])==1)//字符串长度为1
		{
			for(j=0;j<10;j++)
			{
				if(OpD(cur[i],curL1[j]))
				{
					d=countL3[g]/(float)countL1[j];
					//if(d>=c)
					printf("{I%s}:    %f\n",curL1[i],d);
					//break;
				}
			}
		}
		if(SizeStr(cur[i])==2)//字符串长度为2
		{
			for(j=0;j<10;j++)
			{
				if(OpD(cur[i],curL2[j]))
				{
					d=countL3[g]/(float)countL2[j];
					if(d>=c)
						printf("{I%c,I%c}:    %f \n",curL2[j][0],curL2[j][1],d);
					break;
				}
			}
		}
	}
}

//12最后通过main函数完成整过程序
int main()
{
	int i=0,j=0,k;
	char buf[10][6];//保存样本
	char* p[10];//等价于buf[10][6],自己换成了数组指针的形式
	memset(buf,0,sizeof(buf));//申请内存空间
	/*FILE* fp=fopen("date.txt","r");
	if(fp==NULL)
	return 0;
	ch=fgetc(fp);
	while(ch!=EOF)
	{
	printf("adf");
	if(ch==0xa || ch==0xd)
	{
	i++;
	ch=fgetc(fp);
	j=0;
	continue;
	}
	buf[i][j]=ch;
	j++;
	ch=fgetc(fp);
	}*/
	buf[0][0]='1';
	buf[0][1]='2';
	buf[0][2]='5';
	buf[1][0]='1';
	buf[1][1]='2';
	buf[2][0]='2';
	buf[2][1]='4';
	buf[3][0]='1';
	buf[3][1]='2';
	buf[3][2]='4';
	buf[4][0]='1';
	buf[4][1]='3';
	buf[5][0]='1';
	buf[5][1]='2';
	buf[5][2]='3';
	buf[5][3]='5';
	buf[6][0]='1';
	buf[6][1]='2';
	buf[6][2]='3';
	buf[7][0]='2';
	buf[7][1]='5';
	buf[8][0]='2';
	buf[8][1]='3';
	buf[8][2]='4';
	buf[9][0]='3';
	buf[9][1]='4';
	for(k=0;k<10;k++)
	{
		*(p+k)=buf[k];	
	}
	LoadItemL1(p);
	LoadItemL2(p);
	LoadItemL3(p);
	LoadItemL4(p);
	printf("产生关联规则: \n");
	printf("非空子集:    置信度:\n");
	for(i=0;i<10;i++)
	{
		//printf("{%c,%c,%c}:       %d\n",curL3[i][0],curL3[i][1],curL3[i][2],countL3[i]);
		//printf("%s\n",curL3[i]);
		if(curL3[i]!=0 && countL3[i]>=2)
			Support(curL3[i],i);
	}
	return 0;
	
}

运行结果:

抱歉!评论已关闭.