2

对于我的 CS 类,我需要在 Java 中实现 Prim 算法,并且我在优先级队列步骤中遇到问题。我有优先级队列的经验,并且了解它们通常可以工作,但我在某个特定步骤时遇到了麻烦。

Prim(G,w,r)
  For each u in V[G]
    do key[u] ← ∞ 
       π[u] ← NIL  
  key[r] ← 0
  Q ← V[G]  
  While Q ≠ Ø
    do u ← EXTRACT-MIN(Q)
       for each v in Adj[u]
            if v is in Q and w(u,v) < key[v]
                 then π[v] ← u
                       key[v] ← w(u,v)

我创建了一个包含键值(我假设它是连接到节点的最轻的边缘)和父节点的节点类。我的问题是我不明白将节点添加到优先级队列中。当父节点设置为 NIL 并将键设置为 ∞ 时,将所有节点添加到优先级队列对我来说没有意义。

4

3 回答 3

2
于 2009-04-20T00:27:38.233 回答
2

如果你不想使用 PriorityQueue,这里是我在 Java 中的 Heap 实现。你可以用 MinHeap 替换 PriorityQueue。

package algo2;

import java.io.DataInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;

public class Prims {

private static final class GNode implements Comparable<GNode> {
    // unique id of the node
    int id;

    // map of child nodes and their respective distance from current node 'id'
    Map<GNode, Integer> children = new HashMap<GNode, Integer>();

    // used in future computation, to store minimal/optimal updated distance
    int distFromParent=0;

    public GNode(int i) {
        this.id=i;
    }

    @Override
    public int compareTo(GNode o) {
        return this.distFromParent-o.distFromParent;
    }

    @Override
    public String toString() {
        return "GNode [id=" + id + ", distFromParent=" + distFromParent
                + "]";
    }
}

static long findLengthOfMST(GNode[] nodes) {
    PriorityQueue<GNode> pq = new PriorityQueue<GNode>();
    boolean[] visited = new boolean[nodes.length];
    boolean[] exited = new boolean[nodes.length];
    pq.add(nodes[1]);
    visited[1] = true;
    long sum = 0;
    int count = 0;
    while (pq.size() > 0) {
        GNode o = pq.poll();
        if (!exited[o.id]) {
            for (GNode n : o.children.keySet()) {
                if (exited[n.id]) {
                    continue;
                }
                if (visited[n.id]) {
                    if (n.distFromParent >= o.children.get(n)) {
                        n.distFromParent = o.children.get(n);
                    }
                } else {
                    visited[n.id] = true;
                    n.distFromParent = o.children.get(n);
                    pq.add(n);
                }
            }
            sum += o.distFromParent;
            exited[o.id] = true;
            count++;
        }
        if (pq.size() == 0) {
            for (int i = 1; i < nodes.length; i++) {
                if (!exited[i]) {
                    pq.add(nodes[i]);
                }
            }
        }
    }
    System.out.println(count);
    return sum;
}

public static void main(String[] args) {
    StdIn s = new StdIn(System.in);
    int V = s.nextInt();
    int E = s.nextInt();
    GNode[] nodes = new GNode[V+1];
    for (int i = 0; i < E; i++) {
        int u = s.nextInt();
        int v = s.nextInt();
        GNode un = nodes[u];
        GNode vn = nodes[v];
        if (un == null) {
            un = new GNode(u);
            nodes[u] = un;
        }
        if (vn == null) {
            vn = new GNode(v);
            nodes[v] = vn;
        }

        int w = s.nextInt();
        un.children.put(vn, w);
        vn.children.put(un, w);
    }
    long len = findLengthOfMST(nodes);
    System.out.println(len);
}

private static class StdIn {
    final private int BUFFER_SIZE = 1 << 17;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;
    public StdIn(InputStream in) {
    din = new DataInputStream(in);
    buffer = new byte[BUFFER_SIZE];
    bufferPointer = bytesRead = 0;
    }
    public int nextInt() {int ret = 0;byte c = read();while (c <= ' ')c = read();boolean neg = c == '-';if (neg)c=read();do{ret=ret*10+c-'0';c = read();} while (c>' ');if(neg)return -ret;return ret;}
    private void fillBuffer(){try{bytesRead=din.read(buffer,bufferPointer=0,BUFFER_SIZE);}catch(Exception e) {}if(bytesRead==-1)buffer[0]=-1;}
    private byte read(){if(bufferPointer == bytesRead)fillBuffer();return buffer[bufferPointer++];}
    }
}
于 2012-12-08T12:21:59.017 回答
1

您不必担心将所有节点添加到优先级队列中,即使它们具有无限键;它们最终会在伪代码的最后一行被 DECREASE_KEY 降低。无论如何你都需要这个操作,所以没有理由不简化你的生活并一次性插入它们。

我只看到您的伪代码存在一个问题,即它在断开连接的图形上会表现得很奇怪。

于 2009-04-20T00:02:32.067 回答