递归函数的终止条件是必须的吗?哪怕它没用
来源:2-8 作业解析:链表的递归实现
52726814
2023-10-12 06:25:41
// 在以dummyHead为头结点的链表的index位置插入元素e,递归算法
public void addAt(int index, T element){
if(index < 0 || index > size){
throw new IllegalArgumentException("Add failed. Illgegal index");
}
addAtHelper(dummyHead, -1, index, element);
}
private void addAtHelper(Node node, int currIndex, int index, T element){
if(node == null){
return;
}
if(currIndex < index - 1){
addAtHelper(node.next, currIndex+1, index, element);
}else{
Node rear = node.next;
node.next = new Node(element, rear);
size++;
}
}hi, bobo老師,
我觉得我可以把 addAtHelper(..)中的 if(node == null) {return;} 刪了,因为 addAt()中的 index > size扔exception已經避免了 node 会等于 null 的情况。
但如果删了的话,我的递归函数addAtHelper 就没有终止条件了。递归函数一定要有终止条件吗?哪怕这个终止条件没什么用?我有点纠结要不要删掉它,想听听你的建议。 谢谢
我跑过测试,我的代码能跑出正确答案。

1回答
liuyubobobo
2023-10-13
以下内容我没有验证你的程序的正确性,完全是从递归函数的书写的角度谈的。
==========
删掉 if(node == null) {return;} 后,这个递归函数还是有终止条件的。终止条件就是 else 里的内容。
为什么 else 里的内容是终止条件?因为在 else 里没有递归调用了。
换句话说,将这个递归函数写成这个样子,是逻辑等价的:
private void addAtHelper(Node node, int currIndex, int index, T element){
// 递归终止条件
if(currIndex >= index - 1){
Node rear = node.next;
node.next = new Node(element, rear);
size++;
return;
}
// 递归过程
addAtHelper(node.next, currIndex+1, index, element);
}而如果你愿意加上 node ==null 的判断,相当于给递归函数加入了两个终止条件。这是完全可以的:
private void addAtHelper(Node node, int currIndex, int index, T element){
// 递归终止条件
if(node == null){
return;
}
if(currIndex >= index - 1){
Node rear = node.next;
node.next = new Node(element, rear);
size++;
return;
}
// 递归过程
addAtHelper(node.next, currIndex+1, index, element);
}实际上,如果你确认 node 不会等于 null,一个更好的方式是在 node == null 的时候抛异常,或者加入其他的错误处理机制的代码,比如先把这次运行相关的数据写进 log,再 return。
从逻辑的角度,不写 if(node == null) 是完全没有问题的,对于这个“小”程序来说,是完全正确的。但是从“软件工程”的角度看,写这个 if 是更好的。这叫做防御型编程。可以参考这里:https://class.imooc.com/course/qadetail/249635
===========
注意,这和你提出的“终止条件”是两个问题。如我上面所说,你的程序是有终止条件的。一切递归一定有终止条件,否则递归不可能终止,这就像循环会有循环结束条件一样。
而 if(node == null) 这个终止条件,在这个逻辑中,不是必须,但是协商完全没有问题,并且是我推荐的方式,因为下面要调用 node.next,所以考虑 node 为空的情况,不管他是不是真的发生,这是好的编程实践。(这就像一旦遇到除以一个变量,就应该考虑一下这个变量如果是 0 怎么办,而不用管这个变量是不是真的可能是 0。这是好的编程习惯。因为即便在当下的逻辑中,这个变量不会为 0,你不能肯定在以后的版本中,你活着别人是不是可能因为修改逻辑,使得这个变量可以为 0。)
继续加油!:)
相似问题