我已经理解了维基百科中、关于生成递归的描述,但是对于结构递归的概念感到困惑。
请问有人能够解释一下计算第n个斐波那契数和计算1到N阶乘的函数是属于结构递归还是生成递归吗?
我已经理解了维基百科中、关于生成递归的描述,但是对于结构递归的概念感到困惑。
请问有人能够解释一下计算第n个斐波那契数和计算1到N阶乘的函数是属于结构递归还是生成递归吗?
结构递归和生成递归的关键区别在于递归过程获取数据的方式以及如何处理数据。具体而言,对于结构递归,递归调用是在原始输入数据的子集上进行的。而对于生成递归,递归调用是在从原始输入数据构造/计算出的数据上进行的。
例如,如果你想要计算链表中元素的数量,可以采取以下方法:
int NumberOfNodes(ListNode* node) {
if (node == nullptr) return 0;
return 1 + NumberOfNodes(node->next);
}
在这里,对 node->next
进行了递归调用,它是原始输入中已经存在的一部分。 在这种情况下,递归通过将输入拆分为较小的部分,然后对较小的部分进行递归来工作。
类似地,这个搜索二叉搜索树中的值的代码也是结构递归,因为递归调用是针对原始输入的子部分进行的:
TreeNode* Find(TreeNode* root, DataType value) {
if (root == nullptr) return nullptr;
if (value < root->value) return Find(root->left, value);
else return Find(root->right, value);
术语“结构递归”来自于这些结构(列表,BST等)可以通过递归定义的事实:
- 列表要么为空,要么是一个单元格后跟一个列表。
- 二叉树要么为空,要么是具有两个二叉树子节点的节点。int Factorial(int n) {
if (n == 0) return 1;
return n * Factorial(n - 1);
}
这是结构递归,因为参数n - 1是原始输入n的“一部分”。
同样地,按照这个定义,通过递归计算第n个斐波那契数也可以视为结构递归:
int Fibonacci(int n) {
if (n <= 1) return n;
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
这被认为是结构递归,因为 n - 1 是 n 的一部分(通过“撤消”+1形成),而 n - 2 是 n - 1 的一部分(再次通过“撤消”+1形成)。
另一方面,计算 gcd 的代码将被认为是生成递归,而不是结构递归:
int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}
推理是由于a % b
是从a
和b
计算出来的,而不是通过“撤销”一些+1操作形成的,因此数据是生成的。
生成递归与结构递归不同的原因在于没有保证其终止。例如,请考虑以下函数:
int BadTimes(int a, int b) {
if (a == 0 && b == 0) return 0;
return BadTimes(a * 2, b - 1);
}
这个生成递归函数永远不会终止:尽管b
变得越来越小,但a
仍然变得越来越大。
说实话,我以前从未听说过这种区别,而我教离散数学和编程课程。除非有人要求你知道这个区别,否则不必太担心。
希望这可以帮到你!