数据挖掘 apriori算法

来源:互联网 发布:西北师大知行学院学费 编辑:程序博客网 时间:2024/05/02 04:36

这个算法是数据挖掘的经典算法,而且写起来并不麻烦,我是apriori的详解~

这个算法是我们数据结构老师让我们编的,事物集达到了88000多条,第一次验证xcode读txt还是蛮简单的哈哈哈哈哈哈哈哈~( ̄▽ ̄)~

#include <iostream>#include <stdio.h>#include <string.h>#include <stdlib.h>using namespace std;struct L   //频繁项集存储的结构体{    int itemm[100];  //每次求n项频繁项集时都会刷新一遍l,这个数组存放的是n项集里的每个项    int itemm_num;  //存放n项集的n,有点麻烦了}L[90000];struct C  //候选项集存储结构体//每次求n项候选项集时会刷新c{    int itemmm[100];  //每次求n项候选项集时,每个n项候选项存放在这里,编号从0到n-1    int itemmm_num;}C[90000];struct RowFromTxt   //存放资料的结构题,一行用一个结构体存储,一行里的每个数据存在item的数组里{    int item[1000];    int alldatafromtxt[17000]={0};  //为了查找方便特意安排一个数组,数字最大不超过17000,所以可以存放一行里每个数字出现过几遍    int item_num;  //存放一行里几个数字}RowFromTxt[90000];double AllDataFromTxt[17000]={0};   //所有数字出现的频率,计算频繁一项集时会用int RowNumTxt=0;  //资料里一共有多少行double support;    //支持度,在程序里自定的,可以改,不要小于0.005~//int c_num[100];int change_row(char row_string[],int row_num){    char row_end[]=" \n";    char *new_row;    new_row=strtok(row_string, row_end);    int row_item_num=0;    int item;    while (new_row!=NULL) {        row_item_num++;        item=atoi(new_row);        AllDataFromTxt[item]+=1.0000;        RowFromTxt[row_num].item[row_item_num]=item;        RowFromTxt[row_num].alldatafromtxt[item]++;        new_row=strtok(NULL, row_end);        if (new_row==NULL) {            break;        }    }    RowFromTxt[row_num].item_num=row_item_num;    return 0;}int GetCnplus1(int Cplus1EachStructNum,int LTotalStructNum)   //得到n+1项的候选项集{    int i,j,m;    cout<<"候选"<<Cplus1EachStructNum<<"项集为:"<<endl;    int Cplus1TotalStructNum=0;    for (i=1; i<=LTotalStructNum; i++) {   //和其他频繁项对比,如果前n-1项一样,则其他频繁项合起来存进新的候选项        for (j=i+1; j<=LTotalStructNum; j++) {            int flag=1;            for (m=0; m<Cplus1EachStructNum-2; m++) {                if (L[i].itemm[m]!=L[j].itemm[m]) {                    flag=0;                    break;                }            }            if (flag==0) {                continue;            }            if (flag==1) {        //合并两个n项频繁项,存进n+1的频繁项集                Cplus1TotalStructNum++;                C[Cplus1TotalStructNum].itemmm_num=Cplus1EachStructNum;                for (m=0; m<Cplus1EachStructNum-1; m++) {                    C[Cplus1TotalStructNum].itemmm[m]=L[i].itemm[m];                }                C[Cplus1TotalStructNum].itemmm[m]=L[j].itemm[m-1];            }        }    }    for (i=1; i<=Cplus1TotalStructNum; i++) {        for (j=0; j<Cplus1EachStructNum; j++) {            cout<<C[i].itemmm[j]<<" ";        }        cout<<"   ";    }    cout<<endl;    cout<<"共"<<Cplus1TotalStructNum<<"项"<<endl;    return Cplus1TotalStructNum;}int apriori(int ThisCRowTotalStructNum,int ThisCEveryRowDataNumber)   //高能!!!{    int i,j,m,n;    int count=0;    cout<<"频繁"<<C[1].itemmm_num<<"项集有:"<<endl;   //频繁n项集有……    for (i=1; i<ThisCRowTotalStructNum; i++) {   //所有频繁候选n项集的总项数        double show=0;                           //每一项里每个数字在资料里每一行出现的个数统计                for (j=1; j<RowNumTxt; j++) {     //资料里总的行数,全局变量            int flag=1;            for (m=0; m<C[i].itemmm_num; m++) {    //一个n项集里每个数是否在资料里的第j行存在?                if (RowFromTxt[j].alldatafromtxt[C[i].itemmm[m]]==0) {                    flag=0;         //不存在退出                    break;                }            }            if (flag==1) {    //存在说明这一行可以统计,事物里有这个项                show+=1.00;            }        }        if (show/RowNumTxt>=support) {         //如果出现次数除以总的事物rownumtxt大于支持度,那就是频繁项啦~            for (n=0; n<C[1].itemmm_num; n++) {                cout<<C[i].itemmm[n]<<" ";   //输出看看~~            }            cout<<"    ";            count++;            for (m=0; m<C[i].itemmm_num; m++) {                L[count].itemm[m]=C[i].itemmm[m];   //把这个候选项一个一个存进l            }        }    }    cout<<endl;    cout<<"共"<<count<<"项"<<endl;        if (count==1||count==0) {       //如果频繁项只有一个或没有的话,挖掘就结束了        return 0;    }        int Cplus1TotalstructNum=GetCnplus1(C[1].itemmm_num+1, count);  //如果没有结束的话继续得到n+1项的候选项    if(apriori(Cplus1TotalstructNum , C[1].itemmm_num+1)==0)  //计算n+1项的频繁项        return 0;    return 0;}int main(int argc, const char * argv[]){    freopen("/Users/gray/Documents/数据挖掘/数据挖掘课程资料大全/retail副本.txt", "r", stdin);  //打开并读取文件    char row_string[1000];   //每行字符串    while (gets(row_string)) {        RowNumTxt++;        change_row(row_string, RowNumTxt);        memset(row_string, 0, sizeof(1000));    }    support=0.0113;      //定义支持度0.01    int i,j;    int l_num=1;       //开始计算频繁一项集    for (i=0; i<17000; i++) {        if (AllDataFromTxt[i]/RowNumTxt>=support) {   //alldatafromtxt在changerow函数里记录了每个数字出现的次数们可以直接用            L[l_num].itemm[0]=i;   //讲频繁一项集存入l(其实可以直接存入c用作频繁二项集候选项)            L[l_num].itemm_num=1;   //此l的频繁n项集,n为1            l_num++;    //频繁1项集的总数        }    }    cout<<"频繁1项集有:"<<endl;    for (i=1; i<l_num; i++) {        cout<<L[i].itemm[0]<<" ";        cout<<AllDataFromTxt[L[i].itemm[0]]<<endl;    }    //cout<<endl;    //c_num[1]=l_num-1;    //频繁候选2项集的    int l2_num=1;   //统计频繁候选二项集,其实叫c2_num更合适    for (i=1; i<l_num; i++) {       //得到频繁候选二项集,存入结构体        for (j=i+1; j<l_num; j++) {            C[l2_num].itemmm[0]=L[i].itemm[0];            C[l2_num].itemmm[1]=L[j].itemm[0];            C[l2_num].itemmm_num=2;            l2_num++;        }    }    //准备工作完成,开始各种候选    apriori(l2_num, 2);  //输入频繁候选二项集的个数,和频繁候选二项集里每个项集的个数,就是2    return 0;}

事物都是数字,可以直接改字符型……

0 0