UNION-FIND算法

来源:互联网 发布:淘宝洋垃圾服装 编辑:程序博客网 时间:2024/05/16 18:42

算法解释

输入的数据是一个整数,和整数对应的数组对。判断是否相连接,如果不连接则输出并且连接在一起。

算法的实现

UF(int N) 以整数标识(0-N-1)个触点void union(int p, int q) 在p和q之间添加一条连接boolean connected(int p, int q); 如果pq相连接则返回trueint count()返回连通分量的数量,就是未连接点的数量

实现API的方法


  • UF(int N)

这个用来初始化分量id数组
public UF(int N){    count = N;    id = new int[N];    for(int i = 0; i < N; i++)        id[i] = i;}


  • int count

返回连通的数量
public int count(){    return count;}


  • connected(int p, int q)

判断两个节点是否相互连接
public booloean connected(int p, int q){    return find(p) == find(q);}

find()方法和union()方法思想的版本1


  • 算法实现的思想

当保证当仅当id[p]等于id[q]的时候,p和q是连通的。连通的点对应的id[]的值是相同的。所以find方法就是返回其对应的id[]值。
将两者对应的id值合二为一,就能将两点连通。因为一个点是在集合中,所以对应将数组id的值全部修改
public int find(int p){    return id[p];}public void union(int q, int p){    int qID = find(q);    int pID = find(p);    if(pID == qID) return;  //如果p,q已经在同一分量中,不需要任何动作    //归并分量,将p的分量重新命名为q的分量    for(int i = 0; i < id.length; i++)        if(id[i] == pID) id[i] = qID;    count--;}


  • 算法分析

每次调用一次就需要访问数组一次,union()操作调用只需要访问数组的次数在(N+3)和(2*N+1)之间。至少会调用N-1次union算法。所以时间复杂度是o(n^2)

find方法和union方法实现版本2

  • 实现思想

    以触点作为索引的id[]数组,和上述方法不同,它存放的是下一个节点的id值。实现find()方法时候,我们从给定的触点开始,得到另一个触点,在通过这个触点得到下一个触点,如此类推直到到达一个根触点(链接指向自己的触点)
    union算法的实现:union(p, q)的实现,我们由p和q的链接分别找到它们的根节点,然后将一个根触点链接到另一个根触点即可。

  • 算法

private int find(int p){    //找出分量的根节点    while(p != id[p]) p = id[p];    return p;}public void union(int p, int q){    //将p和q的根节点统一    int pRoot = find(p);    int qRoot = find(q);    if(pRoot == qRoot) return;    id[pRoot] = qRoot;//p指向q    count--;}


  • 时间复杂度分析

在最好的情况下,find()方法只需要访问数组一次就能得到一个触点的标识符
在最坏的情况下,需要2n+1次数组访问
所以最佳情况是线性级别,最坏情况下是平方级别的。

版本三

记录每一颗树的大小,并且将小的那一课树链接到较大的那一颗树上。每一个节点都有三个值,是其的地址值(数组对应的下标,不可变),其本身的内容和其指向的数字(id数组中的值)

public int find(int q){    while(p != id[p]) p = id[p];    return p;//找到根节点的本身内容}public void union(int p, int q){    int i = find(p);    int j = find(q);    if(i == j) return;//是同一个树中的,证明已经通    if(sz[i] < sz[j]){id[i] = j; sz[i] += sz[j];}    else {id[j] = i; sz[i] += sz[j];}    count--;}


  • 时间复杂度

处理N个节点和M个链接时候,最多访问数组MlogN,因为是保证都是树形,所以find()访问数组的个数是logN次。

原创粉丝点击