这篇文章记录一下自己对递归函数return的理解。
递归函数执行实际上就是栈调用的方式,递归最底部的程序执行,实际上就是栈顶元素执行。达到递归终止条件之后,栈顶函数执行完被释放,也就是最内部的递归程序执行完,然后是下一级的程序执行,也就是再浅一层的函数执行。最后层层出栈完成最终程序执行。
如果你的递归程序,只需要执行而不需要有返回值,那么写递归程序的时候就不需要写返回值。
// 向树中插入节点是一个纯执行的过程,所以不需要有返回值
protected insertNode(node: TreeNode<T>, element: T) {
if (this.compareFn(element, node.element) === Compare.LESS_THAN) {
if (node.left === null) {
node.left = new TreeNode(element)
} else {
this.insertNode(node.left, element)
}
} else if (node.right === null) {
node.right = new TreeNode(element)
} else {
this.insertNode(node.right, element)
}
}
如果你的递归程序要有返回值,因为递归程序栈是层层结束的,栈顶的元素要想往栈下面传递的话,就需要return作为传输介质。因此如果要有返回值的话,递归程序执行就需要使用return
/** 输入一个节点,查看这个节点及其子节点是否有满足element元素的节点 */
private searchNode(node: TreeNode<T>, element: T) {
if (node === null) return false
if (this.compareFn(element, node.element) === Compare.LESS_THAN) {
return this.searchNode(node.left, element)
} else if (this.compareFn(element, node.element) === Compare.BIGGER_THAN) {
return this.searchNode(node.right, element)
}
// 上面两个条件都不满足就说明相等,找到了,返回true
return true
}
还有一种情况是又有执行又有返回值,常见于对某些内容做更改并把更改的内容返回回去,此时应该赋值和返回都去做。
比如下面这种情况,要对二叉搜索树移除一个节点。
此时要返回一个删除后的新的树,因此要对树的内容赋值,因为有返回,还要写return。对于这种比较复杂的递归问题不要慌,只需要构建起来最为简单的递归小例子,然后验证代码就可以。
/** 从一棵树中移除某个元素,会生成新的树 */
remove(element: T) {
this.root = this.removeNode(this.root, element)
}
private removeNode(node: TreeNode<T>, element: T) {
if (node === null) {
return null
}
if (this.compareFn(element, node.element) === Compare.LESS_THAN) {
node.left = this.removeNode(node.left, element)
return node
} else if (this.compareFn(element, node.element) === Compare.BIGGER_THAN) {
node.right = this.removeNode(node.right, element)
return node
} else {
// key is equal to node.item
// handle 3 special conditions
// 1 - a leaf node
// 2 - a node with only 1 child
// 3 - a node with 2 children
// case 1
if (node.left == null && node.right == null) {
node = null;
return node;
}
// case 2
if (node.left == null) {
node = node.right;
return node;
} else if (node.right == null) {
node = node.left;
return node;
}
// case 3
const aux = this.minNode(node.right);
node.element = aux.element;
node.right = this.removeNode(node.right, aux.element);
return node;
}
}