我在名为ImageNode的类中有以下递归方法,该类从名为Image的类传递头部( this - 链接列表的开头)。 我以为我的代码将以递归方式遍历每个节点,增加计数,然后当它最后返回计数时,不幸的是没有。我哪里错了?
private int countRec() {
int count = 1;
ImageNode node = this;
if (node.next != null ){
node = node.next;
count++;
countRec();
}
return count;
}
答案 0 :(得分:10)
您忽略了countRec()
的结果 - 并且您在递归调用中迭代,从而违背了目的。 (你也在同一个对象上进行递归调用,没有参数,状态没有变化......所以不能做任何好处。)我的递归方法将基于以下设计:
所以:
private int countRec() {
return next == null ? 1 : 1 + next.countRec();
}
现在不允许列出长度为0的列表...你可能想要将列表的想法与节点分开,在这种情况下列表类将具有如下内容:
public int count() {
return head == null ? 0 : head.countRec();
}
其中head
的值是对头节点的引用(如果有),否则为null
。
当然,这将是O(n)及时和空间。您可以使用迭代而不是递归来获得O(1)空间,并且通过将列表的大小保持为列表中的实例变量来获得O(1)时间,并在需要时更新它。我希望这个问题是基于教育要求而不是真实的代码 - 在生产代码中,您只需使用已提供的集合。
答案 1 :(得分:0)
递归函数的定义是它本身定义的:即如果是空列表,则列表中元素的数量等于0;否则它等于1 + 列表中其余元素的计数。
上述定义的斜体部分是进行函数调用的地方。
private int countRec(ImageNode node) {
if (node == null) {
return 0;
} else {
return 1 + countRec(node);
}
}
答案 2 :(得分:0)
当递归函数使用进一步调用的结果来解决他的问题时(如数学上的归纳步骤),递归函数很有用。您的函数没有使用countRec()
调用任何内容的返回值,并且您仍在尝试在没有递归帮助的情况下解决问题。您可以使用它来解决它,如:
if(node.next != null)
{
node = node.next;
count = countRec()+1;
}
return count;
当然,既然我们已经说过要让你的代码更好,你甚至不需要使用这个node
var,只需这样做:
private int countRec() {
if (this.next != null )
return (this.next.countRec())+1;
return 1;
}
希望有所帮助。