我有一个递归问题,我想使用递归来解决。
例如,给定此邻接矩阵AdjMat:
0 1 2 3
0 0 1 0 0
1 1 0 1 0
2 0 1 0 1
3 0 0 1 0
说,我想看一下列0及其所有邻居,以及它的邻居的邻居(距离2),并将所有行索引> 0都存储到一个整数链接列表中。
这是我更新的代码:
intNode *Neighbors(intNode *head, int colOfInterest, int distance) {
int x = colOfInterest;
if (distance == 0) {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (AdjMat[x][j] > 0) {
head = insertInt(head, j);
}
}
break;
}
}
intNode *subpath = NULL;
for (int i = 0; i < distance; i++) {
subpath = Neighbors(head, colOfInterest, distance);
}
// Once the final neighbor column has been reached, add elements to the linked list.
return head;
}
它当前不返回预期的输出(在链表中为0、1和2),但是我不确定为什么。任何帮助或指导表示赞赏。
答案 0 :(得分:4)
您在代码中有两个主要的误解。第一个是递归,第二个是邻接矩阵的工作原理。
递归基本上是这样的:
func(node, d)
; func(next, d - dist(node, next)
调用该节点上的函数。要查找节点#0附近的所有节点,请先从一个空列表开始,然后调用func(0, 2)
,这将导致以下调用:
func(0, 2) // list {0}
func(1, 1) // list {0, 1}
func(0, 0) // list {0, 1, 0} error, see below
func(1, -1) // negative d, do nothing
func(2, 0) // list {0, 1, 0, 2}
func(1, -1) // negative d, do nothing
func(3, -1) // negative d, do nothing
--> recursion depth
此递归最终将停止,因为您会减小每一步的距离。这很重要:每次递归都必须有终止条件,否则它将无限递归。 (无论是预先测试距离还是递归,这都是一种样式问题。Up字体会尽早捕获无效输入,但可能导致无用的“死”递归。)
给定的递归有一个细微的问题:当调用func(0, 2)
时,该函数将两次添加节点#0,因为从节点0到1再回到0会产生距离2,该距离在达到。有几种解决方法。例如,您可以查看给定节点是否已经在列表中。或者,您可以随时将节点标记为已访问。
邻接矩阵确定是否连接了两个节点。如果a
,则连接两个节点b
和adj[a][b] != 0
。这意味着,如果要查找给定节点next
的所有邻居node
,则应执行以下操作:
for (int next = 0; next < N; next++) {
if (adj[node][next]) {
// do something with next
}
}
您不需要两个嵌套循环。矩阵有两个维度,但第一个维度始终是固定的:它是源节点。 (如果您查看代码,将会发现您对i
并没有执行任何操作。)
在您的情况下,邻接矩阵似乎仅具有0和1的值,但它可能具有其他非零值以指示加权图的距离。