我正在为简单的社交网络开发无向图实现。用户使用他们的ID(整数)来表示,我需要找到不同级别的友谊 我使用了Adjacency List方法,因为我的图表非常稀疏。我使用了一个hashmap来保存用户和他们的朋友:
Map<Integer, Set<Integer>> graph;
使用此实现,我能够找到第一和第二级友谊。但是,我写了一个方法,使用BFS来查找两个用户是否是第四级朋友。
例如,如果图表包含以下边缘:
1-2
2-3
3-4
4-5
然后1和5是第四级朋友,当1和5作为参数传递给它时,我的方法应该返回true。
问题是我的方法在main中调用时总是返回false,即使方法本身已经过测试且是正确的!这是方法,并且它是正确和有效的。
public boolean checkLevelBFS(Integer source, Integer dest) {
Queue<Integer> toVisitQueue = new LinkedList<>(graph.get(source));
Set<Integer> visited = new HashSet<>();
visited.add(source);
Integer inreaser = new Integer(-1); // indicator for level increase
toVisitQueue.add(inreaser);
int level = 1; // because we already passed the source and started from its children nodes
while (level <= 4 && !toVisitQueue.isEmpty()) {
Integer currentNode = toVisitQueue.remove();
if (currentNode.equals(dest)) {
return true;
}
if (visited.contains(currentNode)) {
continue;
}
if (currentNode.equals(inreaser)) {
level++;
toVisitQueue.add(inreaser);
continue;
}
visited.add(currentNode);
for (Integer child : graph.get(currentNode)) {
if (!visited.contains(child)){
toVisitQueue.add(child);
}
}
}
return false;
}
使代码返回false的部分如下:
public static void main(String[] args) {
Basics x = new Basics();
x.graph = new HashMap<>();
Set<Integer> s = new HashSet<>();
s.add(2);
x.graph.put(1, s);
s = new HashSet<>();
s.add(1);
s.add(3);
x.graph.put(2, s);
s = new HashSet<>();
s.add(2);
s.add(4);
x.graph.put(3, s);
s = new HashSet<>();
s.add(3);
s.add(5);
x.graph.put(4, s);
s = new HashSet<>();
s.add(4);
s.add(6);
x.graph.put(5, s);
s = new HashSet<>();
s.add(5);
x.graph.put(6, s);
if (!x.initialCheck(1, 5)) {
System.out.println("A new user is involved");
} else {
if (x.levelOneFriends(1, 5)) {
System.out.println("friends");
} else {
System.out.println("not friends");
if (x.levelTwoFriends(1, 5)) {
System.out.println("friends level 2");
} else {
System.out.println("not friends of level 2");
if (x.checkLevelBFS(1, 5)) {
System.out.println("YES - friends of level 4");
} else {
System.out.println("NO - not friends of level 4");
}
}
}
}
System.out.println(x.checkLevelBFS(1, 2));
System.out.println(x.checkLevelBFS(1, 3));
System.out.println(x.checkLevelBFS(1, 4));
System.out.println(x.checkLevelBFS(1, 5));
System.out.println(x.checkLevelBFS(1, 6));
}
输出:
not friends
not friends of level 2
NO - not friends of level 4
false
false
false
false
false
前两行是正确的输出,第三行是不正确的1和5是4级的油炸,应该打印是 -
以下&#39; false&#39;输出也很怪异!
&#39; initialCheck&#39;检查图中是否有两个用户中的任何一个 &#39; levelOneFriends&#39;检查这两个对象是否是直接的朋友 &#39; levelTwoFriends&#39;检查这两个对象是否属于朋友的朋友关系。
任何帮助?
谢谢!
答案 0 :(得分:0)
[OP的评论显示levelTwoFriends
]
public boolean levelTwoFriends(Integer user1, Integer user2) {
Collection<Integer> c = graph.get(user1);
// c.retainAll(graph.get(user2));
// return !c.isEmpty();
// true only if a non-void intersection
return false==Collections.disjoint(c, graph.get(user2));
}
或作为单行
public boolean levelTwoFriends(Integer user1, Integer user2) {
return false==Collections.disjoint( graph.get(user1), graph.get(user2) );
}
[使用x.initialCheck
更新后编辑]
然后,您的错误必须在x.initialCheck
以及您在实际进入x.checkLevelBFS
之前所做的其他事情中。验证x.initialCheck
和x.levelOneFriends
是否违反了邻接列表的内部表示中的修改(必须在那里 - 在调试器中运行并密切关注内容的修改)。我为什么这么说?因为以下代码按预期工作:
static public void main(String[] args) {
ExampleTest x=new ExampleTest(); // in your case, it's Basics
x.graph=new HashMap<>();
x.graph.put(1, new HashSet<>(Arrays.asList(2)));
x.graph.put(2, new HashSet<>(Arrays.asList(1,3)));
x.graph.put(3, new HashSet<>(Arrays.asList(2,4)));
x.graph.put(4, new HashSet<>(Arrays.asList(3,5)));
x.graph.put(5, new HashSet<>(Arrays.asList(4,6)));
x.graph.put(6, new HashSet<>(Arrays.asList(5)));
System.out.println(x.checkLevelBFS(1, 2)); // true
System.out.println(x.checkLevelBFS(1, 3)); // true
System.out.println(x.checkLevelBFS(1, 4)); // true
System.out.println(x.checkLevelBFS(1, 5)); // true
System.out.println(x.checkLevelBFS(1, 6)); // false
}
“问题是我的方法总是返回false!”
但事实并非如此!你的错误可能在其他地方!!!
我会将此标记为为我工作并关闭错误。
我的代码用于推动测试。
class ExampleTest {
Map<Integer, Set<Integer>> graph;
static public void main(String[] args) {
ExampleTest x=new ExampleTest();
x.graph=new HashMap<>();
x.graph.put(1, new HashSet<>(Arrays.asList(2)));
x.graph.put(2, new HashSet<>(Arrays.asList(3)));
x.graph.put(3, new HashSet<>(Arrays.asList(4)));
x.graph.put(4, new HashSet<>(Arrays.asList(5)));
x.graph.put(5, new HashSet<>(Arrays.asList(6)));
System.out.println(x.checkLevelBFS(1, 2)); // true
System.out.println(x.checkLevelBFS(1, 3)); // true
System.out.println(x.checkLevelBFS(1, 4)); // true
System.out.println(x.checkLevelBFS(1, 5)); // true
System.out.println(x.checkLevelBFS(1, 6)); // false
}
// verbatim copy of your method here
public boolean checkLevelBFS(Integer source, Integer dest) {
Queue<Integer> toVisitQueue = new LinkedList<>(graph.get(source));
Set<Integer> visited = new HashSet<>();
visited.add(source);
Integer inreaser = new Integer(-1); // indicator for level increase
toVisitQueue.add(inreaser);
int level = 1; // because we already passed the source and started from its children nodes
while (level <= 4 && !toVisitQueue.isEmpty()) {
Integer currentNode = toVisitQueue.remove();
if (currentNode.equals(dest)) {
return true;
}
if (visited.contains(currentNode)) {
continue;
}
if (currentNode.equals(inreaser)) {
level++;
toVisitQueue.add(inreaser);
continue;
}
visited.add(currentNode);
for (Integer child : graph.get(currentNode)) {
if (!visited.contains(child)){
toVisitQueue.add(child);
}
}
}
return false;
}
}