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", &notDone);
        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
}