在Java中对图的边进行排序(基于邻接列表表示)
我有一个使用HashMap存储其边的图,如下所示:在Java中对图的边进行排序(基于邻接列表表示),java,sorting,data-structures,graph,minimum-spanning-tree,Java,Sorting,Data Structures,Graph,Minimum Spanning Tree,我有一个使用HashMap存储其边的图,如下所示: HashMap<Integer,LinkedList<Node>> adj; 乙二醇 0:->//节点0连接到具有边权重55的节点1和具有边权重54的节点2 1:->//节点1连接到具有边权重43的节点0和具有边权重的节点2 边重44 我需要得到一个按重量排序的边列表,但我不知道该怎么做。我正在尝试实现Kruskal的MST 可以对我定义的图进行排序吗?如果没有,请建议更好的存储方式 让我们先创建一个Edge类:
HashMap<Integer,LinkedList<Node>> adj;
乙二醇
- 0:->//节点0连接到具有边权重55的节点1和具有边权重54的节点2
- 1:->//节点1连接到具有边权重43的节点0和具有边权重的节点2 边重44
可以对我定义的图进行排序吗?如果没有,请建议更好的存储方式 让我们先创建一个
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;
}
}
}
现在,对于您的程序(如果没有针对它的要求),我将如下定义您的列表:
HashMap<Node, List<Edge>> adj; // use any list implementation you want
HashMap adj;//使用您想要的任何列表实现
这将在您的程序中表示如下图形(从您的示例中复制):
- 节点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);
ArrayList sortedges=new ArrayList();
对于(列出连接的边:adj.values()){
分类数据。添加所有(连接数据);
}
收集。分类(分类);
这只需将adj
中的所有Edge
放在一个列表中,然后根据它们的权重对它们进行排序(因为我们使Edge
extend)。根据,sort()
方法使用合并排序,它在O(nlog(n))
时间内运行:
实现说明:此实现是一种稳定、自适应、迭代的mergesort,当输入数组部分排序时,需要的比较远远少于n lg(n),而当输入数组随机排序时,它提供了传统mergesort的性能
通过adj.值获取所有Edge
s的列表需要O(n)
时间(请参见),因此获取按权重排序的边列表的总时间复杂度将是O(n)+O(nlog(n))
=O(nlog(n))
好了。我希望这会有所帮助:)如果您可以自由更改节点的表示方式,我建议您进行更改。目前,节点
类实际上代表一条边(节点由整数
表示,即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());
}
Set nodes=new HashSet();//封闭类跟踪所有节点。
//表示每个节点。
类节点{
int nodeId=/*…*/;
//节点类跟踪其邻居,按其权重排序。
SortedMap edges=新树映射(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( /* ... */ );
}
}
void方法(节点){
迭代器iter=node.edges.keySet().Iterator();//按降序迭代。
while(iter.hasNext()){
int-weight=iter.next();
节点邻居=Node.edges.get(权重);
剂量测定法(/*…*/);
}
}
旁注:你可以摆脱那一个O(n)
通过实现您自己的合并排序,在迭代列表时对列表进行排序。我不确定这样做可以节省多少时间…此方法仅对一个节点的边进行排序。OP希望获得整个图中所有边的列表,按权重排序。
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( /* ... */ );
}
}