
实际上,函数也可以调用它自己。调用自己的函数称为递归函数。来看以下 message 函数:
voID message(){ cout << "This is a recursive function. \n"; message();}该函数显示字符串 "This is a recursive function.",然后调用它自己。每次它调用自己时,循环都会重复。现在应该能发现该函数的问题,因为它没有办法停止递归调用。这个函数就像一个无限循环,因为没有代码阻止它重复。要使递归函数有用,则递归函数必须有一个方法来控制递归调用的次数。以下是对 message 函数的修改。它传递了一个整数参数,该参数将保存函数调用自己的次数。
voID message(int times){ if (times > 0) { cout << "This is a recursive function.\n"; message(times - 1); }}该函数包含一个控制递归的 if 语句。只要 times 参数大于零,它将显示消息并再次调用自己。每次它调用自己时,都会传递 times-1 作为参数。例如,假设有一个程序使用以下语句来调用该函数:message(3);
参数 3 将导致函数被调用 4 次。第一次调用函数时,if 语句将显示消息并以 2 作为参数调用自身,如图 1 所示。图 1 递归函数调用过程
图 1 直观地说明了两次独立的 message 函数调用。每次调用该函数时,会在内存中创建一个 times 参数的新实例。函数第一次被调用时,times 参数被设置为 3;当函数调用自己时,会创建一个新的 times 实例,并将值 2 传递给它。如此循环往复,直到传递给函数的值变成了 0,如图 2 所示。
图 2 通过 times 参数控制递归函数的调用次数
从图 2 可以看到,该函数将被调用 4 次,所以递归的深度是 4。当函数到达第 4 次调用时,times 参数将被设置为 0。此时,if 语句将停止调用的递归链,并且将返回函数的第 4 个实例。程序的控制权将从函数的第 4 个实例返回到第 3 个实例中调用递归函数语句所在的位置:
if (times > 0){ cout << "This is a recursive function.\n"; message(times - 1);}因为在函数调用之后没有更多的语句要执行,所以函数的第 3 个实例会将程序的控制权返回给第 2 个实例。如此重复,直到函数的所有实例都返回。下面的程序演示了修改后的递归 message 函数,它可以显示每次调用时参数的值。
// This program demonstrates a simple recursive function.#include <iostream>using namespace std;//Function prototypevoID message(int);int main(){ message(3); return 0;}voID message(int times){ if (times > 0) { cout << "Message " << times << "\n"; message(times - 1); }}程序输出结果:Message 3
Message 2
Message 1
为了进一步说明这个递归函数的内部工作,不妨来看一看另一个版本的程序。下面的程序中,每次进入函数都会显示一条消息,并且在函数返回之前显示另一条消息。
// This program demonstrates a simple recursive function.#include <iostream>using namespace std;// Function prototypevoID message(int);int main(){ message(3); return 0;}voID message(int times){ cout << "Message " << times << ".\n"; if (times > 0) { message(times - 1); } cout << "Message " << times << " is returning.\n";}程序输出结果:Message 3.
Message 2.
Message 1.
Message 0.
Message 0 is returning.
Message 1 is returning.
Message 2 is returning.
Message 3 is returning.
例如,如果有一长串的名称列表需要排序,则可以将列表分成两个子列表,并将两个子列表分配给两个不词的人来排序。一旦子列表完成排序,它们可以通过合适的整理过程合并形成原始列表的排序版本中。
在这种情况下,排序子列表的问题就是相同类型的更简单的问题。子列表实际上还可以再拆分,而基本情况就出现在子列表中只有一个名称时。
现在来看一个执行实用任务的简单递归示例。函数 frequency 可以计算特定字符出现在字符串中的次数。
int frequency(char ch,string inputString,int position){ if (position == inputString. length () ) //基本情况 return 0; if (inputString[position] == ch) return 1 + frequency(ch,inputString,position+1); else return frequency(ch,position+1);}该函数的参数包括:ch:要搜索和计数的字符。inputString:要搜索的字符串。position:搜索的起始下标。第一个 if 语句确定是否已出现基本情况,即到达字符串的结尾:
if (position == inputString.length())
return 0;
if (inputString[position] == ch) return 1 + frequency(ch,position+1);else return frequency(ch,position+1);如果 inputString [position] 是搜索字符,则函数执行递归调用。返回语句返回 1 加上搜索字符在字符串中出现的次数,从 position+1 开始。如果 inputString [position] 不是搜索字符,则会进行递归调用以搜索字符串的其余部分。下面的程序演示了以上示例。
// This program demonstrates a recursive function for// counting the number of times a character appears// in a string.#include <iostream>#include <string>using namespace std;// Function prototypeint frequency(char ch,int pos);int main(){ string inputString = "abcddddef"; cout << "The letter d appears " << frequency ('d',0) << " times.\n"; return 0;}int frequency(char ch,int position){ if (position == inputString.length()) //base case return 0; if (inputString[position] == ch) return 1 + frequency(ch,position+1);}程序输出结果:The letter d appears 4 times.
直接递归和间接递归迄今为止,我们所讨论的例子都是直接调用自己的递归函数,这称为直接递归。也可以在程序中创建间接递归。例如,当函数 A 调用函数 B,而函数 B 又反过来调用函数 A 时,就会发生这种情况。在间接递归中甚至可能包含若干个函数。例如,函数 A 调用函数 B,函数 B 调用函数 C,而函数 C 又调用函数 A。
总结
以上是内存溢出为你收集整理的什么是递归函数全部内容,希望文章能够帮你解决什么是递归函数所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)