(update 2012.12.28 关于本项目下载及运行的常见问题 FAQ见newsgroup18828文本分类器、文本聚类器、关联分析频繁模式挖掘算法的Java实现工程下载及运行FAQ)
一、Apriori算法
Apriori是非常经典的关联分析频繁模式挖掘算法,其思想简明,实现方便,只是效率很低,可以作为频繁模式挖掘的入门算法。其主要特点是
1、k-1项集连接规律:若有两个k-1项集,每个项集保证有序,如果两个k-1项集的前k-
2个项相同,而最后一个项不同,则证明它们是可连接的,可连接生成k项集。
2、反单调性。如果一个项集是频繁的,那么它的所有子集都是频繁的。即若一个项集的
子集不是频繁项集,则该项集肯定也不是频繁项集。
主要算法流程:
1. 扫描数据库,生成候选1项集和频繁1项集。
2. 从2项集开始循环,由频繁k-1项集生成频繁频繁k项集。
2.1 频繁k-1项集两两组合,判定是否可以连接,若能则连接生成k项集。
2.2 对k项集中的每个项集检测其子集是否频繁,舍弃掉子集不是频繁项集即 不在频繁k-1项集中的项集。
2.3 扫描数据库,计算2.3步中过滤后的k项集的支持度,舍弃掉支持度小于阈值的项集,生成频繁k项集。
3. 若当前k项集中只有一个项集时循环结束。
2. 从2项集开始循环,由频繁k-1项集生成频繁频繁k项集。
2.1 频繁k-1项集两两组合,判定是否可以连接,若能则连接生成k项集。
2.2 对k项集中的每个项集检测其子集是否频繁,舍弃掉子集不是频繁项集即 不在频繁k-1项集中的项集。
2.3 扫描数据库,计算2.3步中过滤后的k项集的支持度,舍弃掉支持度小于阈值的项集,生成频繁k项集。
3. 若当前k项集中只有一个项集时循环结束。
伪代码如下:

JAVA实现代码
- packagecom.pku.yangliu;
- importjava.io.BufferedReader;
- importjava.io.File;
- importjava.io.FileReader;
- importjava.io.FileWriter;
- importjava.io.IOException;
- importjava.util.ArrayList;
- importjava.util.HashMap;
- importjava.util.HashSet;
- importjava.util.List;
- importjava.util.Map;
- importjava.util.Set;
- importjava.util.TreeSet;
- /**频繁模式挖掘算法Apriori实现
- *
- */
- publicclassAprioriFPMining{
- privateintminSup;//最小支持度
- privatestaticList<Set<String>>dataTrans;//以List<Set<String>>格式保存的事物数据库,利用Set的有序性
- publicintgetMinSup(){
- returnminSup;
- }
- publicvoidsetMinSup(intminSup){
- this.minSup=minSup;
- }
- /**
- *@paramargs
- */
- publicstaticvoidmain(String[]args)throwsIOException{
- AprioriFPMiningapriori=newAprioriFPMining();
- double[]threshold={0.25,0.20,0.15,0.10,0.05};
- StringsrcFile="F:/DataMiningSample/FPmining/Mushroom.dat";
- StringshortFileName=srcFile.split("/")[3];
- StringtargetFile="F:/DataMiningSample/FPmining/"+shortFileName.substring(0,shortFileName.indexOf("."))+"_fp_threshold";
- dataTrans=apriori.readTrans(srcFile);
- for(intk=0;k<threshold.length;k++){
- System.out.println(srcFile+"threshold:"+threshold[k]);
- longtotalItem=0;
- longtotalTime=0;
- FileWritertgFileWriter=newFileWriter(targetFile+(threshold[k]*100));
- apriori.setMinSup((int)(dataTrans.size()*threshold[k]));//原始蘑菇的数据0.25只需要67秒跑出结果
- longstartTime=System.currentTimeMillis();
- Map<String,Integer>f1Set=apriori.findFP1Items(dataTrans);
- longendTime=System.currentTimeMillis();
- totalTime+=endTime-startTime;
- //频繁1项集信息得加入支持度
- Map<Set<String>,Integer>f1Map=newHashMap<Set<String>,Integer>();
- for(Map.Entry<String,Integer>f1Item:f1Set.entrySet()){
- Set<String>fs=newHashSet<String>();
- fs.add(f1Item.getKey());
- f1Map.put(fs,f1Item.getValue());
- }
- totalItem+=apriori.printMap(f1Map,tgFileWriter);
- Map<Set<String>,Integer>result=f1Map;
- do{
- startTime=System.currentTimeMillis();
- result=apriori.genNextKItem(result);
- endTime=System.currentTimeMillis();
- totalTime+=endTime-startTime;
- totalItem+=apriori.printMap(result,tgFileWriter);
- }while(result.size()!=0);
- tgFileWriter.close();
- System.out.println("共用时:"+totalTime+"ms");
- System.out.println("共有"+totalItem+"项频繁模式");
- }
- }
- /**由频繁K-1项集生成频繁K项集
- *@parampreMap保存频繁K项集的map
- *@paramtgFileWriter输出文件句柄
- *@returnint频繁i项集的数目
- *@throwsIOException
- */
- privateMap<Set<String>,Integer>genNextKItem(Map<Set<String>,Integer>preMap){
- //TODOAuto-generatedmethodstub
- Map<Set<String>,Integer>result=newHashMap<Set<String>,Integer>();
- //遍历两个k-1项集生成k项集
- List<Set<String>>preSetArray=newArrayList<Set<String>>();
- for(Map.Entry<Set<String>,Integer>preMapItem:preMap.entrySet()){
- preSetArray.add(preMapItem.getKey());
- }
- intpreSetLength=preSetArray.size();
- for(inti=0;i<preSetLength-1;i++){
- for(intj=i+1;j<preSetLength;j++){
- String[]strA1=preSetArray.get(i).toArray(newString[0]);
- String[]strA2=preSetArray.get(j).toArray(newString[0]);
- if(isCanLink(strA1,strA2)){//判断两个k-1项集是否符合连接成k项集的条件
- Set<String>set=newTreeSet<String>();
- for(Stringstr:strA1){
- set.add(str);
- }
- set.add((String)strA2[strA2.length-1]);//连接成k项集
- //判断k项集是否需要剪切掉,如果不需要被cut掉,则加入到k项集列表中
- if(!isNeedCut(preMap,set)){//由于单调性,必须保证k项集的所有k-1项子集都在preMap中出现,否则就该剪切该k项集
- result.put(set,0);
- }
- }
- }
- }
- returnassertFP(result);//遍历事物数据库,求支持度,确保为频繁项集
- }
- /**检测k项集是否该剪切。由于单调性,必须保证k项集的所有k-1项子集都在preMap中出现,否则就该剪切该k项集
- *@parampreMapk-1项频繁集map
- *@paramset待检测的k项集
- *@returnboolean是否该剪切
- *@throwsIOException
- */
- privatebooleanisNeedCut(Map<Set<String>,Integer>preMap,Set<String>set){
- //TODOAuto-generatedmethodstub
- booleanflag=false;
- List<Set<String>>subSets=getSubSets(set);
- for(Set<String>subSet:subSets){
- if(!preMap.containsKey(subSet)){
- flag=true;
- break;
- }
- }
- returnflag;
- }
- /**获取k项集set的所有k-1项子集
- *@paramset频繁k项集
- *@returnList<Set<String>>所有k-1项子集容器
- *@throwsIOException
- */
- privateList<Set<String>>getSubSets(Set<String>set){
- //TODOAuto-generatedmethodstub
- String[]setArray=set.toArray(newString[0]);
- List<Set<String>>result=newArrayList<Set<String>>();
- for(inti=0;i<setArray.length;i++){
- Set<String>subSet=newHashSet<String>();
- for(intj=0;j<setArray.length;j++){
- if(j!=i)subSet.add(setArray[j]);
- }
- result.add(subSet);
- }
- returnresult;
- }
- /**遍历事物数据库,求支持度,确保为频繁项集
- *@paramallKItem候选频繁k项集
- *@returnMap<Set<String>,Integer>支持度大于阈值的频繁项集和支持度map
- *@throwsIOException
- */
- privateMap<Set<String>,Integer>assertFP(
- Map<Set<String>,Integer>allKItem){
- //TODOAuto-generatedmethodstub
- Map<Set<String>,Integer>result=newHashMap<Set<String>,Integer>();
- for(Set<String>kItem:allKItem.keySet()){
- for(Set<String>data:dataTrans){
- booleanflag=true;
- for(Stringstr:kItem){
- if(!data.contains(str)){
- flag=false;
- break;
- }
- }
- if(flag)allKItem.put(kItem,allKItem.get(kItem)+1);
- }
- if(allKItem.get(kItem)>=minSup){
- result.put(kItem,allKItem.get(kItem));
- }
- }
- returnresult;
- }
- /**检测两个频繁K项集是否可以连接,连接条件是只有最后一个项不同
- *@paramstrA1k项集1
- *@paramstrA1k项集2
- *@returnboolean是否可以连接
- *@throwsIOException
- */
- privatebooleanisCanLink(String[]strA1,String[]strA2){
- //TODOAuto-generatedmethodstub
- booleanflag=true;
- if(strA1.length!=strA2.length){
- returnfalse;
- }else{
- for(inti=0;i<strA1.length-1;i++){
- if(!strA1[i].equals(strA2[i])){
- flag=false;
- break;
- }
- }
- if(strA1[strA1.length-1].equals(strA2[strA1.length-1])){
- flag=false;
- }
- }
- returnflag;
- }
- /**将频繁i项集的内容及支持度输出到文件格式为模式:支持度
- *@paramf1Map保存频繁i项集的容器<i项集,支持度>
- *@paramtgFileWriter输出文件句柄
- *@returnint频繁i项集的数目
- *@throwsIOException
- */
- privateintprintMap(Map<Set<String>,Integer>f1Map,FileWritertgFileWriter)throwsIOException{
- //TODOAuto-generatedmethodstub
- for(Map.Entry<Set<String>,Integer>f1MapItem:f1Map.entrySet()){
- for(Stringp:f1MapItem.getKey()){
- tgFileWriter.append(p+"");
- }
- tgFileWriter.append(":"+f1MapItem.getValue()+"\n");
- }
- tgFileWriter.flush();
- returnf1Map.size();
- }
- /**生成频繁1项集
- *@paramfileDir事务文件目录
- *@returnMap<String,Integer>保存频繁1项集的容器<1项集,支持度>
- *@throwsIOException
- */
- privateMap<String,Integer>findFP1Items(List<Set<String>>dataTrans){
- //TODOAuto-generatedmethodstub
- Map<String,Integer>result=newHashMap<String,Integer>();
- Map<String,Integer>itemCount=newHashMap<String,Integer>();
- for(Set<String>ds:dataTrans){
- for(Stringd:ds){
- if(itemCount.containsKey(d)){
- itemCount.put(d,itemCount.get(d)+1);
- }else{
- itemCount.put(d,1);
- }
- }
- }
- for(Map.Entry<String,Integer>ic:itemCount.entrySet()){
- if(ic.getValue()>=minSup){
- result.put(ic.getKey(),ic.getValue());
- }
- }
- returnresult;
- }
- /**读取事务数据库
- *@paramfileDir事务文件目录
- *@returnList<String>保存事务的容器
- *@throwsIOException
- */
- privateList<Set<String>>readTrans(StringfileDir){
- //TODOAuto-generatedmethodstub
- List<Set<String>>records=newArrayList<Set<String>>();
- try{
- FileReaderfr=newFileReader(newFile(fileDir));
- BufferedReaderbr=newBufferedReader(fr);
- Stringline=null;
- while((line=br.readLine())!=null){
- if(line.trim()!=""){
- Set<String>record=newHashSet<String>();
- String[]items=line.split("");
- for(Stringitem:items){
- record.add(item);
- }
- records.add(record);
- }
- }
- }catch(IOExceptione){
- System.out.println("读取事务文件失败。");
- System.exit(-2);
- }
- returnrecords;
- }
- }
实验结果
F:/DataMiningSample/FPmining/Mushroom.dat threshold: 0.25
共用时:54015ms
共有5545项频繁模式
F:/DataMiningSample/FPmining/Mushroom.dat threshold: 0.2
共用时:991610ms
共有53663项频繁模式
F:/DataMiningSample/FPmining/Mushroom.dat threshold: 0.15
结论:对Mushroom.dat挖掘出来的频繁模式及支持度、频繁模式总数正确,但是算法速度很慢,对大数据量如T10I4D100K低阈值挖掘时间太长
解决办法:改用C++写FP-Growth算法做频繁模式挖掘!
解决办法:改用C++写FP-Growth算法做频繁模式挖掘!
二、FP-Growth算法
FP-Growth算法由数据挖掘界大牛Han Jiawei教授于SIGMOD 00‘大会提出,提出根据事物数据库构建FP-Tree,然后基于FP-Tree生成频繁模式集。主要算法流程如下
Step1 读取数据库,构造频繁1项集及FP-tree

Step2 遍历FP-tree的头表,对于每个频繁项x,累积项x的所有前缀路径形成x的条件模式库CPB

Step3 对CPB上每一条路径的节点更新计数为x的计数,根据CPB构造条件FP-tree
Step4 从条件FP-tree中找到所有长路径,对该路径上的节点找出所有组合方式,然后合并计数
Step5 将Step4中的频繁项集与x合并,得到包含x的频繁项集
Step2-5 循环,直到遍历头表中的所有项

由于时间关系,主要基于芬兰教授Bart Goethals的开源代码实现,源码下载见点击打开链接,文件结构及运行结果如下

对Mushroom.dat,accidents.dat和T10I4D100K.dat三个数据集做频繁模式挖掘的结果如下



三、Eclat算法
Eclat算法加入了倒排的思想,加快频繁集生成速度,其算法思想是 由频繁k项集求交集,生成候选k+1项集 。对候选k+1项集做裁剪,生成频繁k+1项集,再求交集生成候选k+2项集。如此迭代,直到项集归一。
算法过程:
1.一次扫描数据库,获得初始数据。包括频繁1项集,数据库包含的所有items,事务总数(行)transNum,最小支持度minsup=limitValue*trans。
2.二次扫描数据库,获得频繁2项集。
3.按照Eclat算法,对频繁2项集迭代求交集,做裁剪,直到项集归一。
Eclat算法加入了倒排的思想,加快频繁集生成速度,其算法思想是 由频繁k项集求交集,生成候选k+1项集 。对候选k+1项集做裁剪,生成频繁k+1项集,再求交集生成候选k+2项集。如此迭代,直到项集归一。
算法过程:
1.一次扫描数据库,获得初始数据。包括频繁1项集,数据库包含的所有items,事务总数(行)transNum,最小支持度minsup=limitValue*trans。
2.二次扫描数据库,获得频繁2项集。
3.按照Eclat算法,对频繁2项集迭代求交集,做裁剪,直到项集归一。
JAVA实现如下
- packagecom.pku.yhf;
- importjava.io.BufferedReader;
- importjava.io.BufferedWriter;
- importjava.io.File;
- importjava.io.FileInputStream;
- importjava.io.FileNotFoundException;
- importjava.io.FileReader;
- importjava.io.FileWriter;
- importjava.io.IOException;
- importjava.io.InputStreamReader;
- importjava.util.ArrayList;
- importjava.util.BitSet;
- importjava.util.Iterator;
- importjava.util.Set;
- importjava.util.TreeMap;
- importjava.util.TreeSet;
- publicclassEclatRelease{
- privateFilefile=newFile("D:/mushroom.dat.txt");
- privatefloatlimitValue=0.25f;
- privateinttransNum=0;
- privateArrayList<HeadNode>array=newArrayList<HeadNode>();
- privateHashHeadNode[]hashTable;//存放临时生成的频繁项集,作为重复查询的备选集合
- publiclongnewItemNum=0;
- privateFiletempFile=null;
- privateBufferedWriterbw=null;
- publicstaticlongmodSum=0;
- /**
- *第一遍扫描数据库,确定Itemset,根据阈值计算出支持度数
- */
- publicvoidinit()
- {
- SetitemSet=newTreeSet();
- MyMap<Integer,Integer>itemMap=newMyMap<Integer,Integer>();
- intitemNum=0;
- Set[][]a;
- try{
- FileInputStreamfis=newFileInputStream(file);
- BufferedReaderbr=newBufferedReader(newInputStreamReader(fis));
- Stringstr=null;
- //第一次扫描数据集合
- while((str=br.readLine())!=null)
- {
- transNum++;
- String[]line=str.split("");
- for(Stringitem:line)
- {
- itemSet.add(Integer.parseInt(item));
- itemMap.add(Integer.parseInt((item)));
- }
- }
- br.close();
- //System.out.println("itemMaplastKey:"+itemMap.lastKey());
- //System.out.println("itemsize:"+itemSet.size());
- //System.out.println("trans:"+transNum);
- //ItemSet.limitSupport=(int)Math.ceil(transNum*limitValue);//上取整
- ItemSet.limitSupport=(int)Math.floor(transNum*limitValue);//下取整
- ItemSet.ItemSize=(Integer)itemMap.lastKey();
- ItemSet.TransSize=transNum;
- hashTable=newHashHeadNode[ItemSet.ItemSize*3];//生成项集hash表
- for(inti=0;i<hashTable.length;i++)
- {
- hashTable[i]=newHashHeadNode();
- }
- //System.out.println("limitSupport:"+ItemSet.limitSupport);
- tempFile=newFile(file.getParent()+"/"+file.getName()+".dat");
- if(tempFile.exists())
- {
- tempFile.delete();
- }
- tempFile.createNewFile();
- bw=newBufferedWriter(newFileWriter(tempFile));
- SetoneItem=itemMap.keySet();
- intcountOneItem=0;
- for(Iteratorit=oneItem.iterator();it.hasNext();)
- {
- intkey=(Integer)it.next();
- intvalue=(Integer)itemMap.get(key);
- if(value>=ItemSet.limitSupport)
- {
- bw.write(key+""+":"+""+value);
- bw.write("\n");
- countOneItem++;
- }
- }
- bw.flush();
- modSum+=countOneItem;
- itemNum=(Integer)itemMap.lastKey();
- a=newTreeSet[itemNum+1][itemNum+1];
- array.add(newHeadNode());//空项
- for(shorti=1;i<=itemNum;i++)
- {
- HeadNodehn=newHeadNode();
- //hn.item=i;
- array.add(hn);
- }
- BufferedReaderbr2=newBufferedReader(newFileReader(file));
- //第二次扫描数据集合,形成2-项候选集
- intcounter=0;//事务
- intmax=0;
- while((str=br2.readLine())!=null)
- {max++;
- String[]line=str.split("");
- counter++;
- for(inti=0;i<line.length;i++)
- {
- intsOne=Integer.parseInt(line[i]);
- for(intj=i+1;j<line.length;j++)
- {
- intsTwo=Integer.parseInt(line[j]);
- if(a[sOne][sTwo]==null)
- {
- Setset=newTreeSet();
- set.add(counter);
- a[sOne][sTwo]=set;
- }
- else{
- a[sOne][sTwo].add(counter);
- }
- }
- }
- }
- //将数组集合转换为链表集合
- for(inti=1;i<=itemNum;i++)
- {
- HeadNodehn=array.get(i);
- for(intj=i+1;j<=itemNum;j++)
- {
- if(a[i][j]!=null&&a[i][j].size()>=ItemSet.limitSupport)
- {
- hn.items++;
- ItemSetis=newItemSet(true);
- is.item=2;
- is.items.set(i);
- is.items.set(j);
- is.supports=a[i][j].size();
- bw.write(i+""+j+""+":"+is.supports);
- bw.write("\n");
- //统计频繁2-项集的个数
- modSum++;
- for(Iteratorit=a[i][j].iterator();it.hasNext();)
- {
- intvalue=(Integer)it.next();
- is.trans.set(value);
- }
- if(hn.first==null)
- {
- hn.first=is;
- hn.last=is;
- }
- else{
- hn.last.next=is;
- hn.last=is;
- }
- }
- }
- }
- bw.flush();
- }catch(FileNotFoundExceptione){
- e.printStackTrace();
- }catch(IOExceptione){
- e.printStackTrace();
- }
- }
- publicvoidstart()
- {
- booleanflag=true;
- //TreeSetts=newTreeSet();//临时存储项目集合,防止重复项集出现,节省空间
- intcount=0;
- ItemSetshareFirst=newItemSet(false);
- while(flag)
- {
- flag=false;
- //System.out.println(++count);
- for(inti=1;i<array.size();i++)
- {
- HeadNodehn=array.get(i);
- if(hn.items>1)//项集个数大于1
- {
- generateLargeItemSet(hn,shareFirst);
- flag=true;
- }
- clear(hashTable);
- }
- }try{
- bw.close();
- }catch(IOExceptione){
- e.printStackTrace();
- }
- }
- publicvoidgenerateLargeItemSet(HeadNodehn,ItemSetshareFirst){
- BitSetbsItems=newBitSet(ItemSet.ItemSize);//存放链两个k-1频繁项集的ItemSet交
- BitSetbsTrans=newBitSet(ItemSet.TransSize);//存放两个k-1频繁项集的Trans交
- BitSetcontainItems=newBitSet(ItemSet.ItemSize);//存放两个k-1频繁项集的ItemSet的并
- BitSetbsItems2=newBitSet(ItemSet.ItemSize);//临时存放容器BitSet
- ItemSetoldCurrent=null,oldNext=null;
- oldCurrent=hn.first;
- longcountItems=0;
- ItemSetnewFirst=newItemSet(false),newLast=newFirst;
- while(oldCurrent!=null)
- {
- oldNext=oldCurrent.next;
- while(oldNext!=null)
- {
- //生成k—项候选集,由两个k-1项频繁集生成
- bsItems.clear();
- bsItems.or(oldCurrent.items);
- bsItems.and(oldNext.items);
- if(bsItems.cardinality()<oldCurrent.item-1)
- {
- break;
- }
- //新合并的项集是否已经存在
- containItems.clear();
- containItems.or(oldCurrent.items);//将k-1项集合并
- containItems.or(oldNext.items);
- if(!containItems(containItems,bsItems2,newFirst)){
- bsTrans.clear();
- bsTrans.or(oldCurrent.trans);
- bsTrans.and(oldNext.trans);
- if(bsTrans.cardinality()>=ItemSet.limitSupport)
- {
- ItemSetis=null;
- if(shareFirst.next==null)//没有共享ItemSet链表
- {
- is=newItemSet(true);
- newItemNum++;
- }
- else
- {
- is=shareFirst.next;
- shareFirst.next=shareFirst.next.next;
- is.items.clear();
- is.trans.clear();
- is.next=null;
- }
- is.item=(oldCurrent.item+1);//生成k—项候选集,由两个k-1项频繁集生成
- is.items.or(oldCurrent.items);//将k-1项集合并
- is.items.or(oldNext.items);//将k-1项集合并
- is.trans.or(oldCurrent.trans);//将bs1的值复制到bs中
- is.trans.and(oldNext.trans);
- is.supports=is.trans.cardinality();
- writeToFile(is.items,is.supports);//将频繁项集及其支持度写入文件
- countItems++;
- modSum++;
- newLast.next=is;
- newLast=is;
- }
- }
- oldNext=oldNext.next;
- }
- oldCurrent=oldCurrent.next;
- }
- ItemSettemp1=hn.first;
- ItemSettemp2=hn.last;
- temp2.next=shareFirst.next;
- shareFirst.next=temp1;
- hn.first=newFirst.next;
- hn.last=newLast;
- hn.items=countItems;
- }
- publicbooleancontainItems(BitSetcontainItems,BitSetbsItems2,ItemSetfirst)
- {
- longsize=containItems.cardinality();//项集数目
- intitemSum=0;
- inttemp=containItems.nextSetBit(0);
- while(true)
- {
- itemSum+=temp;
- temp=containItems.nextSetBit(temp+1);
- if(temp==-1)
- {
- break;
- }
- }
- inthash=itemSum%(ItemSet.ItemSize*3);
- HashNodehn=hashTable[hash].next;
- Nodepre=hashTable[hash];
- while(true)
- {
- if(hn==null)//不包含containItems
- {
- HashNodenode=newHashNode();
- node.bs.or(containItems);
- pre.next=node;
- returnfalse;
- }
- if(hn.bs.isEmpty())
- {
- hn.bs.or(containItems);
- returnfalse;
- }
- bsItems2.clear();
- bsItems2.or(containItems);
- bsItems2.and(hn.bs);
- if(bsItems2.cardinality()==size)
- {
- returntrue;
- }
- pre=hn;
- hn=hn.next;
- }
- }
- publicvoidclear(HashHeadNode[]hashTable)
- {
- for(inti=0;i<hashTable.length;i++)
- {
- HashNodenode=hashTable[i].next;
- while(node!=null)
- {
- node.bs.clear();
- node=node.next;
- }
- }
- }
- publicvoidwriteToFile(BitSetitems,intsupports)
- {
- StringBuildersb=newStringBuilder();
- //sb.append("<");
- inttemp=items.nextSetBit(0);
- sb.append(temp);
- while(true)
- {
- temp=items.nextSetBit(temp+1);
- if(temp==-1)
- {
- break;
- }
- //sb.append(",");
- sb.append("");
- sb.append(temp);
- }
- sb.append(":"+""+supports);
- try{
- bw.write(sb.toString());
- bw.write("\n");
- }catch(IOExceptione){
- e.printStackTrace();
- }
- }
- publicstaticvoidmain(String[]args){
- EclatReleasee=newEclatRelease();
- longbegin=System.currentTimeMillis();
- e.init();
- e.start();
- longend=System.currentTimeMillis();
- doubletime=(double)(end-begin)/1000;
- System.out.println("共耗时"+time+"秒");
- System.out.println("频繁模式数目:"+EclatRelease.modSum);
- }
- }
- classMyMap<T,E>extendsTreeMap
- {
- publicvoidadd(Tobj)
- {
- if(this.containsKey(obj))
- {
- intvalue=(Integer)this.get(obj);
- this.put(obj,value+1);
- }
- else
- this.put(obj,1);
- }
- }
- packagecom.pku.yhf;
- importjava.util.BitSet;
- publicclassItemSet{
- publicstaticintlimitSupport;//根据阈值计算出的最小支持度数
- publicstaticintItemSize;//Items数目
- publicstaticintTransSize;//事务数目
- publicbooleanflag=true;//true,表示作为真正的ItemSet,false只作为标记节点,只在HashTabel中使用
- publicintitem=0;//某项集
- publicintsupports=0;//项集的支持度
- publicBitSetitems=null;
- publicBitSettrans=null;
- //publicTreeSetitems=newTreeSet();//项集
- //publicTreeSettrans=newTreeSet();//事务集合
- publicItemSetnext=null;//下一个项集
- publicItemSet(booleanflag)
- {
- this.flag=flag;
- if(flag)
- {
- item=0;//某项集
- supports=0;//项集的支持度
- items=newBitSet(ItemSize+1);
- trans=newBitSet(TransSize+1);
- }
- }
- }
对mushroom.dat的频繁模式挖掘结果如下

后期打算实现北大邓志鸿老师提出的PPV-Tree算法(基于节点列表的频繁模式挖掘算法),挖掘速度超过Han Jiawei教授的FP-Growth算法,敬请关注:)