【发布时间】:2019-04-05 22:47:08
【问题描述】:
我正在尝试使用以下伪代码在 Java 中实现 BFS 算法:
1. for each vertex u ∈ G.V - {s} // for each vertex except for the source
2. u.color = WHITE // (line 1 cont) in the graph
3. u.distance = ∞
4. u.parent = NIL
5. source.color = GRAY
6. source.distance = 0
7. source.parent = NIL
8. Q = Ø
9. Enqueue (Q, source)
10. while Q != Ø
11. u = Dequeue(Q)
12. for each v ∈ G.Adj[u] // for each adjacent vertext
13. if v.color == WHITE
14. v.color = GRAY
15. v.distance = u.distance + 1
16. v.parent = u
17. Enqueue(Q, v)
18. u.color = BLACK
颜色代表每次访问该节点的时间:
WHITE = 2未被发现
GRAY = 3已被发现,但其相邻的邻居尚未全部被发现
BLACK = 4被发现,所有相邻的邻居都发现了,这里不需要返回
u.distance表示节点到源节点的距离,u.parent是返回源节点的父节点
我的教授说,与其为每个节点(u.color、u.d、u.pi)创建一个对象,不如为每个节点使用一个数组来存储每个节点的值。
他还为我们提供了包含邻接矩阵的框架代码,供我们对其进行测试。
--
我目前正在为第 11 行和第 12 行苦苦挣扎(我认为)。我能够创建和初始化所有数组以及队列,但是在实现 queue.poll() 或 queue.remove() 函数时遇到了问题第 11 行按我的预期行事。我也不知道我是否正确地创建了 for 循环。
我尝试使用从 LinkedList 和 Queue 导入的 .poll() 和 .remove() 函数。 这应该做的是移除队列的头部并将其值分配给变量 u,不是吗?
当我运行我的代码时,第 17 行添加到队列中,但在下一次迭代中永远不会删除队列的头部,第 18 行仅在第一次迭代(源节点)时执行。强>
我不确定我是否正确实现了伪代码的 第 12 行,因为我使用的是普通的 for 循环 (int v; v
while (!q.isEmpty())
{
u = q.poll(); // sets value of u... to most recent item removed from queue??
for (v = 0; v < colors.length; v++)
{
if (colors[v] == WHITE)
{
colors[v] = GRAY; // Sets color of VISITED Node to
dist[v] = dist[u] + 1; // sets distance at index v to value of the index most recently removed from queue + 1
parent[v] = u; // sets parent of index v to most recently removed item from queue
q.add(v); // adds node V to the queue
}
}
colors[u] = BLACK; // sets color of node to black (node visited + adjacent nodes visited)
}
return dist; // returns distance array
}
我尝试沿途打印出数组以查看 for 循环是如何运行的。使用这段代码,我可以看到在第一次迭代后头部没有从队列中移除并分配给值 u。
这是正在测试的矩阵:
int n = 8;
int[][] A =
{{0, 1, 0, 0, 1, 0, 0, 0},
{1, 0, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 1, 0, 1, 1, 0},
{0, 0, 1, 0, 0, 0, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 0, 0, 1, 0},
{0, 0, 1, 1, 0, 1, 0, 1},
{0, 0, 0, 1, 0, 0, 1, 0}};
我的结果:
COLORS: [2, 3, 2, 2, 2, 2, 2, 2]
DISTANCE: [2147483647, 0, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647]
PARENT: [0, 0, 0, 0, 0, 0, 0, 0]
COLORS: [3, 3, 2, 2, 2, 2, 2, 2]
dist[u] = 0
DISTANCE: [1, 0, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647]
PARENT: [1, 0, 0, 0, 0, 0, 0, 0]
QUEUE: []
COLORS: [3, 3, 3, 2, 2, 2, 2, 2]
dist[u] = 0
DISTANCE: [1, 0, 1, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647]
PARENT: [1, 0, 1, 0, 0, 0, 0, 0]
QUEUE: [0]
COLORS: [3, 3, 3, 3, 2, 2, 2, 2]
dist[u] = 0
DISTANCE: [1, 0, 1, 1, 2147483647, 2147483647, 2147483647, 2147483647]
PARENT: [1, 0, 1, 1, 0, 0, 0, 0]
QUEUE: [0, 2]
COLORS: [3, 3, 3, 3, 3, 2, 2, 2]
dist[u] = 0
DISTANCE: [1, 0, 1, 1, 1, 2147483647, 2147483647, 2147483647]
PARENT: [1, 0, 1, 1, 1, 0, 0, 0]
QUEUE: [0, 2, 3]
COLORS: [3, 3, 3, 3, 3, 3, 2, 2]
dist[u] = 0
DISTANCE: [1, 0, 1, 1, 1, 1, 2147483647, 2147483647]
PARENT: [1, 0, 1, 1, 1, 1, 0, 0]
QUEUE: [0, 2, 3, 4]
COLORS: [3, 3, 3, 3, 3, 3, 3, 2]
dist[u] = 0
DISTANCE: [1, 0, 1, 1, 1, 1, 1, 2147483647]
PARENT: [1, 0, 1, 1, 1, 1, 1, 0]
QUEUE: [0, 2, 3, 4, 5]
COLORS: [3, 3, 3, 3, 3, 3, 3, 3]
dist[u] = 0
DISTANCE: [1, 0, 1, 1, 1, 1, 1, 1]
PARENT: [1, 0, 1, 1, 1, 1, 1, 1]
QUEUE: [0, 2, 3, 4, 5, 6]
我希望它最终会像下面这样:
COLORS: [4, 4, 4, 4, 4, 4, 4, 4]
dist[u] = most recently removed from queue (not 0)
DISTANCE: [1, 0, 2, 3, 2, 1, 2, 3]
QUEUE: []
【问题讨论】:
-
您可能不应该在
while (!q.isEmpty())循环中包含return dist;。或者这只是你的不良缩进? -
for each v ∈ G.Adj[u]写入不正确,因为您的v循环根本没有使用u,即不是“对于每个相邻的顶点”。 -
return dist;行是我写错了。它不在实际代码的 while 循环中。你将如何编写 for 循环?我看到我实现它的方式没有任何意义,但我不确定(在 Java 中)还能怎么做? -
我在您的代码中没有看到
G.Adj[u](获取邻居)。如需更多帮助,请发布您的代码,而不仅仅是发布的 sn-p。见minimal reproducible example
标签: java eclipse algorithm data-structures breadth-first-search