过程或函数可能包含对其中另一个过程的调用。其中,子程序可以调用自身。在这种情况下,计算机不关心。他也一如既往,从上到下始终如一地执行他遇到的命令。
如果你还记得数学,那你就会遇到 数学归纳原理。具体如下:
对于每个自然 n 如果
1. 对 n = 1 和 有效
2. 从对任意自然数 n = k 的陈述的有效性,可以得出它对 n = k+1 为真。
在编程中,这种技术称为 递归
递归是一种根据给定的简单基本情况根据集合本身定义一组对象的方法。
Recursive 也将被称为过程(函数),直接或通过其他过程和函数调用自身
递归过程的一个例子:
<前>
<代码>void Rec(int a)
{
如果 (a>0) Rec(a-1);
输出 << A;
}
示意性地,递归的工作可以用流程图表示
Rec() 过程以参数 3 执行。然后,在参数 3 的过程中,调用参数 2 的过程,依此类推,直到调用参数 0 的过程。当过程带有参数 0 被调用,递归调用已经不会发生,参数 0 的过程将打印数字 0 并终止。然后控制权返回给参数为 1 的过程,它也通过打印数字 1 来完成它的工作,依此类推。在带有参数 3 的过程之前。
所有被调用的过程都存储在内存中,直到它们完成它们的工作。并发过程的数量称为递归深度 。
|
递归。回路模拟
我们已经看到,递归是重复执行子程序中包含的指令。反过来,这类似于循环的工作。有些编程语言根本不存在循环结构,例如 Prolog。
让我们尝试模拟循环 for 的工作。
for 循环包含一个计步器变量。在递归子程序中,这样的变量可以作为参数传递。
// 带有两个参数的过程 LoopImitation()。
// 第一个参数 –计步器,第二个参数——总步数。
void LoopImitation(int i, int n)
{
输出 << “你好” <<我 <<结束; // 对 i 的任何值重复的运算符
if (i < n) // 直到循环计数器等于 n,
{ // 使用参数 i+1 调用过程的新实例(转到下一个值 i)。
LoopImitation(i + 1, n);
}
|
递归和迭代
要理解递归,你需要理解递归...
迭代 在编程中-循环数据处理过程的 一步。
当前步骤(迭代)的迭代算法通常使用在先前步骤计算的相同操作或动作的结果。 此类计算的一个例子是递归关系的计算。
递归值的一个简单示例是阶乘: \(N!=1 \cdot 2 \cdot 3 \cdot \ ... \ \cdot N\)。
每一步(迭代)的值的计算是 \(N=N \cdot i\) 。 在计算 \(N\)的值时,我们取已经存储的值 \(N\) >.
一个数的阶乘也可以用 递归公式 来描述:
\(\begin{equation*} n!= \begin{cases} 1 &\text{n <= 1,}\\ (n-1)!\cdot n &\text{n > 1.} \end{cases} \end{equation*}\)
你可能会注意到这个描述只不过是一个递归函数。
这里第一行 ( \(n <= 1\)) 是基本情况(递归终止条件),第二行是到下一步的过渡。
<正文>
递归阶乘函数 |
迭代算法 |
整数阶乘(整数 n)
{
如果 (n > 1)
返回 n * 阶乘(n - 1);
否则返回 1;
|
x = 1;
对于 (i = 2; i <= n; i++)
x = x * 我;
输出 << x;
|
表>
应该理解,函数调用涉及一些额外的开销,因此非递归阶乘计算会稍微快一些。
结论: 如果您可以使用简单的迭代算法编写程序,无需递归,那么您就需要编写无递归的程序。但是,仍然存在一大类仅通过递归实现计算过程的问题。
另一方面,递归算法通常更容易理解。
任务
在部落语言“Tumba-Yumba”的字母表中;四个字母:“K”、“L”、“M”和“N”。您需要显示所有由 n 个字母组成的单词,这些单词可以从这个字母表的字母组成。
这个问题是一个普通的蛮力问题,可以简化为一个更小的问题。
我们将依次用字母替换单词。
单词的第一个位置可以是字母表中的 4 个字母之一(K、L、M、N)。
让我们把字母K 放在第一位。然后,为了得到第一个字母为K 的所有变体,您需要枚举剩余n - 1 位置的所有可能的字母组合 等等。 (见图)
这样,问题就简化为解决四个长度为 n - 1 的问题。
递归遍历 n 个字符
w[0]='K'; // 遍历最后的 L-1 个字符
w[0]='L'; // 遍历最后的 L-1 个字符
w[0]='M'; // 遍历最后的 L-1 个字符
w[0]='N'; // 遍历最后的 L-1 个字符
w - 存储工作词的字符串。
因此,我们得到了递归。我们可以将问题的解决方案安排在递归过程的形式。
递归何时结束还有待确定?当设置完所有字符时,即设置的字符个数为n 。在这种情况下,您需要在屏幕上显示结果词并退出程序。
C++ 程序将如下所示。
<分区>
#include;
使用命名空间标准;
void TumbaWords(字符串 A, string &w, int N )
// w - 可变参数(字符串结果)
// TumbaWords 程序将字母表作为字符串传递,
// 单词 word 和已经设置的字符数(在 – 0 之前)。
{
诠释我;
如果 (N == w.size())
{
// 如果所有字符都已经设置为单词,
// 然后需要输出一个字符串并结束程序
输出 << w<<结束;
返回;
}
for ( i = 1; i < A.size(); i ++ )
{
// 如果上面的条件为假(也就是说,不是所有的字符都是间隔的,
// 然后在循环中我们遍历字母表中的所有字符并
//交替将字符放在第一个空闲空间
w[N] = A[i];
TumbaWords ( A, w, N+1 );
}
}
主要的()
{
国际;
字符串词;
国际;
辛>>名词;
word.resize(n); // 将字符串增加到 n
TumbaWords(“KLMN”,字,0);
注意 w 是一个可变参数(结果字符串)!
|
|