对于节点5,它应该简单地为5 = [6],为什么有3个不同的值。另外,我知道,这个当前的代码是错误的大时间,因为当我添加像2,1和2,3这样的边时它甚至会做2 = [3,3]。它只是用旧的值替换旧值并复制它。这是带有结果的图像。
Graph.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
public class Graph {
HashMap <Integer, ArrayList<Integer>> adj =new HashMap<Integer, ArrayList<Integer>>();
public void addEdge(int source, int destination) {
ArrayList<Integer> list = new ArrayList<Integer>();
adj.put(source,list);
list.add(destination);
for(Entry<Integer, ArrayList<Integer>> entry: adj.entrySet()) {
int existing = entry.getKey();
System.out.println("Existing: "+existing);
System.out.println("Source: " +source);
if (source != existing) {
//adj.get(2).add(9);
//System.out.println(source +": "+ destination);
adj.get(source).add(destination);
}
}
}
public void print() {
System.out.println(adj);
}
}
AdjacencyList.java
import java.util.Scanner;
public class AdjacencyList {
public static void main(String[] args) {
Scanner in = new Scanner (System.in);
System.out.println("Enter nodes below like (u,v):");
Graph g = new Graph();
for (int i=0; i<3; i++) {
String nodes = in.nextLine();
String[] data = nodes.split(",");
String u = data[0];
String v = data[1];
int inNode = Integer.parseInt(u);
int outNode =Integer.parseInt(v);
g.addEdge(inNode,outNode);
System.out.println("Added to list");
}
g.print();
}
}
答案 0 :(得分:1)
据我所知,您正在更新Map
source -> List<destination>
。
您添加了一个新的source
节点,并将其作为sources
映射到所有现有destination
。
所以,例如我有
1 -> [2,3]
2 -> [1,3]
3 -> [1,2]
如果我通过调用addEdge(4, 5)
添加新映射,我最终应该
1 -> [2,3,5]
2 -> [1,3,5]
3 -> [1,2,5]
4 -> [5]
这是对的吗?
在这种情况下,您的代码存在缺陷。首先请注意:
adj.get(source).add(destination);
您始终将destination
添加到属于源节点的List<destination>
。所以当你在上面的例子中调用addEdge(4, 5)
时(为了简单起见假设迭代):
entry.key()
为1
,1 != 4
,将5
添加到adj.get(4)
entry.key()
为2
,2 != 4
,将5
添加到adj.get(4)
entry.key()
为3
,3 != 4
,将5
添加到adj.get(4)
entry.key()
是4
,4 == 4
,noop。所以你最终得到:
1 -> [2,3]
2 -> [1,3]
3 -> [1,2]
4 -> [5,5,5]
要解决这个问题,我需要知道您对给定初始状态和输入的预期输出是什么 - 即我需要算法。猜测我会说你想这样做:
Map<Integer, List<Integer>> adj = new HashMap<>();
public void addEdge(int source, int destination) {
List<Integer> list = new ArrayList<>();
adj.put(source, list);
list.add(destination);
for (final Entry<Integer, List<Integer>> entry : adj.entrySet()) {
if (source != entry.getKey()) {
entry.getValue().add(destination);
}
}
}
即。
entry.key()
为1
,1 != 4
,将5
添加到adj.get(1)
entry.key()
为2
,2 != 4
,将5
添加到adj.get(2)
entry.key()
为3
,3 != 4
,将5
添加到adj.get(3)
entry.key()
是4
,4 == 4
,noop。我还将代码更改为程序到interface
,并使用Java 7菱形语法来提高可读性。
在这种情况下,您需要完成检查的唯一原因是您在循环之前将put
destination
放入您创建的新List
中。我可以建议:
public void addEdge(int source, int destination) {
if (adj.get(source) == null) {
adj.put(source, new ArrayList<>());
}
for (final Entry<Integer, List<Integer>> entry : adj.entrySet()) {
entry.getValue().add(destination);
}
}
即。我们检查source
的映射是否为null
,如果是,我们将new ArrayList
添加到adj
。然后,我们遍历所有映射,并将目标添加到每个映射。结果将与上述相同。
以下是新代码的一些输出:
public static void main(final String[] args) throws Exception {
System.out.println(adj);
addEdge(1, 2);
System.out.println(adj);
addEdge(3, 7);
System.out.println(adj);
addEdge(4, 2);
System.out.println(adj);
}
输出:
{}
{1=[2]}
{1=[2, 7], 3=[7]}
{1=[2, 7, 2], 3=[7, 2], 4=[2]}
所以可能还有另一个错误 - 即如果我将相同的目的地放在两次,我会以这种方式复制。如果这不是您想要的,则需要进行小的更改:
Map<Integer, Collection<Integer>> adj = new HashMap<>();
public void addEdge(int source, int destination) {
if (adj.get(source) == null) {
adj.put(source, new LinkedHashSet<>());
}
for (final Entry<Integer, Collection<Integer>> entry : adj.entrySet()) {
entry.getValue().add(destination);
}
}
更改Map
以保留常规Collection
并添加LinkedHashSet
而不是ArrayList
。 LinkedHashSet
维护订单(Linked
)并且不允许重复元素(Set
)。
输出现在是:
{}
{1=[2]}
{1=[2, 7], 3=[7]}
{1=[2, 7], 3=[7, 2], 4=[2]}
修改强>
继OP的评论
输入以下节点,如(u,v):2,1添加到列表2,3添加到列表5,6添加到列表{2 = [3,6],5 = [6]} < / em>的
这似乎更简单。 OP希望维护一个简单的映射 - 并且只更新相关的source -> destination
并且不允许重复的目标。代码是:
Map<Integer, Collection<Integer>> adj = new HashMap<>();
public void addEdge(int source, int destination) {
//see if adj contains source already
Collection<Integer> destinations = adj.get(source);
//if not add in a new LinkedHashSet
if (destinations == null) {
destinations = new LinkedHashSet<>();
adj.put(source, destinations);
}
//Set returns false if item exists
if (!destinations.add(destination)) {
System.out.println("This mapping already exists.");
}
}
输出:
{}
{1=[2]}
{1=[2], 3=[7]}
{1=[2], 3=[7], 4=[2]}
{1=[2], 3=[7], 4=[2, 3]}
This mapping already exists.
{1=[2], 3=[7], 4=[2, 3]}