【数据结构笔记】8:并查集:并时加权/查后折叠

来源:互联网 发布:什么叫人工智能技术 编辑:程序博客网 时间:2024/06/09 19:44

并查集可以看成一个多棵树组成的森林,它用双亲表示数组来存储。属同一棵树的元素属于同一等价类。

加权规则:在合并(Union())时小树挂在大树上,以避免树结构的过度退化。

折叠规则:在查找(Find())后将所查元素的路径上的所有元素回序挂在树根上,以改善树的性能,减少以后查找所需的时间。


*树的双亲表示数组节点类ElemNode.h

//树的双亲表示数组的节点struct ElemNode{char data;//数据域int parent;//双亲域};

*并查集森林UFSets.h

#include "ElemNode.h"#include <iostream>using namespace std;//并查集森林class UFSets{protected:ElemNode *sets;//并查集树的双亲表示数组int size;//数组长度public:UFSets(char es[],int n);//构造器void Show();//显示/*重要的函数*/int GetOrder(char e)const;//取指定元素下标int Find(char e);//取指定元素所在等价类根下标void Union(char a,char b);//合并所在等价类bool Differ(char a,char b);//判断是否在同一等价类};//构造器UFSets::UFSets(char es[],int n){size=n;//设置数组长度sets=new ElemNode[size];//分配空间for(int i=0;i<size;i++)//两个域都要初始化{sets[i].data=es[i];//对象的名称sets[i].parent=-1;//每个对象开始都自己是一个等价类}}//显示双亲表示数组void UFSets::Show(){for(int i=0;i<size;i++){cout<<"["<<sets[i].data<<","<<sets[i].parent<<"]";}}//取指定元素下标int UFSets::GetOrder(char e)const{int i;for(i=0;i<size;i++)if(sets[i].data==e)return i;//找到返回下标return -1;//没找到返回-1}//查:指定元素所在等价类根下标(带折叠规则)int UFSets::Find(char e){int p=GetOrder(e);//取e下标给pif(p==-1)return -1;//没有e故也找不到根int i=p;//i用来向上找i的根while(sets[i].parent>-1)//双亲非负时i=sets[i].parent;//游标i向双亲走//return i;//不做折叠时在这返回等价类根下标//折叠规则:查找路径上的子树回序挂到根上去if(p!=i)//为根时什么都不做{while(sets[p].parent!=i)//p向上走,还没连到根i时{int k=sets[p].parent;//记录p双亲游标sets[p].parent=i;//p挂到i上去p=k;//p再变为其双亲(回序走)}}return i;//返回等价类根下标}//并:两元素所在等价类(带加权规则)void UFSets::Union(char a,char b){int r1=Find(a);//a所在等价类根下标int r2=Find(b);//b所在等价类根下标if(r1!=-1 && r2!=-1 && r1!=r2)//两个根都找到且不同时可做合并{int temp=sets[r1].parent+sets[r2].parent;//记录两根parent域之和//加权规则:小树挂大树if(sets[r1].parent<=sets[r2].parent)//r2为小树{sets[r2].parent=r1;//小树的根挂在大树根上sets[r1].parent=temp;//大树元素数目(的相反数)更新}else//r1为小树{sets[r1].parent=r2;//小树的根挂在大树根上sets[r2].parent=temp;//大树元素数目(的相反数)更新}}}//判断是否在同一等价类bool UFSets::Differ(char a,char b){if(Find(a)==-1||Find(b)==-1)return 0;//有一个找不到都返回0return Find(a)==Find(b) ? 1 : 0;//都找到且相等返回1}

*测试程序

#include "UFSets.h"int main(){char a[]={'A','B','C','D','E','F','G','H','I','J'};UFSets b(a,10);char k;char m,n;while(1){cout<<endl<<"1.合并";cout<<endl<<"2.判同";cout<<endl<<"3.查找";cout<<endl<<"4.显示";cout<<endl<<"其它.结束"<<endl;cin>>k;switch(k){case '1':cout<<"输入char类型m n:";cin>>m>>n;b.Union(m,n);break;case '2':cout<<"输入char类型m n:";cin>>m>>n;if(b.Differ(m,n)==1)cout<<"YES";elsecout<<"NO or N/A";break;case '3':cout<<"输入char类型m:";cin>>m;cout<<b.Find(m);break;case '4':b.Show();break;default:cout<<"程序结束";return 0;}}}

运行结果:




原创粉丝点击