【问题标题】:implement Union-Find Algorithm confusion实现Union-Find算法混淆
【发布时间】:2014-10-21 03:20:54
【问题描述】:

我正在尝试为 Kruskal 实施联合查找算法。我正在使用这个伪代码,我不理解下面的联合部分 step2(它不是递归调用),或者我什至很接近。如果这种方式不起作用,只要我理解它,我可以使用任何实现。提前谢谢。 U 和 V 是我的边缘节点,现在只是整数。

  Init(V)
  1.for every vertex v do
  2.boss[v]=v
  3.size[v]=1
  4.set[v]={v}

  Find (u)
  1.Return boss[u] 

  Union (u,v)
  1.if size[boss[u]]>size[boss[v]] then
  2.set[boss[u]]=set[boss[u]] union set[boss[v]]
  3.size[boss[u]]+=size[boss[v]]
  4.for every z in set[boss[v]] do
  5.boss[z]=boss[u]
  6.else do steps 2.-5. with u,v switched

我不明白第 2 步,这是我目前的代码:

public class UnionFind {

    private int[] _boss;
    private int[] _size;
    private int[] _set;

    public UnionFind(int max) 
    {
        _boss = new int[max];
        _size = new int[max];
        _set  = new int[max];
    }

    public void init(Set<Integer> vertSet)
    {
        //for every vertex do
        int j=0;
        for(int i : vertSet)
        {
            _boss[j]=i;
            _size[j]=1;
            _set[j]=i;
            j++;
        }
    }

    int find(int u)
    {
        return(_boss[u]);
    }

    void union(int u, int v)
    {
        if(_size[_boss[u]]>_size[_boss[v]])
        {
            _set[_boss[u]]=_set[_boss[u]];
             //_set[_boss[v]];
            _size[_boss[u]]+=_size[_boss[v]];

            for(int z=0;z<_boss.length;z++)
            {
                _boss[z]=_boss[u];
            }
        }
        else
        {
            //switch u and v
            _set[_boss[v]]=_set[_boss[v]];
            //union(_set[_boss[v]],_set[_boss[u]]);
            _size[_boss[v]]+=_size[_boss[u]];

            for(int z=0;z<_boss.length;z++)
            {
                _boss[z]=_boss[v];
            }
        }
    }

【问题讨论】:

    标签: java kruskals-algorithm union-find


    【解决方案1】:

    步骤 2 意味着集合 u 现在变成了 u 和 v 的并集,所以你不能分配 set[v] = set[v] (u 和 v 是 boss[u], boss[v] 的缩写,分别)。所以,如果集合 u 是 {u} 并且集合 v 是 {v},经过这一步,集合 u 将是 {u,v},再举一个例子是 set u = {1,2} , set v = {3, 4},因此在此之后,设置 u = {1,2,3,4}。根据您使用的数据结构,您需要以不同的方式实现它。一种方法是使用ArrayList

    ArrayList<Integer> set[] = new ArrayList[max];
    //Initialize each set, add element into set
    for(int i = 0; i < max; i++)
       set[i] = new ArrayList();
       set[i].add(i);
    //For step 2
    set[boss[u]].addAll(set[boss[v]]);
    

    最后一件事是,您的第 4 步是错误的,对于您当前的实现,您只需将每个元素添加到 set[boss[u]] 中,但在这一步中,它们只需要那些在 set[boss[ v]]。所以:

            int bossV = boss[v];//This is important! Answer why this is needed by yourself.
            for(int z=0;z<_boss.length;z++)
            {
                if(boss[z] == bossV)
                   _boss[z]=_boss[u];
            }
    

    小提示:您使用的这个版本不是union-find最快的版本,请尝试阅读更多信息!

    【讨论】:

    • 谢谢,我有关于这个主题的最糟糕的书,除了维基和更好的参考?
    • 那么第2步也是双数组吗?这一点我一定不明白。
    • @DixonSteel 嗯,你可以试试看这个book或者这个经典的one
    • 谢谢,找到了一个更好的版本,可以实现一些压缩,这对我的理解来说更直接。到目前为止,它似乎工作正常。
    猜你喜欢
    • 1970-01-01
    • 2019-08-22
    • 2015-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-06
    • 2011-06-28
    • 1970-01-01
    相关资源
    最近更新 更多