c语言并查集,并查集的C语言实现

-设S1= {0, 6,

7, 8 },S2= { 1, 4, 9 },S3= { 2, 3, 5

}

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

-为简化讨论,忽略实际的集合名,仅用表示集合的树的根来标识集合。  -为此,采用树的双亲表示作为集合存储表示。集合元素的编号从0到n-1。其中n是最大元素个数。在双亲表示中,第i个数组元素代表包含集合元素i的树结点。根结点的双亲为-1,表示集合中的元素个数。为了区别双亲指针信息(

≥ 0 ),集合元素个数信息用负数表示。

下标a4c26d1e5885305701be709a3d33442f.pngparent

集合S1,

S2和S3的双亲表示:a4c26d1e5885305701be709a3d33442f.png

#include

using namespace std;

int up[10000];

int rank[10000];

void makeset(int x)

{

up[x]=-1; //表示x是树根

rank[x]=0;

}

int find(int x)

{

int r=x;

while(up[r]!=-1) /获得根节点r

r=up[r]; //类似链表中的r=next[r]的意思,这里是向根节点移动

while(x!=r) //路径压缩

{

int t=up[x]; //先保存x的父节点

up[x]=r; //把x指向r,也就是说x的父节点变成r

x=t; //x向上移动

}

return r;

}

void join(int a,int b)

{

int root1=find(a);

int root2=find(b);

if(rank[root1]>rank[root2])

{

up[root2]=root1; //root1成为root2的父节点

}

else

up[root1]=root2;

if(rank[root1]==rank[root2])

rank[root2]++;

}

int

main()

{

int

i,a,b,c,d;

while(cin>>N>>M)

{

for(i=1;i<=N;i++)

makeset(i);

for(i=1;i<=M;i++)

{

cin>>a>>b;

if(find(a)!=find(b))

unionone(a,b);

}

cin>>Q;

for(i=1;i<=Q;i++)

{

cin>>c>>d;

if(find(c)==find(d))

cout<

else

cout<

}

}

return

0;

}

接下来一篇树来实现

typedef

struct uf_n_t

{

int

rank;

item_t

*item;

struct

uf_n_t *up;

}uf_node_t;

uf_node_t  *insert(item_t

*new_item)

{

uf_node_t

*new_node;

new_node=get_node();

new_node->item=new_item;

new_node->rank=0;

new_node->up=NULL;

return

(new_node);

}

int

same_class(uf_node_t  *node1,uf_node_t

*node2)

{

uf_node_t  *root1, *root2,

*tmp;

for(root1=node1;root1->up!=NULL;root1=root1->up)

;

for(root1=node2;root2->up!=NULL;root2=root2->up)

;

while()

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值