A-Priori算法

来源:互联网 发布:华语乐坛唱功最好知乎 编辑:程序博客网 时间:2024/05/15 00:36

一、实验内容

给定某超市购物篮数据库文件basketdata.xls,里面有18项商品的747条购买记录。取支持度阈值s =185,请利用A-Priori算法提取其中的最大频繁项集Lk。

附件:某超市数据集basketdata.xls

二、实验设计(原理分析及流程)
首先,当然是将超市购物篮的数据文件读取到一个数据结构中保存起来。这里,因为开始的购物车数量以及商品数量已知,使用分割函数将信息文件信息存放到静态数组。我选择使用一个747行,18列的静态数组来存储信息。建立几个静态数组来存放频繁项集以及候选项集,之后根据伪代码进行操作。

三、这里使用set会比较简单,但当时还没学,所以就没用上,代码比较丑陋。。。

四、代码:

#include <fstream>#include <string>#include <iostream>#include <streambuf>#include <vector>#define ListLen 747     // 购物车数量#define GoodsNum 18     // 商品数量#define S 185           // 阈值using namespace std;// 存放商品名称的string数组const string ItemName[GoodsNum] ={    "饮料", "冲饮食品", "乳制冲饮", "罐头食品", "即食主食",    "中式挂面/通心粉", "酱油", "醋", "调味品", "饼干",    "中式糕点", "膨化食品", "休闲小食品", "炒货食品", "糖果巧克力",    "进口食品", "香烟", "啤酒"};// 分割函数,将从文件读取的一行string分割成多个列// 参数为 源字符串,分界符,存放单词的容器int Split(const string &str, const string &splitchar, std::vector <string> &vec){    string stmp = "";    string::size_type pos = 0, prev_pos = 0;    vec.clear(); // 删除存在的元素    while ((pos = str.find_first_of(splitchar, pos)) != string::npos)    {        stmp = str.substr(prev_pos, pos - prev_pos);        vec.push_back(stmp);        prev_pos = ++pos;    }    stmp = str.substr(prev_pos, pos - prev_pos);    if (stmp.length() > 0)    {        vec.push_back(stmp);    }    return 0;}// 生成数据矩阵的函数 从文本中读取数据// 参数:矩阵,存放单词的容器,矩阵列的数目,文本行数目int MatrEst(int DataList[][GoodsNum], vector <string> &LineWord, int GN, int LineCount){    for (int i = 1; i < GN + 1; i++)  // 跳过原行号,将新的数组行号作为行号    {        // 将数据文件的信息转化为数组信息        if (!(LineWord[i]).compare("T"))            DataList[LineCount][i-1] = 1;        else if (!(LineWord[i]).compare("F"))            DataList[LineCount][i-1] = 0;        else            cout << "Error!" << endl;    }    return 0;}// 构造频繁一项集,容器存放频繁项的列号 列号:0-17 返回频繁一项个数// 参数:容器,信息矩阵int OneItem(vector<int> &OneFrc,int DataList[][GoodsNum]){    vector<int> OneCanVec(18, 0);    for (int i = 0; i < ListLen; i++)    {        for (int j = 0; j < GoodsNum; j++)        {            if (DataList[i][j])                OneCanVec[j]++;        }    }    for (int i = 0; i < GoodsNum; i++)    {        if (OneCanVec[i] < S)            ;        else            // 一项集,若支持度大于阈值,加入一项频繁项集            OneFrc.push_back(i);    }    unsigned ItemNum = OneFrc.size();       // 频繁项集数目    if (ItemNum == 0)        return 0;    else        return ItemNum;}// 构造频繁二项集,容器存放频繁项的列号 列号:0-17 返回频繁二项个数// 参数:存放频繁二项集的数组,信息矩阵,频繁一项个数,频繁一项集容器int TwoItem(int TwoFrc[][2], int DataList[][GoodsNum], int OneNum, vector<int> &OneFrc){    // 从频繁一项集中组成二项集并判断    int TwoCount = 0, TwoFrcFi = 0, TwoFrcNum = 0;// 支持度计数    int i, j;    for (i = 0; i < OneNum - 1; i++) // 0-8    {        for (j = i + 1; j < OneNum; j++) // 1-9        {            for (int k = 0; k < ListLen; k++)  // 遍历每一行并统计该二项集支持度            {                int first = OneFrc[i], second = OneFrc[j];                //cout << "First: " << first << " Second " << second << endl;                if (DataList[k][first] && DataList[k][second])      // 两项同时出现在一个购物篮                    TwoCount++;            }            if (TwoCount >= S)            {                // 记录频繁二项集                TwoFrc[TwoFrcFi][0] = OneFrc[i], TwoFrc[TwoFrcFi][1] = OneFrc[j];                TwoFrcFi++;                TwoFrcNum++;            }            TwoCount = 0;        }    }    return TwoFrcNum;}// 判断两个项是否存在于频繁二项集中 返回 1表示存在 0 不存在// 参数:第一个列序号,第二个列序号,频繁二项集,频繁二项集数目int ExistTwo(int i, int j, int TwoFrc[][2], int TwoNum){    int IN = 0;    for (int k = 0; k < TwoNum; k++)        if ((TwoFrc[k][0] == i) && (TwoFrc[k][1] == j))        {            IN = 1;            break;        }    if (IN)        return 1;    else        return 0;}// 构造频繁三项集,容器存放频繁项的列号 列号:0-17 返回频繁三项个数// 参数:存放频繁二项集的数组,存放候选三项集数组,存放频繁三项集数组,信息矩阵,频繁二项个数int ThreeItem(int TwoFrc[][2], int ThrCan[][3], int ThrFrc[][3],int DataList[][GoodsNum], int TwoNum){    int ThCount = 0, ThFrCount = 0, ThFrNum = 0;    for (int i = 0; i < TwoNum - 1; i++)        // 每一行    {        for (int j = i + 1; j < TwoNum; j++)        {            int first = TwoFrc[i][1], second = TwoFrc[j][1];            if ((TwoFrc[i][0] == TwoFrc[j][0]) &&                    ExistTwo(first, second, TwoFrc, TwoNum))            {                ThrCan[ThCount][0] = TwoFrc[i][0];                ThrCan[ThCount][1] = first;                ThrCan[ThCount][2] = second;                ThCount++;            }        }    }    cout << "ThCount: " << ThCount << endl;    for (int i = 0; i < ThCount; i++)    {        int first = ThrCan[i][0], second = ThrCan[i][1],            third = ThrCan[i][2];        for (int k = 0; k < ListLen; k++)  // 遍历每一行并统计该二项集支持度        {            if (DataList[k][first] && DataList[k][second] && DataList[k][third])// 项同时出现在一个购物篮                ThFrCount++;        }        if (ThFrCount >= S)        {            // 记录频繁二项集            ThrFrc[ThFrNum][0] = first;            ThrFrc[ThFrNum][1] = second;            ThrFrc[ThFrNum][2] = third;            ThFrNum++;        }        ThFrCount = 0;    }    return ThFrNum;}int main (void){    vector<string> LineWord;          // 存放一行单词集合来处理    vector<int> OneFrc;               // 存放频繁一项集    int TwoFrc[45][2];                // 存放频繁二项集    int ThreeCan[20][3];              // 存放候选三项集    int ThreeFrc[10][3];              // 存放频繁二项集    int DataList[ListLen][GoodsNum];  // 创建静态数组来保存购物车信息看做一个矩阵    const string SplitStr = ",";      // CSV文件分隔符    ifstream DataStream;              // 读取文件流    string FileLine;                  // 读取文件行存放的string    int LineCount = 0;                // 行计数    int KItem[GoodsNum];              // 保存频繁项集的个数数组    DataStream.open("basketdata.csv", ios::in);    if(!DataStream)                   // 读取不成功则是NULL    {        cout << "Can't not open data file!\n";        return 0;    }    getline(DataStream, FileLine);    // 读取掉前面两行    getline(DataStream, FileLine);    while(LineCount < ListLen && getline(DataStream, FileLine) )// 每次读取数据文件的一行进行处理    {        // 因为转化为csv文件,根据,来对每个数据存储到静态数组        // 将一行数据中的每一列分开        Split(FileLine, SplitStr, LineWord);        MatrEst(DataList, LineWord, GoodsNum, LineCount);        LineCount++;    }    KItem[1] = OneItem(OneFrc, DataList);              // 获得频繁一项集    KItem[2] = TwoItem(TwoFrc, DataList, KItem[1], OneFrc);    KItem[3] = ThreeItem(TwoFrc, ThreeCan, ThreeFrc, DataList, KItem[2]);    if ( KItem[3] < 4)    {        cout << "找到最大频繁项集,项数为3,个数: " << KItem[3] << endl;        cout << ItemName[ThreeFrc[0][0]] << ", " << ItemName[ThreeFrc[0][1]]             << ", " << ItemName[ThreeFrc[0][2]] << endl;        cout << ItemName[ThreeFrc[1][0]] << ", " << ItemName[ThreeFrc[1][1]]             << ", " << ItemName[ThreeFrc[1][2]] << endl;    }    cout << "Done!" << endl;    return 0;}
原创粉丝点击