在Java中对图形的边缘(基于Adjacency List表示)进行排序

时间:2014-07-12 07:02:35

标签: java sorting data-structures graph minimum-spanning-tree

我有一个图表,使用HashMap存储它的边缘如下:

HashMap<Integer,LinkedList<Node>> adj;

其中定义了Node;

class Node
{
   int number;
   int weight;
}

例如

  • 0:&lt; 1,55&gt; - &GT; &LT; 2,54&GT; //节点0连接到具有边缘权重55的节点1和具有边缘权重54的节点2
  • 1:&lt; 0,43&gt; - &GT; &LT; 2,44&GT; //节点1连接到节点0,边缘权重43和节点2 边重44

我需要按重量排序顺序获取边缘列表,我不知道如何去做。我正在尝试实施Kruskal的MST。

是否可以对我定义的图表进行排序?如果没有,请建议更好的存储方式。

2 个答案:

答案 0 :(得分:4)

让我们首先创建一个Edge类:

class Edge implements Comparable<Edge> { // Important: must implement Comparable. More on this later
    public Node first; // first connected node
    public Node second; // second connected node
    public int weight; // move edge weight to Edge class

    @Override
    public int compareTo(Edge e) {
        if (weight < e.weight) {
            return -1;
        } else if (weight > e.weight) {
            return 1;
        } else {
            return 0;
        }
    }
}

由于weight类位于Edge类,Node中不需要它,因此您可以删除它:

class Node {
    public int number;
    // add more variables later is you need here
}

现在,对于你的程序(如果没有要求),我会像这样定义你的列表:

HashMap<Node, List<Edge>> adj; // use any list implementation you want

这将在您的程序中代表这样的图形(从您的示例中复制):

  • 节点0:边缘(节点0,节点1,55),边缘(节点0,节点2,54)
  • 节点1:边缘(节点1,节点0,43),边缘(节点1,节点2,44)

要回答您的问题,让我们找到按边缘权重排序的边缘:

ArrayList<Edge> sortedEdges = new ArrayList<Edge>();
for (List<Edge> connectedEdges : adj.values()) {
    sortedEdges.addAll(connectedEdges);
}
Collections.sort(sortedEdges);

这只需要Edge中的所有adj并将它们全部放在一个列表中,然后根据它们的权重对它们进行排序(因为我们将Edge扩展为Comparable<Edge> })。根据{{​​3}},sort()方法使用合并排序,该排序在O(nlog(n))时间内运行:

  

实现注意事项:此实现是一个稳定的,自适应的迭代合并输出,当输入数组被部分排序时,需要远远少于n lg(n)的比较,同时在输入数组随机排序时提供传统mergesort的性能

Edge获取所有adj.values的列表需要O(n)时间(请参阅Javadoc on Collections.sort()),因此获取按重量排序的边列表的总时间复杂度将是O(n) + O(nlog(n)) = O(nlog(n))

所以你去吧。我希望这有助于:)

答案 1 :(得分:0)

如果您可以自由更改节点的表示方式,我建议您更改它。目前,Node类实际上代表了一个边(并且一个节点由Integer表示,即adj变量的键。

例如,以下似乎更自然:

Set<Node> nodes = new HashSet<>(); // The enclosing class keeps track of all nodes.

// Represents each node.
class Node {
    int nodeId = /* ... */;

    // The Node class keeps track of its neighbors, sorted by their weights.
    SortedMap<Integer,Node> edges = new TreeMap<>(Collections.reverseOrder());
}

然后,每当你需要按重量的降序做事时,你可以这样做:

void method(Node node) {
    Iterator<Integer> iter = node.edges.keySet().iterator(); // Iterates in descending order.
    while(iter.hasNext()) {
        int weight = iter.next();
        Node neighbor = node.edges.get(weight);

        doSomething( /* ... */ );
    }
}