【算法大體描述】c++
Aprior算法主要有兩個操做,掃描數據庫+統計。計算每一階頻繁項集都要掃描一次數據庫而且統計出知足支持度的n階項集。算法
【算法主要步驟】數據庫
1、頻繁一項集ide
算法開始第一步,經過掃描數據庫,統計出每條記錄中出現的每個單獨項並計數,數據庫掃描完成,統計結束,根據支持度,選出知足條件的頻繁一項集 L1。測試
2、鏈接spa
用 Lk-1自鏈接獲得Ck。code
方法,若是Lk-1中的兩個元素的前K-2項都相同,只有最後一項不一樣,則自鏈接獲得Ck中的一個元素。例如L3{(12,13,14),(12,13,15) }則可自鏈接獲得C4{(12 13 14 15)}blog
3、修剪ci
對於自鏈接獲得的Ck,其中有些元素是能夠不用掃描數據庫就能夠肯定它確定不是頻繁項集的。一個k-項集,若是它的一個k-1項集(它的子集 )不是頻繁的,那它自己也不多是頻繁的。get
例如L3{(12 ,13,14),(12,13,15)}自鏈接獲得C4{(12,13,14,15)} 可是(13,14,15)不在L3中,因此能夠確定(12,13,14,15)不是頻繁四項集,不用再去掃描數據庫。
經過修剪,能夠很快的減小Ck中的元素,減小數據庫的掃描次數,大大加快效率。
4、掃描數據庫獲得頻繁k項集Lk
將已經修剪過的Ck中的每個元素拿到數據庫中去找,統計出現次數,根據支持度獲得結果。
C++源碼
#include<bits/stdc++.h> #include<string> #include<vector> #include<map> using namespace std; vector <string> result; map<string,int>r1; float suport; vector<string> file; void Getfile(){ ifstream ifile("D://retail.dat"); if(!ifile){ cout<<"open file error"<<endl; } else{ string temp; while(getline(ifile,temp)){ file.push_back(temp); } } ifile.close(); } bool IsrealCk(vector<string>& Lk ,vector<string> &str){//判斷str的子集是否在Lk-1中 string temp; int i; for( i=0;i<str.size();i++){ temp.clear(); for(int j=0;j<str.size();j++){//Cn 1 if(j!=i){ temp+=str[j]; temp.push_back(','); } }//生成一個子集 temp.erase(temp.size()-1); int k; for( k=0;k<Lk.size();k++){// if(Lk[k]==temp) break; } if(k>=Lk.size()){//不在Lk break; } } if(i>=str.size()) return 1; else return 0; } vector<string> minCK(vector<string>& Lk,vector<string>& Ck){//剪枝 (12,45,32) vector<string> minck; vector<string> str; for(int i=0;i<Ck.size();i++){ string s; str.clear(); for(int j=0;j<Ck[i].size();j++){ while(Ck[i][j]!=','&&j<Ck[i].size()){ s.push_back(Ck[i][j]); j++; } str.push_back(s); s.clear(); } if(IsrealCk(Lk,str)){ minck.push_back(Ck[i]); } } return minck; } vector<string> GetL1_C2(){ vector <string> L1; vector<int> count; vector<string> l1; vector<string> C2; string temp; int line=0; string lk; for(int f=0;f<file.size();f++){ temp=file[f]; line++; int i; for( i=0;i<temp.size();i++){ while(temp[i]!=' '&&temp[i]!='\n'&&i!=temp.size()){ lk+=temp[i]; i++; } if(r1.find(lk)!=r1.end()) r1[lk]++; else r1[lk]=1; lk.clear();// } } temp.clear(); map<string,int>::iterator it; for(it=r1.begin();it!=r1.end();it++){//待刪除 if(it->second>=ceil(suport*line)){ cout<<it->first<<" ("<<it->second<<")"<<endl; result.push_back(it->first); } } for(int i=0;i<result.size();i++){ for(int j=i+1;j<result.size();j++){ string c2=result[i]+","+result[j]; C2.push_back(c2); } } return C2; } vector<string> CK(vector<string>& L){ vector<string> Ck;//k+1候選像集 vector<string> minck; for(int i=0;i<L.size();i++){ for(int j=i+1;j<L.size();j++){ if(i!=j){ string temp1,temp2; int m1,m2; for(m1=L[i].size()-1;m1>0;m1--){ if(L[i][m1]==',') break; } temp1=L[i].substr(0,m1+1); for(m2=L[j].size()-1;m2>0;m2--){ if(L[j][m2]==',') break; } temp2=L[j].substr(0,m2+1); if(temp1==temp2){//能夠鏈接 string lk=temp1; for(int x=m1+1;x<L[i].size();x++) { lk.push_back(L[i][x]); } lk.insert(lk.end(),','); for(int x=m2+1;x<L[j].size();x++) { lk.push_back(L[j][x]); } Ck.push_back(lk);//加入候選項 } } } } // minck=minCK(L,Ck); return minck=minCK(L,Ck); } bool Isin(string& temp,string& str){ int j; string s; for( j=0;j<temp.size();j++){//遍歷temp while(temp[j]!=' '&&j<temp.size()){ s.push_back(temp[j]); j++; } if(s==str) break; s.clear(); } if(j>=temp.size()) return 0; else return 1; } vector<string> GetLk(vector<string>& Ck){ map<string,int> Lk; string temp; int flag=0; int line=0; for(int f=0;f<file.size();f++){ temp=file[f]; line++;int t=0; vector<string> str; for(int i=0;i<Ck.size();i++){ string s;//記錄單個元素 12,32 s=12 str.clear(); for( int j=0;j<Ck[i].size();j++){//遍歷 12,34 while(Ck[i][j]!=','&&j<Ck[i].size()){ s.push_back(Ck[i][j]); j++; } str.push_back(s); s.clear(); } int p; for( p=0;p<str.size();p++){ if(!Isin(temp,str[p])) break; } if(p>=str.size()){//在temp中出現 if(Lk.find(Ck[i])!=Lk.end()) Lk[Ck[i]]++; else Lk[Ck[i]]=1; } } } /*********/ temp.clear(); vector<string> ck; map<string,int>::iterator it; for( it=Lk.begin();it!=Lk.end();it++){//待刪除 if(it->second>=ceil(suport*line)){ ck.push_back(it->first); } } return ck; } void Apri(vector<string>& Ck){ if(Ck.size()<1){ return ; } else{ vector<string> temp=GetLk(Ck); if(temp.size()<1) return; else{ for(int i=0;i<temp.size();i++){ result.push_back(temp[i]);//記錄Lk } vector<string>nextck= CK(temp); Apri(nextck); } } } int main(){ cout<<"請輸入最小支持度"<<endl; cin>>suport; Getfile(); int c=0; vector<string> C2=GetL1_C2(); Apri(C2); cout<<"頻繁項集以下:"<<endl; for(int i=0;i<result.size();i++){ cout<<result[i]<<endl; c++; } cout<<" count "<<c<<endl; return 0; }
測試文件(有八萬多條記錄,測試代碼建議跑0.1支持度)
https://pan.baidu.com/s/1Lp7LJOXksIRh3KBra2iVIw