简体   繁体   English

带路径压缩算法的加权快速联合

[英]Weighted Quick-Union with Path Compression algorithm

There is a "Weighted Quick-Union with Path Compression" algorithm. 存在“具有路径压缩的加权快速联盟”算法。

The code: 代码:

public class WeightedQU 
{
    private int[] id;
    private int[] iz;

    public WeightedQU(int N)
    {
        id = new int[N];
        iz = new int[N];
        for(int i = 0; i < id.length; i++)
        {
            iz[i] = i;
            id[i] = i;
        }
    }

    public int root(int i)
    {
        while(i != id[i])
        {
            id[i] = id[id[i]];   // this line represents "path compression"
            i = id[i];
        }
        return i;
    }

    public boolean connected(int p, int q)
    {
        return root(p) == root(q);
    }

    public void union(int p, int q)   // here iz[] is used to "weighting"
    {
        int i = root(p);
        int j = root(q);
        if(iz[i] < iz[j])
        {
            id[i] = j;
            iz[j] += iz[i];
        }
        else
        {
            id[j] = i;
            iz[i] += iz[j];
        }
    }
}

Questions: 问题:

  1. How does the path compression work? 路径压缩如何工作? id[i] = id[id[i]] means that we reach only the second ancester of our node, not the root. id[i] = id[id[i]]意味着我们只到达节点的第二个ancester,而不是root。

  2. iz[] contains integers from 0 to N-1 . iz[]包含从0N-1整数。 How does iz[] help us know the number of elements in the set? iz[]如何帮助我们知道集合中元素的数量?

Can someone clarify this for me? 有人可以为我澄清一下吗?

First understand that id is a forest . 首先要明白id是一个森林 id[i] is the parent of i . id[i]是的父i If id[i] == i it means that i is a root. 如果id[i] == i则表示i是根。

For some root i (where id[i] == i ) then iz[i] is the number of elements in the tree rooted at i . 对于一些根i (其中, id[i] == i然后) iz[i]是在根的的元素数i

public int root(int i)
{
    while(i != id[i])
    {
        id[i] = id[id[i]];   // this line represents "path compression"
        i = id[i];
    }
    return i;
}

How does the path compression work? 路径压缩如何工作? id[i] = id[id[i]] means that we reach only the second ancester of our node, not the root. id[i] = id[id[i]]意味着我们只到达节点的第二个ancester,而不是root。

As we are ascending the tree to find the root we move nodes from their parents to their grandparents. 当我们提升树找到根时,我们将节点从父母移动到他们的祖父母。 This partially flattens the tree. 这部分地使树变平。 Notice that this operation doesn't change which tree the node is a member of, this is all we are interested in. This is the path compression technique. 请注意,此操作不会更改节点所属的树,这是我们感兴趣的全部内容。这是路径压缩技术。

(You did notice the loop right? while(i == id[i]) terminates once i is a root node) (你确实注意到循环正确吗? while(i == id[i])一旦i是根节点就终止了)

iz[] contains integers from 0 to N-1 . iz[]包含从0N-1整数。 How does iz[] help us know the number of elements in the set? iz[]如何帮助我们知道集合中元素的数量?

There is a transcription error in the code: 代码中存在转录错误:

for(int i = 0; i < id.length; i++)
{
    iz[i] = i; // WRONG
    id[i] = i;
}

This is the correct version: 这是正确的版本:

for(int i = 0; i < id.length; i++)
{
    iz[i] = 1; // RIGHT
    id[i] = i;
}

iz[i] is the number of elements for a tree rooted at i (or if i is not a root then iz[i] is undefined). iz[i]是在根的树中的元素的数量i (或者如果i不是根然后iz[i]是未定义)。 So it should be initialized to 1 , not i . 所以它应该初始化为1 ,而不是i Initially each element is a seperate "singleton" tree of size 1 . 最初,每个元素都是一个大小为1的单独“单例”树。

id[i] = id[id[i]]; id [i] = id [id [i]]; // this line represents "path compression" //这一行表示“路径压缩”

The above code is "Simpler one-pass variant" as mentioned in the slide of Union Find (Algorithms, Part I by Kevin Wayne and Robert Sedgewick). 上面的代码是“简单的一次通过变量”,如Union Find(Algorithms,第一部分,Kevin Wayne和Robert Sedgewick)的幻灯片中所提到的。 Therefore your guess for question 1 is correct. 因此,您对问题1的猜测是正确的。 Each examined node points to its grandparent. 每个被检查的节点都指向其祖父母。

To make each examined node points to the root we will need two-pass implementation: 要使每个被检查的节点指向根,我们将需要两遍实现:

  /**
 * Returns the component identifier for the component containing site <tt>p</tt>.
 * @param p the integer representing one site
 * @return the component identifier for the component containing site <tt>p</tt>
 * @throws java.lang.IndexOutOfBoundsException unless 0 <= p < N
 */
public int find(int p) {
    int root = p;
    while (root != id[root])
        root = id[root];
    while (p != root) {
        int newp = id[p];
        id[p] = root;
        p = newp;
    }
    return root;
}

Reference: http://algs4.cs.princeton.edu/15uf/WeightedQuickUnionPathCompressionUF.java.html 参考: http//algs4.cs.princeton.edu/15uf/WeightedQuickUnionPathCompressionUF.java.html

Question 1. It is not right to say that the line id[i] = id[id[i]]; 问题1.说id [i] = id [id [i]]行是不对的; only reaches the second ancestor of the root.You will realize that while loop while(i != id[i]) stops only when the node i is pointing at the root ie when i == id[i].By this time we shall have pointed the node to the root using the line id[i] = id[id[i]]; 只会到达root的第二个祖先。你会意识到while while while(i!= id [i])只在节点i指向根时停止,即当i == id [i]时。这次我们应使用行id [i] = id [id [i]]将节点指向根节点; where the inner id[i] is the root. 内部id [i]是根。

Question 2. 问题2。

You are wrong to initialize iz[i] = i; 你错误地初始化iz [i] = i; actually it should be iz[i] = 1; 实际上它应该是iz [i] = 1; meaning, each and every node size is initialized by 1 at the beginning since they are of size 1. In the union function you realize that we have the lines iz[j] += iz[i]; 意思是,每个节点大小在开始时由1初始化,因为它们的大小为1.在union函数中,您意识到我们有行iz [j] + = iz [i]; and iz[i] += iz[j]; 和iz [i] + = iz [j]; which updates the size of the root node to be the sum of the sizes of the two components joined together. 它将根节点的大小更新为连接在一起的两个组件的大小的总和。 This efficiently updates the nodes sizes. 这有效地更新了节点大小。

One more thing to be noted here: 还有一点需要注意:

While finding the root when we are making id[i]=id[id[i]] ie; 在我们制作id[i]=id[id[i]]时找到根; making i under its grand parent 让我在其祖父母之下

-then size of id[i] will decrease by size of ii,e; - 然后id[i]的大小将减小ii,e的大小; iz[id[i]]-=iz[i]

Now this makes code perfectly correct. 现在这使代码完全正确。

I am not sure about this but intuitively i feel, Its absence does not cause problems because we are always comparing size of the roots. 我不确定这一点,但直觉上我觉得,它的缺席不会引起问题,因为我们总是比较根的大小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM