重生之我在黑盒学编程5

今天我们来讲一下c++中的递归算法

原理/理论

递归是编程中一种强大的技术,它允许函数自我调用。在C++中,递归通常用于解决某些类型的问题,如分治算法等。下面我们将深入探讨C++中的递归知识,包括其原理、用法、作用等。

递归的原理

递归的核心思想是将问题分解为更小的子问题。这些子问题通常与原始问题相似,但规模更小。通过解决这些子问题,我们可以组合它们的解决方案来获得原始问题的解决方案。

递归的基本步骤如下:

  1. 基线条件:这是递归终止的条件。当问题规模足够小时,基线条件将被满足,递归调用将停止。

  2. 递归步骤:这是将问题分解为更小子问题的步骤。函数会自我调用,每个子问题的规模都比原始问题小。

  3. 组合子问题的解决方案:当所有的子问题都被解决后,它们的解决方案被组合起来以形成原始问题的解决方案。

递归的作用

递归在编程中有很多用途,包括:

  1. 解决问题:许多问题可以通过递归有效地解决,特别是那些可以自然分解为更小子问题的问题。例如,排序算法(如快速排序和归并排序)、搜索算法(如深度优先搜索和广度优先搜索)以及图算法(如Dijkstra算法和Prim算法)都可以用递归来实现。

  2. 简化代码:对于某些问题,使用递归来编写代码可以使代码更简洁、更易于理解。由于每个递归调用都做类似的事情,这也有助于代码复用。

  3. 抽象和分治策略:递归是一种强大的抽象工具,可以用来解决复杂的问题。通过将问题分解为更小的子问题,我们可以更容易地理解和解决原始问题。此外,分治策略(即将问题分解为独立的子问题,然后解决这些子问题并将结果组合起来)也是递归的核心概念。

  4. 理解复杂概念:对于初学者来说,递归可能是一个难以理解的概念。然而,一旦掌握了它,就可以更好地理解许多复杂的编程概念,如动态规划、堆栈、队列等。

  5. 处理无限数据结构:虽然在实际编程中很少遇到无限数据结构,但理论上,递归是处理这类数据结构的唯一方法。例如,无限斐波那契数列和无限链表只能通过递归来处理。


递归函数

递归函数是一种特殊的函数,它在其定义或实现中直接或间接地调用自身。递归函数通常用于解决一些可以通过分解为更小的子问题来解决的问题。在C++中,递归函数的定义和实现与其他函数类似,但是需要在函数的主体中调用自身。

递归函数的基本结构如下:

  1. 基线条件:这是递归终止的条件。当问题规模足够小时,基线条件将被满足,递归调用将停止。

  2. 递归步骤:这是将问题分解为更小子问题的步骤。函数会自我调用,每个子问题的规模都比原始问题小。

  3. 组合子问题的解决方案:当所有的子问题都被解决后,它们的解决方案被组合起来以形成原始问题的解决方案。

生动的理解

递归,就是在运行的过程中调用自己本身

A. 构成递归需具备的条件:

  1. 子问题须与原始问题为同样的事,且更为简单:
    这是递归的核心概念。一个函数要成为递归的,它必须在其定义中调用自身来处理比原始问题更小的子问题。这些子问题必须与原始问题相似,但规模更小。这样,通过解决这些子问题,我们可以组合它们的解决方案来得到原始问题的解决方案。

  2. 不能无限制的调用本身,必须有个出口,化简为非递归状况处理:
    为了避免无限递归,递归函数必须有一个或多个基线条件。当满足基线条件时,递归调用停止。基线条件是递归终止的条件,通常当问题规模足够小时满足。这样,递归函数最终会化简为非递归状况处理,从而避免无限递归。

B. 递归可以解决的问题:

  1. 阶乘:阶乘是一个典型的递归问题。例如,计算5的阶乘(5!)可以分解为计算4的阶乘(4!)和加上5。然后,4的阶乘可以分解为计算3的阶乘(3!)和加上4,依此类推,直到基线条件1! = 1。

  2. 斐波那契数列:这是一个著名的递归问题。每个斐波那契数都是前两个数的和。例如,要计算第n个斐波那契数,可以递归地计算第n-1个和第n-2个斐波那契数,然后将它们相加。

  3. 汉诺塔:这是一个经典的递归问题。汉诺塔问题要求将一堆盘子从一个柱子移动到另一个柱子,每次只能移动一个盘子,并且不能将一个较大的盘子放在较小的盘子上面。这个问题的解决方案是一个典型的递归过程,其中将问题分解为更小的子问题(移动较小的盘子)并将其解决,然后将结果组合起来(移动较大的盘子)以解决原始问题。

  4. 杨辉三角的存取:杨辉三角是一个经典的数学问题,可以通过递归的方式求解。例如,可以使用递归来计算杨辉三角中的第n行数字。

  5. 字符串回文判断:这是一个可以通过递归解决的问题。可以使用递归来比较字符串的首尾字符,然后递归地比较字符串的中间部分,直到字符串的长度为1或0。

  6. 字符串全排列:全排列可以通过递归的方式求解。可以使用递归来生成所有可能的排列,直到所有字符都被排列。

  7. 二分查找:二分查找是一个经典的递归算法。它通过将搜索空间一分为二来找到目标值。在每次递归调用中,算法将搜索空间缩小一半,直到找到目标值或搜索空间为空。

  8. 树的深度求解:树的深度可以通过递归的方式求解。对于每个节点,算法将其子节点的最大深度作为该节点的深度。在每个递归调用中,算法处理一个子树并返回该子树的深度,直到达到叶节点或没有子节点为止。

C. 递归的过程:

递归过程通常包含以下几个步骤:

  1. 定义:定义函数的基本结构并明确函数的名称和输入参数。

  2. 基线条件:确定函数的基线条件。这是递归终止的条件,通常当问题规模足够小时满足。

  3. 递归步骤:将问题分解为更小的子问题,并调用自身来处理这些子问题。这个步骤是递归的核心部分,它使函数能够自我调用以解决更小的子问题。

  4. 组合子问题的解:当所有的子问题都被解决后,将这些子问题的解组合起来以形成原始问题的解。这个步骤是将递归转化为非递归的过程,通过组合子问题的解来获得原始问题的解。

  5. 返回值:在函数体中返回结果或执行其他必要的操作以完成函数的执行。

通过以上步骤,递归函数实现了将复杂问题分解为更小的子问题并最终解决原始问题的目的。然而,使用递归时需要注意防止无限递归和栈溢出等问题,确保在基线条件下及时终止递归调用。

部分代码,思路来自csdn

举几个例子

阶乘

斐波那契数列

字符串回文判断

看到这里,你已经基本了解了c++中的递归算法

下面是一个递归的习题练习一下:

由键盘录入一个正整数,求该整数中每个数字出现的次数。
输入:19931003
输出:
0 2
1 2
3 2
9 2

更多游戏资讯请关注:电玩帮游戏资讯专区

电玩帮图文攻略 www.vgover.com