我有一个图表,使用HashMap存储它的边缘如下:
HashMap<Integer,LinkedList<Node>> adj;
其中定义了Node;
class Node
{
int number;
int weight;
}
例如
我需要按重量排序顺序获取边缘列表,我不知道如何去做。我正在尝试实施Kruskal的MST。
是否可以对我定义的图表进行排序?如果没有,请建议更好的存储方式。
答案 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
这将在您的程序中代表这样的图形(从您的示例中复制):
要回答您的问题,让我们找到按边缘权重排序的边缘:
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( /* ... */ );
}
}