递归算法详解完整版

合集下载

递归算法及经典例题详解

递归算法及经典例题详解

递归算法及经典例题详解
1.什么是递归
递归简单来说就是在运行过程中不断调用自己,直到碰到终止条件,返回结果的过程。

递归可以看作两个过程,分别是递和归。

递就是原问题把要计算的结果传给子问题;归则是子问题求出结果后,把结果层层返回原问题的过程。

下面设一个需要经过三次递归的问题,为大家详细看一下递归的过程:当然,现实中我们遇到递归问题是不会按照图中一样一步一步想下来,主要还是要掌握递归的思想,找到每个问题中的规律。

2.什么时候使用递归
递归算法无外乎就是以下三点:1.大问题可以拆分为若干小问题2.原问题与子问题除数据规模不同,求解思路完全相同3.存在递归终止条件
而在实际面对递归问题时,我们还需要考虑第四点:
当不满足终止条件时,要如何缩小函数值并让其进入
下一层循环中
3.递归的实际运用(阶层计算)
了解了大概的思路,现在就要开始实战了。

下面我们来看一道经典例题:
求N的阶层。

首先按照思路分析是否可以使用递归算法:
1.N!可以拆分为(N-1)!*N
2.(N-1)!与N!只有数字规模不同,求解思路相同
3.当N=1时,结果为1,递归终止
满足条件,可以递归:
publicstaticintFactorial(int num){if(num==1){return num;}return num*Factorial(num-1);}
而最后的return,便是第四步,缩小参数num的值,让递归进入下一层。

一般来说,第四步往往是最难的,需要弄清该如何缩
小范围,如何操作返回的数值,这一步只能通过不断
地练习提高了(当然如果你知道问题的数学规律也是
可以试出来的)。

全排列递归算法详解

全排列递归算法详解

全排列递归算法详解
哎呀,啥是全排列递归算法呀?我一个小学生刚开始听到这个词的时候,简直是一头雾水,就好像走进了一个黑漆漆的迷宫,找不到出口。

咱们先来说说啥叫排列吧。

比如说,有三个数字1、2、3,把它们排排队,123 是一种排法,213 是一种排法,321 又是一种排法,这就是排列。

那全排列呢,就是把所有可能的排法都找出来。

那递归算法又是啥呢?这就像我们玩的搭积木。

我们先搭一层,然后在这一层的基础上再搭一层,一层一层地往上加。

递归算法也是这样,它自己调用自己,就像搭积木一样,一层一层地解决问题。

比如说,我们要对三个数字1、2、3 进行全排列。

那我们可以先固定第一个数字1,然后对剩下的2 和3 进行全排列。

怎么排呢?再固定2,剩下3 自己就是一种排法;然后固定3,剩下2 又是一种排法。

这是不是有点像我们做数学题的时候,一步一步来,每一步都为下一步打下基础?这不就和我们一层一层搭积木一样嘛!
再想想,如果数字更多了,比如1、2、3、4 这四个数字,那我们还是用同样的方法。

先固定一个数字,然后对剩下的数字进行全排列。

这是不是有点像我们解决难题的时候,把大问题分成一个个小问题,然后一个个解决?
哎呀,说了这么多,我感觉全排列递归算法就像是一个神奇的魔法,能把一堆乱七八糟的数字变得整整齐齐,让我们能找到所有的可能性。

反正我觉得全排列递归算法虽然有点难,但是只要我们认真去想,去琢磨,就一定能搞明白!。

递归算法详解完整版

递归算法详解完整版

递归算法详解完整版递归算法是一种重要的算法思想,在问题解决中起到了很大的作用。

它通过将一个大问题划分为相同或类似的小问题,并将小问题的解合并起来从而得到大问题的解。

下面我们将详细介绍递归算法的定义、基本原理以及其应用。

首先,我们来定义递归算法。

递归算法是一种通过调用自身解决问题的算法。

它通常包括两个部分:基础案例和递归步骤。

基础案例是指问题可以被直接解决的边界情况,而递归步骤是指将大问题划分为较小问题并通过递归调用自身解决。

递归算法的基本原理是"自顶向下"的思维方式。

即从大问题出发,不断将问题划分为较小的子问题,并解决子问题,直到达到基础案例。

然后将子问题的解合并起来,得到原始问题的解。

递归算法的最大特点是简洁而优雅。

通过将复杂问题分解为简单问题的解决方式,可以大大减少代码的复杂程度,提高程序的效率和可读性。

但是递归算法也有一些缺点,包括递归深度的限制和复杂度的不确定性。

过深的递归调用可能导致栈溢出,而不合理的递归步骤可能导致复杂度过高。

递归算法有许多应用场景,我们来介绍其中一些典型的应用。

1.阶乘问题:计算一个数的阶乘。

递归算法可以通过将问题划分为更小的子问题来解决。

例如,n的阶乘可以定义为n乘以(n-1)的阶乘。

当n 等于1时,我们可以直接返回1作为基础案例。

代码如下:```int factorial(int n)if (n == 1)return 1;}return n * factorial(n - 1);```2.斐波那契数列问题:求斐波那契数列中第n个数的值。

斐波那契数列的定义是前两个数为1,然后从第三个数开始,每个数都是前两个数的和。

递归算法可以通过将问题划分为两个子问题来解决。

当n等于1或2时,直接返回1作为基础案例。

代码如下:```int fibonacci(int n)if (n == 1 , n == 2)return 1;}return fibonacci(n - 1) + fibonacci(n - 2);```3.二叉树问题:对于给定的二叉树,递归算法可以通过递归调用左子树和右子树的解来解决。

6种基本算法 递归

6种基本算法 递归

6种基本算法递归递归是一种重要的算法思想,它在计算机科学中得到广泛应用。

本文将介绍六种基本的递归算法,并对其原理和应用进行讲解。

一、递归的基本概念递归是指一个函数在其定义中调用自身的过程。

递归算法通过将一个大问题划分为一个或多个相同或相似的子问题,然后通过解决子问题来解决原始问题。

递归算法具有简洁、优雅以及可读性强的特点,但同时也需要注意递归的停止条件,以避免无限递归的发生。

二、阶乘算法阶乘算法是递归算法中最经典的例子之一。

它的定义如下:```n! = n * (n-1) * (n-2) * ... * 1```其中,n为一个非负整数。

阶乘算法可以通过递归的方式实现,即:```fact(n) = n * fact(n-1)```其中,停止条件为`n=0`时,返回1。

三、斐波那契数列算法斐波那契数列是一个无限序列,其定义如下:```F(0) = 0F(1) = 1F(n) = F(n-1) + F(n-2) (n>1)```斐波那契数列算法可以通过递归的方式实现,即:```fib(n) = fib(n-1) + fib(n-2)```其中,停止条件为`n=0`或`n=1`时,返回相应的值。

四、二分查找算法二分查找算法是一种高效的查找算法,它的基本原理是将已排序的数组分成两部分,然后判断目标值在哪一部分,并继续在该部分中进行查找,直到找到目标值或者查找范围为空。

二分查找算法可以通过递归的方式实现,即:```binarySearch(arr, target, start, end) = binarySearch(arr, target, start, mid-1) (target < arr[mid])= binarySearch(arr, target, mid+1, end) (target > arr[mid])= mid (target = arr[mid])```其中,`arr`为已排序的数组,`target`为目标值,`start`和`end`为查找范围的起始和结束位置。

递归算法详解

递归算法详解

递归算法详解what:在计算机科学中是指⼀种通过重复将问题分解为同类的⼦问题⽽解决问题的⽅法when:发现问题可以分解为同类⼦问题且采⽤同样的⽅式去解决how:找到递归出⼝和递归体步骤:通过分析题⽬是否可以分解为若⼲重复⼦问题,判断是否可以采⽤递归算法进⾏解决。

确定采⽤递归算法之后,开始找递归出⼝和递归体,这是递归算法的核⼼部分,下⾯通过两个题⽬讲⼀下我的解题步骤。

P1:leetcode226 翻转⼆叉树简单题解答:题⽬很简单,翻转⼆叉树,然后查看输⼊输出,其实就是将每个节点的左右⼦树进⾏了交换。

这个时候⼦问题已经出现了,交换左右⼦树,按题⽬说法就是翻转左右⼦树,可以采⽤递归来做。

接下来需要找到递归出⼝和递归体,⼀般情况下先找递归体,因为确定递归的时候⼤概就已经确定了递归体,然后就是考虑边界问题,确定递归出⼝。

回到题⽬,根据题⽬的分析,可以确定递归体即为交换翻转当前节点的左右⼦树,当遍历⾄根节点⽆节点可翻转时即退出递归,即找到递归出⼝当前节点为null。

接下来代码实现:public class Solution{/** 226. 翻转⼆叉树简单题**/public TreeNode invertTree(TreeNode root) {this.invert(root);return root;}private void invert(TreeNode root){if (null == root) {return;}TreeNode left = root.left;TreeNode right = root.right;root.right = invertTree(left);root.left = invertTree(right);}}class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) {this.val = val;}TreeNode(int val, TreeNode left, TreeNode right) {this.val = val;this.left = left;this.right = right;}}P2:leetcode24,给定⼀个链表,两两交换其中相邻的节点,并返回交换后的链表。

python中的递归算法详解

python中的递归算法详解

python中的递归算法详解递归算法是一种在函数内部调用自身的方法。

在Python中,递归可以实现复杂的问题解决,它的实现遵循以下几个关键步骤。

第一,定义基本情况:递归算法在每一次调用中都需要判断是否达到了基本情况,即算法可以直接返回结果而不继续调用自身。

这个基本情况确保算法不会无限递归下去,而是能够找到问题的解。

第二,拆分问题:递归算法需要将大问题拆分成子问题,在每一次递归调用中解决子问题。

这样,较大的问题就会逐渐转化为较小的问题,直到最终达到基本情况。

第三,调用自身:递归算法通过调用自身来解决子问题。

在每次递归调用中,算法会传递不同的参数,以便在下一次调用中解决不同的子问题。

递归算法的关键在于它能够将复杂的问题转化为简单的子问题,并通过不断调用自身来解决这些子问题。

举个例子,考虑一个计算阶乘的递归算法:```pythondef factorial(n):# 基本情况if n == 0:return 1# 拆分问题subproblem = factorial(n - 1)# 调用自身result = n * subproblemreturn result```在这个例子中,递归算法使用了基本情况 `n == 0` 来停止递归。

当输入参数为0时,算法直接返回1,否则继续调用自身,解决 `n - 1` 的阶乘问题。

最终,算法将计算 `n` 的阶乘并返回结果。

需要注意的是,递归算法在处理大规模问题时可能会遇到效率问题。

递归算法会调用自身多次,每次调用都需要保存状态并分配栈空间,所以在某些情况下,循环迭代可能会更加高效。

因此,在使用递归算法时,需要谨慎考虑问题的规模和算法实现的复杂度,以充分利用递归的优势。

排列组合递归算法

排列组合递归算法是一种基于递归思想的算法,用于解决与排列和组合相关的问题。

下面是排列组合递归算法的详细介绍:
基本概念:
排列(Permutation):从n个不同元素中取出m(m ≤n)个不同元素按照一定的顺序排成一列,称为从n个元素中取出m个元素的一个排列,所有排列的个数记为P(n,m)。

组合(Combination):从n个不同元素中取出m(m ≤n)个不同元素按照一定的顺序排成一列,不考虑排列的顺序,称为从n个元素中取出m个元素的一个组合,所有组合的个数记为C(n,m)。

递归的基本思想:
递归算法的基本思想是将一个复杂的问题分解为若干个简单的问题,然后将这些简单问题的解组合起来得到原问题的解。

在排列组合问题中,可以将一个大问题分解为若干个小问题,例如:从n个元素中取出m个元素的排列/组合问题可以分解为从剩余元素中继续取下一个元素的问题。

递归公式:
排列的递归公式:P(n,m) = n * P(n-1,m-1) + P(n-1,m)
组合的递归公式:C(n,m) = P(n,m) / P(m,m) = (n * P(n-1,m-1) + P(n-1,m)) / P(m,m)
应用示例:
使用排列组合递归算法可以解决很多与排列和组合相关的问题,例如:给定一个数组,求数组中所有元素的排列/组合数、给定一个集合,求集合的所有子集等。

注意事项:
在使用递归算法时需要注意避免出现无限递归的情况,需要对递归终止条件进行正确的设置。

另外,由于递归算法会涉及到大量的重复计算,因此在处理大规模数据时可能会效率较低,可以考虑使用动态规划等优化方法来提高算法的效率。

汉诺塔递归算法及详解

汉诺塔递归算法及详解
汉诺塔(Tower of Hanoi)是一个经典的数学谜题和递归问题。

它由三个塔杆和一些不同大小的圆盘组成,开始时圆盘按从大到小的顺序叠放在一个塔杆上。

目标是将所有圆盘从起始塔杆移动到目标塔杆上,同时遵守以下规则:
1. 一次只能移动一个圆盘。

2. 任何时刻,大的圆盘不能放在小的圆盘上面。

递归算法是解决汉诺塔问题的常用方法。

其基本思想是将问题分解为较小规模的子问题,然后通过递归地解决子问题来解决原问题。

以下是汉诺塔递归算法的详解:
1. 如果只有一个圆盘需要移动,则直接将圆盘从起始塔杆移动到目标塔杆上。

2. 如果有多个圆盘需要移动,则按以下步骤进行操作:
- 将除最下方的圆盘以外的上方圆盘从起始塔杆移动到辅助塔杆上。

这可以通过递归调用解决较小规模的子问题来实现,即将上方圆盘从起始塔杆移动到目标塔杆上(目标塔杆作为新的辅助塔杆)。

- 然后将最下方的圆盘从起始塔杆直接移动到目标塔杆上。

- 最后,将辅助塔杆上的所有圆盘移动到目标塔杆上,这可以通过递归调用解决较小规模的子问题来实现,即将上方圆盘从辅助塔杆移动到起始塔杆上(起始塔杆作为新的目标塔杆)。

通过递归地应用以上步骤,就可以实现将所有圆盘从起始塔杆移动到目标塔杆上的操作。

递归求组合数

递归求组合数组合数是组合数学中的一种重要概念,用于表示从n个元素中选取k个元素的不同方式的数量。

在数学中,组合数C(n, k)可以通过递归方法求解。

本文将介绍递归算法的原理,并通过实例演示如何使用递归求解组合数。

1. 递归算法原理递归算法是一种通过反复调用自身来解决问题的方法。

在求解组合数时,递归算法可以通过以下步骤实现:步骤一:如果k等于0或者k等于n,直接返回1,表示选择的元素个数为0或者选择所有元素。

步骤二:否则,组合数C(n, k)等于C(n-1, k-1) + C(n-1, k)。

其中C(n-1, k-1)表示从n-1个元素中选取k-1个元素的方式数量,C(n-1, k)表示从n-1个元素中选取k个元素的方式数量。

步骤三:通过递归调用上述步骤二,即可求解组合数C(n, k)。

2. 递归求组合数的实例下面通过一个实例演示如何使用递归求解组合数。

假设有一个集合{1, 2, 3, 4, 5},我们需要从中选取3个元素的所有不同组合方式数量。

首先,我们需要定义一个递归函数来求解组合数:```pythondef combination(n, k):if k == 0 or k == n:return 1else:return combination(n-1, k-1) + combination(n-1, k)```然后,我们可以调用该函数来求解组合数:```pythonresult = combination(5, 3)print("组合数C(5, 3)的值为:", result)```通过运行上述代码,可以得到结果:```组合数C(5, 3)的值为: 10```因此,从集合{1, 2, 3, 4, 5}中选取3个元素的不同组合方式数量为10。

3. 小结递归求组合数是一种简单而有效的方法,可以用于求解从n个元素中选取k个元素的不同方式的数量。

通过定义递归函数,反复调用自身,我们可以实现组合数的递归求解。

递归算法详解范文

递归算法详解范文递归是一种常用的算法思想,它通常用于解决可以被划分为更小规模相同问题的情况。

在递归算法中,问题被分解成更小的子问题,逐步求解子问题,最终得到整个问题的解。

接下来,我将详细介绍递归算法的原理、特点和应用。

一、递归算法的原理递归算法的原理是基于函数调用的特性。

在递归算法中,函数可以调用其自身来解决更小规模的子问题。

每次递归调用会将问题分解为更小规模的子问题,直到达到边界条件,然后逐步返回结果,最终得到整个问题的解。

递归算法通常具有以下两个重要的特点:1.递归定义:递归算法通过将问题分解为更小规模的子问题来定义。

2.递归调用:递归算法通过调用自身来解决更小规模的子问题。

递归算法的实现通常包含两个部分:基本情况和递归情况。

1.基本情况:基本情况是递归算法的边界条件,它表示问题已经足够小,可以直接求解,无需继续递归调用。

2.递归情况:递归情况是递归算法的重点,它描述了如何将当前问题分解为更小规模的子问题,并调用自身来解决子问题。

递归算法在实现时需要注意以下几点:1.基本情况的设置要合理,以确保算法能够终止。

2.递归调用时,问题规模要比上一次递归调用减小,确保算法能够在有限步骤内得到解。

3.递归算法的效率通常比较低,因为它会重复计算一些子问题。

可以通过记忆化、动态规划等方法进行优化。

二、递归算法的特点递归算法具有以下几个特点:1.逻辑简单清晰:递归算法的实现通常比较简洁,容易理解和调试。

2.代码复用性好:递归算法可以将问题分解为更小规模的子问题,这样可以复用代码来解决不同规模的问题。

3.可读性强:递归算法通常可以直观地反映问题的结构和解题思路。

4.可扩展性好:递归算法可以方便地将问题扩展到更大规模。

然而,递归算法也存在一些局限性:1.递归算法通常会消耗较多的内存空间,因为每一次递归调用都需要保存一些中间结果。

2.递归算法的效率较低,因为它会存在重复计算的问题,可以通过优化方法进行提升。

3.递归算法可能会因为递归过深而导致栈溢出,需要注意递归调用的次数。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

递归算法详解标准化管理处编码[BBX968T-XBB8968-NNJ668-MM9N]递归冯文科一、递归的基本概念。

一个函数、概念或数学结构,如果在其定义或说明内部直接或间接地出现对其本身的引用,或者是为了描述问题的某一状态,必须要用至它的上一状态,而描述上一状态,又必须用到它的上一状态……这种用自己来定义自己的方法,称之为递归或递归定义。

在程序设计中,函数直接或间接调用自己,就被称为递归调用。

二、递归的最简单应用:通过各项关系及初值求数列的某一项。

在数学中,有这样一种数列,很难求出它的通项公式,但数列中各项间关系却很简a与前面临近几项之间的关单,于是人们想出另一种办法来描述这种数列:通过初值及n系。

要使用这样的描述方式,至少要提供两个信息:一是最前面几项的数值,一是数列间各项的关系。

比如阶乘数列1、2、6、24、120、720……如果用上面的方式来描述它,应该是:a的值,那么可以很容易地写成这样:如果需要写一个函数来求n这就是递归函数的最简单形式,从中可以明显看出递归函数都有的一个特点:先处理一些特殊情况——这也是递归函数的第一个出口,再处理递归关系——这形成递归函数的第二个出口。

递归函数的执行过程总是先通过递归关系不断地缩小问题的规模,直到简单到可以作为特殊情况处理而得出直接的结果,再通过递归关系逐层返回到原来的数据规模,最终得出问题的解。

以上面求阶乘数列的函数)f为例。

如在求)3(f时,由于3不是特殊值,因此需(n要计算)2(3f,但)2(f是对它自己的调用,于是再计算)2(f,2也不是特殊值,需要计*算)1(f,返回)1(= 2f,需要知道)1(f的值,再计算)1(f,1是特殊值,于是直接得出1*上一步,得23*)2()3(==f,从而得最终=f)1(32**)2(==f2f,再返回上一步,得6解。

用图解来说明,就是下面再看一个稍复杂点的例子。

【例1】数列}{n a 的前几项为1、111+、11111++、1111111+++、……输入n ,编程求n a 的精确分数解。

分析:这个题目较易,发现11=a ,其它情况下有111-+=n n a a 。

如要求实数解的话,这基本已经可以写出递归函数了。

但由于题目要求精确的分数解,还需做一些调整。

设p q a n =-1,则由递归关系,有qp p p qa a n n +=+=+=-11111,再约分化简,即得n a 。

但发现一个问题:求出1-n a 时,需要返回两个整数:分子q 与分母p ,而通常的函数只能返回一个整数。

这个问题一般有两类解决办法,一种是让求值函数返回一个结构体变量,这样就可以返回两个变量了(其实还可以不只两个呢);另一种是在求值函数的参数表中加入两个指针变量或引用变量,通过参数给带回数值。

但由于后一种做法会使程序结构不清晰——返回值是由参数表得到的,因此我们使用前一种方法。

另外,在通过p q a n =-1得出qp p a n +=后,n a 就已经是最简分数了,无须化简。

证明如下: 若pq 是最简分数,即说明q p ,的最大公约数为1,即对任何q r ≤<1,都有r q mod 与r p mod 不全为0,不防记a r q =mod 、b r p =mod ,则有只要a 与b 不全为0,且r b r a <<,,就有a 与r b a mod )(+不全为0。

因此对任何的q r ≤<1,有r p mod 与r q p mod )(+不全为0。

而对于p r q ≤<的情况而言,记a r p =mod ,则有由于r q r a <<<≤0,0,因此同样有r p mod 与r q p mod )(+不全为0。

所以对任意p r ≤<1,都有r p mod 与r q p mod )(+不全为0,因此它们的最大公约数为1,即qp p +是最简分数。

虽然这是个要求1-n a (即p q )是最简分数的结论,但由于数列第二项为21,是最简分数,因此可以证明第三项也是最简分数,同时也证明对所有的n a ,求出的qp p +就是最简分数,无须化简。

具体代码如下:)90(≤≤N N N -0i 1+i 2+i N N N i N i 12+i )1(2+i , MAX*sizeof(char)); t[n]='\0';for(i=0;i<n;i++){t[q[i]]='Q';cout<<t<<endl;t[q[i]]='.';}cout<<endl;}bool test(int i, int k){int j;j=0;while(j<k && abs(j-k)!=abs(q[j]-i)) j++;if(j==k && mark[i]==false)return true;elsereturn false;}void search(int k){if(k==n){write();c++;return;}int i;for(i=0;i<n;i++)if(test(i, k)){mark[i]=true;q[k]=i;search(k+1);mark[i]=false; }}int main()六、练习【练习】为给定的表达式建立表达式树,并求值。

给定的表达式中,所有数字都是1位正整数,出现的符号可能为+、-、*、/、(、)。

分析:这是一个与一般数据结构书上讲的用栈计算的方法本质不同的方法。

在详细说明这个算法之前,需要首先明确这个算法用到的概念1、单元:一个单元可能是用括号括起来的一个表达式,或是一个整数;2、项:一个项是指由*与/连接起来的若干单元;3、表达式:一个表达式是指由+或-连接起来的若干项。

要建立表达式树,需要三个函数互相调用的函数:一个是getunit,用于建立一个单元;一个是getexpr,用于建立一个项,另一个就是build,用于建立一个表达式。

getunit函数较易,如果字符串首字母是(的话,那么从它后面的字符开始用build建立一个表达式,这个表达式就是一个单元;否则,就处理一个整数;getexpr函数是建立在getunit之上的,它先用getunit建立一个单元,然后不停地考察之后地连接符号是不是*或/,若是,则不停地重复读连接符、建立另一个单元、建立连接的操作,直到连接符号不是*或/为止。

build函数是用于最终建立表达式的,它先用getexpr建立一个项,再用符号将剩余的各项连接成二叉树。

代码如下:if(n>0){ hanoi(n-1,x,z,y); hanoi(n-1,y,x,z); }.w[10]中int knap(int s,int n){ 算法32是求n个数的和的递归算法。

算法33是相应的迭代版本。

假设n个数已存储在数组a的分量a[1],…,a[n]中。

float sum(int n){.a[n]都置为0a[0]=1; *//* ---------------------------------------- */void main(){int i;for ( i = 0; i < 5; i++ )printf("%d! = %d\n",i,factorial(i));/*递归阶乘函数调用*/ }/* ======================================== *//* 使用列印数组函数来说明递归调用 *//* ======================================== */int list[6] = { 1, 2, 3, 4, 5, 6 }; /* 数组内容 *//* ---------------------------------------- *//* 递归数组反向列印函数 *//* ---------------------------------------- */void invert_array(int j){if ( j < 6 ) /* 终止条件 */{/* 递归链表列印函数调用 */invert_array(j + 1);printf("[%d]",list[j]); /* 列印元素资料 */ }}/* ---------------------------------------- */ /* 主程式: 反向列印数组内容. *//* ---------------------------------------- */ void main(){int i;printf("数组的内容:\n");for ( i = 0; i < 6; i++ )printf("[%d]",list[i]); /* 列印元素资料 */ printf("\n"); /* 换行 */printf("递归列印数组的内容:\n");invert_array(0); /* 调用列印函数 */printf("\n"); /* 换行 */}/* ======================================== */ /* 递归阶乘函数来说明递归内部处理 *//* ======================================== *//* ---------------------------------------- */ /* 递归阶乘函数 *//* ---------------------------------------- */int factrial(int j){int sum = 0; /* 阶乘总和变数 */int temp = 0; /* 阶乘总和暂存变数 */if ( j == 0 ) /* 终止条件 */{sum = 1;printf("到达终止条件(j = 0)\n");}else{printf("从函数factrial(%d)调用前的状态: sum = %d\n", j, sum);temp = factrial(j - 1); /* 递归阶乘函数调用 */printf("返回函数factrial(%d)后的状态: sum = %d\n",j, sum);sum = j * temp; /* 计算j!的值 */printf(" ==> 在计算%d!阶乘后的状态: sum = %d\n",j, sum);}return sum;}/* ---------------------------------------- *//* 主程式: 计算整数 4 的阶乘. *//* ---------------------------------------- */void main(){printf("4! = %d\n",factrial(4)); /* 递归阶乘函数调用 */}/* ======================================== */ /* 递归的链表建立和列印 *//* ======================================== */ #include <>struct list /* 链表结构宣告 */ {int data; /* 节点资料 */struct list *next; /* 指向下一节点 */ };typedef struct list node; /* 定义新型态 */ typedef node *link; /* 定义新型态指标 */ /* ---------------------------------------- *//* 递归链表列印函数 *//* ---------------------------------------- */ void print_list(link ptr){if ( ptr != NULL ) /* 终止条件 */{printf("[%d]",ptr->data); /* 列印节点资料 */ /* 递归链表列印函数调用 */print_list(ptr->next);}}/* ---------------------------------------- */ /* 递归链表建立函数 *//* ---------------------------------------- */ link create_list(int *array,int len,int pos) {link head; /* 链表节点的指标 */if ( pos == len ) /* 终止条件 */return NULL;else{/* 建立节点记忆体 */head = ( link ) malloc(sizeof(node));if ( !head )return NULL;head->data = array[pos]; /* 建立节点内容 */head->next = create_list(array,len,pos + 1);return head;}}/* ---------------------------------------- *//* 主程式: 建立链表后将内容印出. *//* ---------------------------------------- */void main(){int list[6] = { 1, 2, 3, 4, 5, 6 }; /* 数组内容 */ link head; /* 指向链表开始 */head = create_list(list,6,0); /* 建立链表 */if ( !head ){printf("记忆体配置失败! \n");exit(1);}printf("链表的内容:\n");print_list(head); /* 列印链表 */printf("\n"); /* 换行 */}/* ======================================== */ /* 递归的链表建立和反向列印 *//* ======================================== */ #include <>struct list /* 链表结构宣告 */ {int data; /* 节点资料 */struct list *next; /* 指向下一节点 */ };typedef struct list node; /* 定义新型态 */ typedef node *link; /* 定义新型态指标 *//* ---------------------------------------- *//* 递归链表反向列印函数 *//* ---------------------------------------- */ void print_list(link ptr){if ( ptr != NULL ) /* 终止条件 */{/* 递归链表列印函数调用 */print_list(ptr->next);printf("[%d]",ptr->data); /* 列印节点资料 */ }}/* ---------------------------------------- *//* 递归链表建立函数 *//* ---------------------------------------- */ link create_list(int *array,int len,int pos){link head; /* 链表节点的指标 */if ( pos == len ) /* 终止条件 */return NULL;else{/* 建立节点记忆体 */head = ( link ) malloc(sizeof(node));if ( !head )return NULL;head->data = array[pos]; /* 建立节点内容 */ head->next = create_list(array,len,pos + 1); return head;}}/* ---------------------------------------- */ /* 主程式: 建立链表后将内容印出. *//* ---------------------------------------- */ void main(){int list[6] = { 1, 2, 3, 4, 5, 6 }; /* 数组内容 */ link head; /* 指向链表开始 */head = create_list(list,6,0); /* 建立链表 */if ( !head ){printf("记忆体配置失败! \n");exit(1);}printf("链表的内容:\n");print_list(head); /* 列印链表 */printf("\n"); /* 换行 *//* ======================================== *//* 河诺塔问题 *//* ======================================== *//* ---------------------------------------- *//* 河内塔问题的递归函数 *//* ---------------------------------------- */int hanoi(int dishs,int peg1,int peg2,int peg3) {if ( dishs == 1) /* 终止条件 */printf("盘子从 %d 移到 %d\n",peg1,peg3);else{hanoi(dishs - 1,peg1,peg3,peg2); /* 第一步骤 */ printf("盘子从 %d 移到 %d\n",peg1,peg3);hanoi(dishs - 1,peg2,peg1,peg3); /* 第三步骤 */ }}/* ---------------------------------------- */ /* 主程式: 找出河内塔问题的解. *//* ---------------------------------------- */ void main(){hanoi(3,1,2,3); /* 调用递归函数 */}/* ======================================== */ /* 应用递归来走迷宫 *//* 数字 0: 表示是可走的路 *//* 数字 1: 表示是墙壁,不可走的路 *//* 数字 2: 标示是走过的路 *//* ======================================== */int maze[7][10] = { /* 迷宫的数组 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 0, 1, 0, 1, 0, 0, 0, 0, 1,1, 0, 1, 0, 1, 0, 1, 1, 0, 1,1, 0, 1, 0, 1, 1, 1, 0, 0, 1,1, 0, 1, 0, 0, 0, 0, 0, 1, 1,1, 0, 0, 0, 1, 1, 1, 0, 0, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };/* ---------------------------------------- */ /* 走迷宫的递归函数 *//* ---------------------------------------- */ int find_path(int x,int y){if ( x == 1 && y == 1 ) /* 是否是迷宫出口 */{maze[x][y] = 2; /* 记录最后走过的路 */return 1;}elseif ( maze[x][y] == 0 ) /* 是不是可以走 */{maze[x][y] = 2; /* 记录己经走过的路 */if ( ( find_path(x - 1,y) + /* 调用递归函数往上 */ find_path(x + 1,y) + /* 往下 */find_path(x,y - 1) + /* 往左 */find_path(x,y + 1) ) > 0 ) /* 往右 */return 1;else{maze[x][y] = 0; /* 此路不通取消记号 */ return 0;}}elsereturn 0;}/* ---------------------------------------- */ /* 主程式: 用递归的方法在数组迷宫找出口. *//* ---------------------------------------- */ void main(){int i,j;find_path(5,8); /* 调用递归函数 */printf("迷宫的路径如下图所示:\n");for ( i = 1; i < 6; i++) /* 印出迷宫的图形 */ {for ( j = 1; j < 9; j++)printf("%d",maze[i][j]); /* 印出各座标 */ printf("\n"); /* 换行 */}}/* ======================================== *//* 应用递归来解 N 皇后问题 *//* 数字 1: 表示是放置皇后 *//* 数字 0: 表示没有放置 *//* ======================================== */#define MAXQUEEN 8 /* 最大放置的皇后数 */int pad[MAXQUEEN][MAXQUEEN] = { /* N X N 的棋盘 */ 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0 };/* ---------------------------------------- *//* 放 N 个皇后的递归函数 *//* ---------------------------------------- */int put_queen(int x,int y,int times){int i,j,result = 0;if ( times > MAXQUEEN ) /* 终止条件 */ return 1;elseif ( place(x,y) ) /* 检查是否可放置皇后 */ {pad[x][y] = 1; /* 放置皇后 */for ( i = 0; i < MAXQUEEN; i++)for ( j = 0; j < MAXQUEEN; j++){/* 递归调用放置下一个皇后 */result += put_queen(i,j,times + 1); if ( result > 0 )break;}if ( result > 0 ) /* 找到了解 */ return 1;else{pad[x][y] = 0; /* 清除皇后 */ return 0;}}elsereturn 0;}/* ---------------------------------------- *//* 检查皇后是否有相互攻击 *//* ---------------------------------------- */(End)递归冯文科一、递归的基本概念。

相关文档
最新文档