FP-tree c++实现(求强规则)

最近刚学完FP-tree,写个简单的实现巩固一下。其中原始项目集只能以字符串的形式读入,输出结果为强规则,中间过程的条件模式基以及频繁模式都可以输出。

知识点:

1.理清楚FP-tree算法流程(这个是必须的)。

2.递归求string的所有子序列。

3.树的灵活运用。(多叉树,father指针,特定结点链表指针)

优点:

实现的还是很详细的,每个小阶段的结果都可以输出。另外使用的方法都是比较简单易懂的。

缺点:

代码技巧性不足导致效率较低。

运行截图:

#include <bits/stdc++.h>

using namespace std;

struct cmp1{
	bool operator()(const pair<char,int> a,const pair<char,int> b){
		if(a.second == b.second)return a.first > b.first;
		return a.second < b.second;
	}
};

priority_queue<pair<char,int>,vector<pair<char,int> >,cmp1>Qt;//用于数据内部排序 
stack<string> St,S;//存储预处理前数据。预处理后数据 
map<char,int>M,hd;//用于统计数据出现次数。记录头指针的编号。
map<string,int>FP;//用于存频繁模式 

//-----------------------------------树相关结构及函数定义----------------------------------------
typedef struct Node* node;

node head[10005];

struct Node {//结点定义 
	char key;
	int value;
	node next,father;
	vector<node> child;
};


node CreateNode(char _key,char _value){//创建结点 
	node p = new Node;
	p->key = _key;
	p->value = _value;
	p->father = p->next = NULL;
	return p;
}

node getNode(char _key,char _value,node _father){//得到处理后的结点 
	node p = CreateNode(_key,_value);
	p->father = _father;
	p->next = head[hd[_key]];
	head[hd[_key]] = p;
	return p;
}

void SolveDate(string s,node rt){//将数据转换到树上
	node p = rt; 
	for(int i=0 ; i<s.length() ; ++i){
		if((p->child).empty()){
			(p->child).push_back(getNode(s[i],1,p));
			p = (p->child).back();
		}
		else {
			vector<node>::iterator it;
			for(it=(p->child).begin() ; it!=(p->child).end() ; ++it){
				if((*it)->key == s[i]){
					(*it)->value++;
					p = *it;
					break;
				}
			}
			if(it == (p->child).end()){
				(p->child).push_back(getNode(s[i],1,p));
				p = (p->child).back(); 
			}
		}
	}
}

int Combination2(string s,int temp,int num,string a,string b,int ZCD,double MC){//求关联规则时求string的所有子序列 
	if(s.length()-temp < num)return 0;
	if(temp == s.length()){//这里不能num==0就停,因为b串未全。 
		if(FP.find(a) == FP.end() || FP[a] < ZCD)return 0;
		if(FP.find(b) == FP.end() || FP[b] < ZCD)return 0;
		double de = 1.0*FP[s]/FP[a];
		if(de >= MC){
			cout << s << " " << a << "-->" << b << " " << de << endl;
			return 1;
		} 
		return 0;
	}
	int ans = 0;
	if(num)ans += Combination2(s,temp+1,num-1,a+s[temp],b,ZCD,MC);
	ans += Combination2(s,temp+1,num,a,b+s[temp],ZCD,MC);
	return ans;
}

void Combination(string s,int temp,char ch,int val,int num,string t){//求频繁模式时求string的所有子序列 
	if(s.length()-temp < num)return ;
	if(num == 0){
		priority_queue<pair<char,int>,vector<pair<char,int> >,cmp1>qt;
		for(int i=0 ; i<t.length() ; ++i)qt.push(make_pair(t[i],M[t[i]]));
		qt.push(make_pair(ch,M[ch]));
		t = "";
		while(!qt.empty()){
			t += qt.top().first;
			qt.pop();
		}
		if(FP.find(t) == FP.end())FP[t] = val;
		else FP[t] += val;
		return ;
	}
	Combination(s,temp+1,ch,val,num-1,t+s[temp]);
	Combination(s,temp+1,ch,val,num,t);
}

void getFP(string s,char ch,int val){//求频繁模式
	for(int i=1 ; i<=s.length() ; ++i){
		Combination(s,0,ch,val,i,"");
	}
}

void getCPB(){//求条件模式基 
	for(int i=1 ; head[i]!=NULL ; ++i){
		node p = head[i];
		/*想输出条件模式基的话取消下面3项的注释*/
		//cout << "--项--" << p->key << ":" << endl;// --1 
		char ch = p->key;
		while(p){
			string s = "";
			if(p->father->father){//如果父节点是根跳过 
				node pt = p->father;
				//cout << p->value << ' ';// --2
				while(pt->father){
					s += pt->key;
					pt = pt->father;
				}
				//cout << s << endl;// --3
				getFP(s,ch,p->value);
			}
			p = p->next;	
		}
	}
}
//---------------------------------------------------------------------------------

void init(){//初始化 
	M.clear();
	hd.clear();
	FP.clear();
	while(!St.empty())St.pop();
	while(!S.empty())S.pop();
	while(!Qt.empty())Qt.pop();
	memset(head,NULL,sizeof head);
}

int main(){
	init();
	//--------------------------------------------变量----------------------------------
	int ZCD;//最小支持度阈值 
	double MC;//最小置信度 
	//---------------------------------------------数据获取---------------------------------
	while(true){
		cout << "请输入最小支持度阈值(整数):" << endl;
		cin >> ZCD;
		if(ZCD < 0){
			cout << "输入不合法,请重新输入。" << endl;
			continue;
		}
		cout << "请输入最小置信度(小数):" << endl;
		cin >> MC;
		if(MC < 0.0 || MC > 1.0){
			cout << "输入不合法,请重新输入。" << endl;
		}
		else break;
	}
	cout << "请输入数据:" << endl;
	/*数据预处理测试样例 
	最小支持度阈值为 3。 
	输入数据 
	facdgimp
	abcflo
	bfhjmp
	bckmos
	afcelnop
	处理后数据 
	fcamp
	fcabo
	fbmp
	cbmo
	fcaop
	*/
	string s;
	while(cin >> s){
		St.push(s);
		for(int i=0 ; i<s.length() ; ++i){
			if(M.find(s[i]) == M.end())M[s[i]] = 1;
			else M[s[i]]++;
		}
	}
	//-----------------------------数据预处理--------------------------------------------------
	while(!St.empty()){
		string s1 = St.top();
		St.pop();
		while(!Qt.empty())Qt.pop();
		for(int i=0 ; i<s1.length() ; ++i){
			if(M[s1[i]] >= ZCD)Qt.push(make_pair(s1[i],M[s1[i]]));
		}
		s1 = "";
		while(!Qt.empty()){
			s1 += Qt.top().first;
			Qt.pop();
		}
		if(s1 != "")S.push(s1);
	}
	/*
	输出预处理结果 
	while(!S.empty()){
		cout << S.top() << endl;
		S.pop();
	}
	*/
	//----------------------------------------建立头表-------------------------------------------------
	map<char,int>::iterator it;
	while(!Qt.empty())Qt.pop();
	for(it=M.begin() ; it!=M.end() ; ++it){
		if(it->second < ZCD)continue;
		//------------这里要注意把一阶频繁项加进FP,方便以后求强规则 
		string t = "";
		t += it->first; 
		FP[t] = it->second; 
		//-------------
		Qt.push(make_pair(it->first,it->second));
	}
	int tot = 0;
	while(!Qt.empty()){
		hd[Qt.top().first] = ++tot;
		Qt.pop();
	}
	/*测试头表排序 
	cout << "-----------------" << endl;
	for(it=hd.begin() ; it!=hd.end() ; ++it){
		cout << it->first << " " << it->second << endl;
	}
	*/
	node root = CreateNode('-1',0);//参数随意 
	while(!S.empty()){
		string st = S.top();
		S.pop();
		SolveDate(st,root);
	} 
	getCPB();//求条件模式基 
	
	/*//输出频繁模式 
	cout << "----------------------------------" << endl;
	map<string,int>::iterator it2;
	for(it2=FP.begin() ; it2!=FP.end() ; ++it2){
		if(it2->second >= ZCD){
			cout << it2->first << " " << it2->second << endl;
		}
	}
	*/
	
	cout << "--强关联规则:--" << endl;   
	map<string,int>::iterator it2;
	int ans = 0;
	for(it2=FP.begin() ; it2!=FP.end() ; ++it2){
		if(it2->second < ZCD)continue;
		for(int i=1 ; i<=(it2->first).length() ; ++i){
			ans += Combination2(it2->first,0,i,"","",ZCD,MC);
		}
	}
	cout << "--总共" << ans << "条--" << endl;
	
	
	return 0;
}

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值