不相交集(DisjointSet)

<DisjointSet.h>

#include<iostream>
#include<vector>
using namespace std;
/************************************************
*    类名称:不相交集合类DisjointSet 
************************************************/
class DisjointSet
{
public:
//将构造函数声明为explicit,来防止隐式类型转换。
        //explicit关键字只能用于类内部的构造函数声明上,而不能用在类外部的函数定义上
DisjointSet();
DisjointSet(int n);
~DisjointSet(){ delete[]parent; }
void unionSets(int root1,int root2); //合并
void unionSetsBySize(int root1,int root2); //按树大小合并
void unionSetsByHeight(int root1,int root2);  //按树高度合并 
int find(int x)const;    //查找
void print() ; //输出各个不相交集合类中的元素 
private:
   void print(int x);  
//定义了一个 整型的动态数组,用于保存不相交集 
int size;
int *parent;
// vector<int> s;  //存放每个元素的根节点或父节点 
};
/*********************************************************
*     函数名称: DisjointSet(int n)
*     功能描述: 构造函数,同时对每个元素进行集合初始化
*     参数列表: n 是集合中的个数
*     返回值:   无
*********************************************************/
DisjointSet::DisjointSet(int n)
{
//参数是不相交集的规模。
//构造函数根据用户指定的规模申请一个动态的数组。
//初始时,所有的数据元素之间都没有任何关系,
//每个元素都是一个独立的子集
//将所有的父结点设为-1 


size=n;
parent=new int[size];


for (int i = 0; i<size; ++i) parent[i] = -1;
}


//析构函数函数释放动态数组的空间,它作为内联函数直接定义在类定义中


//Find函数,采用了路径压缩方案,从被查找结点到根结点的路径上的所有结点的父结点都将被改为根结点
//利用递归函数调用时的回溯过程,将根结点的下标赋给路径上的各个结点
/**int DisjointSet::Find(int x)
{
   if(parent[x]<0) return x;


  return parent[x]=Find(parent[x]);


}
*/
//Union函数,按规模并的方法。
//它的参数是两颗待归并的树的树根。函数首先比较两棵树是否为同一棵树
//如果是,则返回。否则判断哪棵的规模大。(树的规模是用负值便是的,因此规模越大,根结点的值越小)
/**void DisjointSet::Union(int root1,int root2)
{
if(root1==root2) return;


if(parent[root1]<parent[root2])
{
parent[root1] +=parent[root2];
parent[root2]=root1;
}
else
{
parent[root2]+=parent[root1];
parent[root1]=root2;
}


}  */
/*******************************************************
*        函数名称: print
*        功能描述: 打印集合中的元素
*        参数列表: 无
*        返回结果: void
*******************************************************/
void DisjointSet::print()
{
cout << "输出不相交集合类(每行表示一个相交集合):" << endl;
cout << "s:";


for (int i = 0; i<size; ++i)
{
cout << parent[i] << " ";
}
cout << endl;
for (int i = 0; i<size; ++i)
{
if (parent[i]<0)
{
print(i);
cout << endl;
}
}
}


/*******************************************************
*         函数名称:print(int x)
*         功能描述: 打印元素x
*         参数列表:   x  要打印的元素
*         返回结果: void
*******************************************************/
void DisjointSet::print(int x)
{
cout << x << " ";
for (int i = 0; i < size; ++i)
{
if (parent[i] == x)  print(i);
}
}


/*******************************************************
*         函数名称:find(int x) const
*         功能描述: 查找x处于集合中的名字
*         参数列表:   x  要查找的元素
*         返回结果: 返回元素x的集合名字
*******************************************************/
int DisjointSet::find(int x)const
{
if (parent[x]<0) return x;


return parent[x] = find(parent[x]);
cout << "元素的集合名字"<<x<<endl;
}


/*******************************************************
*         函数名称:unionSets(int root1,int root2)
*         功能描述: 合并两个集合
*         参数列表:  root1 表示集合1,root2 表示集合2
*         返回结果: void
*******************************************************/
void DisjointSet::unionSets(int root1, int root2)
{
if (root1 == root2) return;


parent[root2] = root1;
}


/*******************************************************
*         函数名称:unionSetBySize(root1,root2)
*         功能描述: 按集合大小合并两个集合,使得较小的树成为较大的树的子树
*         参数列表:   root1 表示集合1,root2 表示集合2
*         返回结果: void
*******************************************************/
void DisjointSet::unionSetsBySize(int root1, int root2)
{
if (parent[root2]<parent[root1]){    //root2树比较大 
parent[root2] += parent[root1];        //更新树的大小
parent[root1] = root2;          //root1的父节点变为root2 
}
else{
parent[root1] += parent[root2];
parent[root2] = root1;
}
}
/*******************************************************
*         函数名称:unionSetHeight(root1,root2)
*         功能描述: 按集合高度合并两个集合,使得较小的树成为较大的树的子树
*         参数列表:   root1 表示集合1,root2 表示集合2
*         返回结果: void
*******************************************************/
void DisjointSet::unionSetsByHeight(int root1, int root2)
{
if (parent[root2]<parent[root1]){   //root2树比较高 
parent[root1] = root2;     //直接合并,root1成为root2树的子树 


}
else{        //root1树比较高,或相等 
//如果相等则更新树的高度 
if (parent[root1] == parent[root2])
{
parent[root1]--;
parent[root2] = root1;
}
}
}

<main.cpp>

#include<iostream>
#include"DisjointSet.h"


using namespace std;


int main(){
     cout<<"任意合并:"<<endl;
     DisjointSet dj(8);
     dj.unionSets(4,5);
     dj.unionSets(6,7);
     dj.unionSets(4,6);
     
     dj.print();
       
cout << "按大小合并:" << endl;
DisjointSet dj2(8);
dj2.unionSetsBySize(4, 5);
dj2.unionSetsBySize(6, 7);
dj2.unionSetsBySize(4, 6);
dj2.unionSetsBySize(3, 4);


dj2.print();


cout << "按高度合并:" << endl;
DisjointSet dj3(8);
dj3.unionSetsByHeight(4, 5);
dj3.unionSetsByHeight(6, 7);
dj3.unionSetsByHeight(4, 6);
dj3.unionSetsByHeight(3, 4);


dj3.print();


system("pause");
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值