Recursion 试着理解递归函数
为了更好地理解递归,我试图计算每对()之间的字符数, 不计算其他()中的字符数。例如:Recursion 试着理解递归函数,recursion,Recursion,为了更好地理解递归,我试图计算每对()之间的字符数, 不计算其他()中的字符数。例如: (abc(ab(abc)cd)(()ab)) 将输出: Level 3: 3 Level 2: 4 Level 3: 0 Level 2: 2 Level 1: 3 其中“Level”是指()嵌套的级别。因此,第三级意味着字符在一对(1)中在一对(2)中在一对(3)中 要做到这一点,我想最简单的方法是实现对函数的某种递归调用,正如函数“recursiveParaCheck”中所述。当我开始思考一个重复关系
(abc(ab(abc)cd)(()ab))
将输出:
Level 3: 3
Level 2: 4
Level 3: 0
Level 2: 2
Level 1: 3
其中“Level”是指()嵌套的级别。因此,第三级意味着字符在一对(1)中在一对(2)中在一对(3)中
要做到这一点,我想最简单的方法是实现对函数的某种递归调用,正如函数“recursiveParaCheck”中所述。当我开始思考一个重复关系时,我的方法是什么
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int recursiveParaCheck(char input[], int startPos, int level);
void main()
{
char input[] = "";
char notDone = 'Y';
do
{
//Read in input
printf("Please enter input: ");
scanf(" %s", input);
//Call Recursive Function to print out desired information
recursiveParaCheck(input, 1, 1);
printf("\n Would you like to try again? Y/N: ");
scanf(" %c", ¬Done);
notDone = toupper(notDone);
}while(notDone == 'Y');
}
int recursiveParaCheck(char input[], int startPos, int level)
{
int pos = startPos;
int total = 0;
do
{
if(input[pos] != '(' && input[pos] != ')')
{
++total;
}
//What is the base case?
if(BASE CASE)
{
//Do something?
}
//When do I need to make a recursive call?
if(SITUATION WHERE I MAKE RECURSIVE CALL)
{
//Do something?
}
++pos;
}while(pos < 1000000); // assuming my input will not be this long
}
#包括
#包括
#包括
#包括
int recursiveParaCheck(字符输入[],int startPos,int级别);
void main()
{
字符输入[]=“”;
char notDone='Y';
做
{
//读入输入
printf(“请输入:”);
扫描频率(“%s”,输入);
//调用递归函数打印出所需的信息
递归并行检查(输入,1,1);
printf(“\n是否重试?是/否:”);
scanf(“%c”、¬Done);
notDone=toupper(notDone);
}while(notDone='Y');
}
int recursiveParaCheck(字符输入[],int开始,int级别)
{
int pos=startPos;
int-total=0;
做
{
如果(输入[pos]!='('&输入[pos]!='))
{
++总数;
}
//基本情况是什么?
if(基本情况)
{
//做点什么?
}
//我什么时候需要进行递归调用?
if(我进行递归调用的情况)
{
//做点什么?
}
++pos;
}while(pos<1000000);//假设我的输入不会这么长
}
递归是一个很棒的编程工具。它提供了一种处理各种问题的简单、强大的方法。然而,通常很难看到如何递归地处理问题;递归地“思考”可能很难。编写一个递归程序也很容易,要么运行时间太长,要么根本无法正确终止。在本文中,我们将介绍递归的基础知识,希望能帮助您开发或完善一项非常重要的编程技能
什么是递归?
为了确切地说明递归是什么,我们首先必须回答“什么是递归?”基本上,如果函数调用自身,则称其为递归函数
您可能会认为这并不十分令人兴奋,但此函数演示了设计递归算法时的一些关键注意事项:
它处理简单的“基本情况”,而不使用递归。
在本例中,基本情况是“HelloWorld(0)”;如果函数被要求打印零次,那么它将返回,而不会产生更多的“HelloWorld”。
它避免了循环。
为什么使用递归?
我们上面说明的问题很简单,我们编写的解决方案也很有效,但是我们最好使用循环,而不是递归。在问题稍微复杂一点的情况下,递归往往会大放异彩。递归几乎可以应用于任何问题,但在某些情况下,您会发现它特别有用。在本文的剩余部分中,我们将讨论其中一些场景,同时,我们还将讨论在使用递归时需要记住的一些核心思想
场景1:层次结构、网络或图形
在算法讨论中,当我们谈论一个图表时,我们通常不会谈论一个显示变量之间关系的图表(比如TopCoder评级图,它显示时间和评级之间的关系)。相反,我们通常谈论的是以各种方式相互联系的事物、人或概念的网络。例如,路线图可以被认为是一个显示城市及其道路连接方式的图表。图形可能很大,很复杂,很难通过编程来处理。它们在算法理论和算法竞赛中也很常见。幸运的是,使用递归可以简化图形的处理。图的一种常见类型是层次结构,例如企业的组织结构图:
姓名管理器
贝蒂·萨姆
鲍勃萨利
迪尔伯特·内森
约瑟夫·萨利
内森·维罗妮卡
莎莉·维罗妮卡
山姆·约瑟夫
苏珊·鲍勃
维罗尼卡在该图中,对象是人,图中的连接显示公司中谁向谁报告。我们的图表上有一条向上的线,表示图表上较低的人向他们上面的人报告。在右边,我们可以看到如何在数据库中表示此结构。对于每个员工,我们都会记录他们的姓名和经理的姓名(根据这些信息,如果需要,我们可以重建整个层次结构-你知道怎么做吗?) 现在假设我们要编写一个类似于“countEmployeesUnder(employeeName)”的函数。此功能旨在告诉我们有多少员工(直接或间接)向employeeName指定的人员报告。例如,假设我们打电话给“countEmployeesUnder('Sally')”,了解有多少员工向Sally报告 首先,计算有多少人直接在她手下工作很简单。为此,我们循环遍历每个数据库记录,对于经理为Sally的每个员工,我们增加一个计数器变量。实现这种方法,我们的函数将返回一个计数2:Bob和Joseph。这是一个开始,但我们还想计算像苏珊或贝蒂这样的人,他们的级别较低,但间接向萨利报告。这很尴尬,因为举例来说,当查看苏珊的个人记录时,并不清楚萨利是如何参与其中的 正如您可能已经猜到的,一个好的解决方案是使用递归。例如,当我们在数据库中遇到Bob的记录时,我们不只是将计数器增加1。相反,我们增加1(计算Bob),然后增加peop的数量
function countEmployeesUnder(employeeName)
{
declare variable counter
counter = 0
for each person in employeeDatabase
{
if(person.manager == employeeName)
{
counter = counter + 1
counter = counter + countEmployeesUnder(person.name)
}
}
return counter
}