递归算法详解
递归算法及经典例题详解

递归算法及经典例题详解
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步。
那要是只有1级楼梯,那很简单呀,就只有1种走法,直接一步就上去啦。
要是有2级楼梯呢,你可以一次走2步,或者分两次每次走1步,这就有2种走法。
那要是楼梯级数多了呢?比如说有n级楼梯。
我们就可以用递归的思想来看这个问题哦。
啥是递归呢?简单说就是自己调用自己。
对于n级楼梯的走法数量,其实就等于先走1步后剩下的n - 1级楼梯的走法数量,加上先走2步后剩下的n - 2级楼梯的走法数量。
就好像你站在楼梯口,你有两种选择嘛,走1步或者走2步,这两种选择后面的走法数量加起来就是总的走法数量啦。
我们可以把这个写成一个数学表达式一样的东西哦。
假设f(n)表示n级楼梯的走法数量,那就有f(n)=f(n - 1)+f(n - 2)。
这是不是有点像斐波那契数列呀?对啦,它们很相似呢。
但是呢,这里我们得有个基础情况,就像刚刚说的,当n = 1的时候,f(1)=1,当n = 2的时候,f(2)=2。
要是没有这个基础情况,这个递归就没完没了啦,就像你在一个圈里一直转,不知道啥时候停。
比如说现在有3级楼梯,那f(3)就等于f(2)+f(1),也就是2 + 1 = 3种走法。
再要是4级楼梯呢,f(4)就等于f(3)+f(2),根据前面算出来的,f(3)=3,f(2)=2,那f(4)=3+2 = 5种走法。
递归算法就像是一个聪明的小助手,它能把复杂的爬楼梯走法数量的计算,分解成简单的基础情况和重复的小问题。
不过呢,递归算法有时候也会有点小脾气哦,要是楼梯级数太多了,它可能会算得比较慢,因为它要不断地调用自己。
但不管怎么说,这个递归算法来解决爬楼梯的走法数量问题,真的是超级巧妙呢。
宝子,现在是不是对这个递归算法有点感觉啦? 。
递归算法知识点总结

递归算法知识点总结一、基本概念递归算法的基本概念是基于递归函数的思想。
递归函数是一个调用自身的函数。
递归算法通常可以分为两种类型:简单递归和复杂递归。
简单递归是指在递归函数中直接调用自身,而复杂递归则是指在递归函数中可能会有多个递归调用。
递归算法通常用于解决可以分解为若干子问题的问题,这种方法通常可以更加简洁地解决问题,但同时也可能会带来一些计算复杂度的问题。
递归算法的设计通常包括以下几个步骤:1. 确定基本情况:在设计递归函数时,通常需要确定一个或多个基本情况。
基本情况通常是指在递归函数中不需要再次调用自身的情况。
2. 确定递归情况:在设计递归函数时,需要确定一个或多个递归情况。
递归情况通常是指在递归函数中需要调用自身的情况。
3. 确定递归方式:当确定了递归函数的基本情况和递归情况之后,就需要确定递归函数的调用方式。
通常有两种方式:直接递归和间接递归。
4. 编写递归函数:根据确定的基本情况、递归情况和递归方式,编写递归函数。
5. 测试递归函数:编写递归函数后,需要对递归函数进行测试,确保递归函数能够正确地解决问题。
二、递归算法的原理递归算法的原理是基于递归函数的调用。
当一个递归函数被调用时,它会将自身的执行环境保存到栈中,并且在栈中分配一些空间。
在递归函数中,如果有一些局部变量,这些变量会在栈中分配空间。
随着递归函数的深入调用,栈中的空间也会不断增加。
在递归函数的执行过程中,通常需要考虑递归栈的压栈和出栈操作。
在递归函数被调用时,会执行一些初始化操作,并将递归参数保存到栈中。
在递归函数中,如果遇到递归情况,会再次调用自身,并且将自身的执行环境保存到栈中。
在递归函数的执行过程中,如果遇到基本情况,就会结束当前递归调用,并且从栈中释放空间。
递归算法的原理是基于递归函数的深度调用的。
当递归函数被调用时,会执行一些初始化过程,并将递归参数保存到栈中。
当递归函数执行完毕后,会从栈中释放空间。
在递归函数的执行过程中,栈中的空间会不断增加和释放。
递归算法详解完整版

递归算法详解完整版递归算法是一种重要的算法思想,在问题解决中起到了很大的作用。
它通过将一个大问题划分为相同或类似的小问题,并将小问题的解合并起来从而得到大问题的解。
下面我们将详细介绍递归算法的定义、基本原理以及其应用。
首先,我们来定义递归算法。
递归算法是一种通过调用自身解决问题的算法。
它通常包括两个部分:基础案例和递归步骤。
基础案例是指问题可以被直接解决的边界情况,而递归步骤是指将大问题划分为较小问题并通过递归调用自身解决。
递归算法的基本原理是"自顶向下"的思维方式。
即从大问题出发,不断将问题划分为较小的子问题,并解决子问题,直到达到基础案例。
然后将子问题的解合并起来,得到原始问题的解。
递归算法的最大特点是简洁而优雅。
通过将复杂问题分解为简单问题的解决方式,可以大大减少代码的复杂程度,提高程序的效率和可读性。
但是递归算法也有一些缺点,包括递归深度的限制和复杂度的不确定性。
过深的递归调用可能导致栈溢出,而不合理的递归步骤可能导致复杂度过高。
递归算法有许多应用场景,我们来介绍其中一些典型的应用。
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种基本算法递归递归是一种重要的算法思想,它在计算机科学中得到广泛应用。
本文将介绍六种基本的递归算法,并对其原理和应用进行讲解。
一、递归的基本概念递归是指一个函数在其定义中调用自身的过程。
递归算法通过将一个大问题划分为一个或多个相同或相似的子问题,然后通过解决子问题来解决原始问题。
递归算法具有简洁、优雅以及可读性强的特点,但同时也需要注意递归的停止条件,以避免无限递归的发生。
二、阶乘算法阶乘算法是递归算法中最经典的例子之一。
它的定义如下:```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`为查找范围的起始和结束位置。
递归算法 递推公式求解

递归算法递推公式求解递归算法是一种自我调用的算法,它通过不断将问题分解为更小的子问题来求解问题。
递归算法的核心是递推公式,也称为递归式,它描述了如何将问题分解为子问题,并如何从子问题的解中得到原问题的解。
递推公式通常具有以下形式:T(n) = aT(n/b) + f(n)其中,T(n) 表示问题规模为n 时的时间复杂度,a 表示每次递归调用的次数,b 表示每次递归调用后问题规模缩小的比例,f(n) 表示除了递归调用外的其他操作的时间复杂度。
为了求解递推公式,我们可以使用以下方法:1.迭代法:通过迭代递推公式的方式逐步计算出T(n) 的值。
这种方法比较直观,但对于较大的n 值,迭代次数可能非常多,计算量也会非常大。
2.替换法:通过猜测T(n) 的形式,并将其代入递推公式中进行验证。
如果猜测正确,则可以得到T(n) 的解。
这种方法需要对问题有一定的了解和猜测能力。
3.大师定理:大师定理是一种求解递推公式的通用方法。
它可以根据递推公式的形式,直接给出T(n) 的时间复杂度。
大师定理有多种形式,其中最常用的是以下三种:a. 如果f(n) = O(n^c),其中c < log_b(a),则T(n) = O(n^log_b(a))。
b. 如果f(n) = O(n^c),其中c = log_b(a),则T(n) = O(n^c * log_n)。
c. 如果f(n) = O(n^c),其中c > log_b(a),且对于所有足够大的n,有af(n/b) <= f(n),则T(n) = O(f(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. 递归算法的定义递归算法是一种通过反复调用自身来解决问题的算法。
它通常包含了一个递归出口(基本情况)和一个递归体(递归情况)。
当问题达到递归出口时,算法停止递归并返回结果。
否则,算法继续递归调用自身,将问题分解为规模更小的子问题,并在子问题上进行递归求解。
2. 递归算法的优点与注意事项递归算法具有以下优点:1) 逻辑清晰简洁:递归算法能够使用简洁的方式描述问题的解决过程。
2) 结构灵活:递归算法能够解决各种类型的问题,适用范围广泛。
然而,递归算法也需要注意以下事项:1) 递归深度:递归算法的性能与问题的规模成反比。
递归深度过大可能导致栈溢出或性能下降。
2) 重复计算:递归算法中可能存在重复计算,增加了计算量。
可以使用记忆化技术(如动态规划)来优化递归算法。
3. 递归算法的应用场景递归算法在计算机科学中有广泛的应用,包括但不限于以下领域:1) 数据结构:递归算法常用于处理树、图、链表等数据结构,如树的遍历、图的深度优先搜索等。
2) 排列组合:递归算法可以用于生成排列组合,如全排列、组合数等。
3) 分治算法:分治算法通常使用递归来将问题分解为更小的子问题,并分别求解。
4. 递归算法的实现步骤实现一个递归算法通常包括以下步骤:1) 定义递归出口:确定递归算法何时停止递归,返回结果。
2) 确定递归体:根据问题的特点,将问题分解为规模更小的子问题,并调用自身来解决子问题。
3) 设计递归调用:根据子问题的规模和性质,设计递归调用的方式。
4) 处理子问题的结果:将子问题的结果合并得到原问题的结果。
5. 递归算法的示例:阶乘计算下面通过计算阶乘的例子来具体说明递归算法的工作原理:```python# 递归算法计算阶乘def factorial(n):if n == 0:return 1else:return n * factorial(n-1)```上述代码中,factorial函数通过递归来计算阶乘。
汉诺塔递归算法及详解

汉诺塔递归算法及详解汉诺塔(Hanoi Tower)是一种数学谜题,由法国数学家Édouard Lucas在19世纪中期提出。
这个谜题由三根柱子和一组圆盘组成,圆盘从上到下按照从小到大的顺序放置在柱子上。
问题的目标是将所有圆盘从一个柱子移动到另一个柱子,每次只能移动一个圆盘,并且不能将大的圆盘放在小的圆盘上面。
解决汉诺塔问题的一种常见方法是使用递归算法。
递归是一种数学和计算机科学中常见的方法,通过将复杂的问题分解为更小的相同问题的子问题来解决。
汉诺塔的递归算法主要包含以下步骤:1.将N-1个圆盘从起始柱子移动到中间柱子上,这可以通过将起始柱子作为源柱子,中间柱子作为辅助柱子,目标柱子为空柱子来实现。
这个步骤可以通过递归调用来实现,将起始柱子作为源柱子,中间柱子作为辅助柱子,目标柱子作为空柱子。
2.将第N个圆盘从起始柱子移动到目标柱子上。
3.将N-1个圆盘从中间柱子移动到目标柱子上,这可以通过将中间柱子作为源柱子,目标柱子作为辅助柱子,起始柱子作为空柱子来实现。
这个步骤可以通过递归调用来实现,将中间柱子作为源柱子,目标柱子作为辅助柱子,起始柱子作为空柱子。
下面是一个示例代码,使用递归算法解决汉诺塔问题:```pythondef hanoi(n, source, target, auxiliary):if n > 0:#将N-1个圆盘从起始柱子移动到中间柱子hanoi(n-1, source, auxiliary, target)#将第N个圆盘从起始柱子移动到目标柱子print("Move disk", n, "from", source, "to", target)#将N-1个圆盘从中间柱子移动到目标柱子hanoi(n-1, auxiliary, target, source)#测试n=3hanoi(n, 'A', 'C', 'B')```上述代码中,`hanoi(`函数接受四个参数:圆盘的数量n,起始柱子source,目标柱子target和辅助柱子auxiliary。
c语言递归算法

c语言递归算法C语言递归算法递归算法是一种基于函数调用的编程方法,即一个函数在执行过程中调用自身,以此实现循环的效果。
C语言中递归函数的应用范围很广,可以帮助我们简化代码结构,提高代码复用率和可读性。
在接下来的文章中,将会详细介绍C语言中递归算法的原理和应用。
1.递归算法的基本原理递归算法的原理非常简单,即一个函数在执行过程中,调用自身直到达到某个结束条件。
换句话说,递归算法就是把一个大问题不断地分成小问题,直到小问题可以轻松解决的时候,再逐层返回最终结果。
2.递归算法的应用2.1.阶乘问题递归算法最经典的应用场景之一就是求阶乘。
阶乘的定义是从1乘到给定的数字n,所以我们可以使用递归函数来求解阶乘问题。
即,如果n等于1,则阶乘就是1;否则阶乘为n乘以n-1的阶乘。
代码如下:```cint factorial(int n){if (n == 1)return 1;elsereturn n * factorial(n-1);}```2.2.斐波那契数列斐波那契数列是另一个非常经典的递归算法实现问题。
斐波那契数列的定义是,前两个数都是1,之后的每一个数都是前两个数的和。
以下是斐波那契数列的递归函数的实现:```cint fibonacci(int n){if (n <= 1)return n;elsereturn fibonacci(n-1) + fibonacci(n-2);}```2.3.越界问题递归函数存在一个重要的问题就是越界问题。
如果递归函数的调用层数过多,会容易就会导致栈内存溢出,从而导致程序崩溃。
为了防止这种情况的发生,我们可以使用迭代方法来提高程序的效率和稳定性。
```cint fibonacci(int n){int result[100];result[0] = 1;result[1] = 1;for(int i=2; i<=n; i++)result[i] = result[i-1] + result[i-2];return result[n-1];}```3.总结本文详细介绍了C语言中递归算法的实现原理和应用场景,从阶乘问题到斐波那契数列,每一个问题都展示了递归算法的优点和缺点,以及如何提高程序的效率和稳定性。
数据结构递归算法

数据结构递归算法递归算法是一种常见的算法思想,它可以将一个问题分解成更小的子问题,直到问题的规模足够小,可以直接解决。
在计算机科学中,递归算法通常用于解决树形结构、图形结构等复杂的数据结构问题。
本文将介绍递归算法的基本概念、应用场景以及实现方法。
递归算法的基本概念递归算法是一种自我调用的算法,它通过将一个问题分解成更小的子问题来解决原问题。
递归算法通常包含两个部分:基本情况和递归情况。
基本情况是指问题的规模足够小,可以直接解决。
递归情况是指问题的规模较大,需要将问题分解成更小的子问题来解决。
递归算法的应用场景递归算法通常用于解决树形结构、图形结构等复杂的数据结构问题。
例如,计算一棵二叉树的深度、查找一张图的连通性等问题都可以使用递归算法来解决。
此外,递归算法还可以用于解决一些数学问题,例如计算斐波那契数列、计算阶乘等。
递归算法的实现方法递归算法的实现方法通常包含两个部分:递归函数和递归终止条件。
递归函数是指一个函数调用自身的过程,递归终止条件是指当问题的规模足够小时,递归函数不再调用自身,直接返回结果。
下面以计算斐波那契数列为例,介绍递归算法的实现方法。
斐波那契数列是一个数列,其中每个数都是前两个数的和。
例如,数列的前几个数为0、1、1、2、3、5、8、13、21、34、55、89、144、233、377、610、987、1597、2584、4181、6765、10946、17711、28657、46368、75025、121393、196418、317811、514229、832040、1346269、2178309、3524578、5702887、9227465、14930352、24157817、39088169、63245986、102334155、165580141、267914296、433494437、701408733、1134903170、1836311903、2971215073、4807526976、7778742049、12586269025等。
递归算法详解

递归算法详解递归详解通过运⾏时堆栈来⽀持递归的调⽤,在我们刚接触递归的时候,国内很多教材都采⽤求阶乘和菲波那契数列来描述该思想,就如同深受⼤家敬爱的国产的C语⾔程序设计,⽼谭也⽤了阶乘来描述递归,以⾄于很多新⼿⼀看见阶乘就理所当然的认为是递归,坑了不少⼈,说实在的,描述这个思想还是可以,但是利⽤递归求阶乘可是没有⼀点好处,递归解决菲波那契数列效率更是低得惊⼈,这点是显⽽易见的!废话不多说,接下来我们进⼊正题!(不过说实话,我很讨厌接下来这些太理论的东西,说到底就是那么个意思,⼤家懂就好了,也可以当看看故事!我主要说的就是各种各样递归的实例)1:递归算法的思想递归算法是把问题转化为规模缩⼩了的同类问题的⼦问题。
然后函数(或过程)来表⽰问题的解。
在C语⾔中的运⾏堆栈为他的存在提供了很好的⽀持,过程⼀般是通过函数或⼦过程来实现。
递归算法:在函数或⼦过程的内部,直接或者间接地调⽤⾃⼰的算法。
2:递归算法的特点:递归算法是⼀种直接或者间接地调⽤⾃⾝算法的过程。
在计算机编写程序中,递归算法对解决⼀⼤类问题是⼗分有效的,它往往使算法的描述简洁⽽且易于理解。
递归算法解决问题的特点:(1) 递归就是在过程或函数⾥调⽤⾃⾝。
(2) 在使⽤递归策略时,必须有⼀个明确的递归结束条件,称为递归出⼝。
(3) 递归算法解题通常显得很简洁,但递归算法解题的运⾏效率较低。
所以⼀般不提倡⽤递归算法设计程序。
(4) 在的过程当中系统为每⼀层的返回点、局部量等开辟了栈来存储。
递归次数过多容易造成等。
所以⼀般不提倡⽤递归算法设计程序。
3:递归算法的要求递归算法所体现的“重复”⼀般有三个要求:⼀是每次调⽤在规模上都有所缩⼩(通常是减半);⼆是相邻两次重复之间有紧密的联系,前⼀次要为后⼀次做准备(通常前⼀次的输出就作为后⼀次的输⼊);三是在问题的规模极⼩时必须⽤直接给出解答⽽不再进⾏,因⽽每次递归调⽤都是有条件的(以规模未达到直接解答的⼤⼩为条件),⽆条件递归调⽤将会成为死循环⽽不能正常结束。
C语言的递归算法解析

C语言的递归算法解析递归算法是一种经常在编程中使用的重要技术。
在C语言中,递归算法可以通过函数的自我调用来实现。
本文将对C语言中的递归算法进行详细解析,并介绍递归算法在实际应用中的一些常见场景。
一、什么是递归算法递归算法是一种通过函数的自我调用来解决问题的方法。
在递归算法中,一个函数可以直接或间接地调用自身。
递归算法通常分为两个部分:基本情况和递归情况。
基本情况是指能够直接解决的问题,而递归情况是指将问题划分为子问题并通过递归调用解决。
递归算法的核心思想是将原问题转化为规模更小的子问题,并通过递归调用解决子问题。
递归算法必须要有一个终止条件,否则会进入无限循环,导致程序崩溃或者运行时间过长。
二、递归算法的实现在C语言中,递归算法可以通过函数的自我调用来实现。
下面是一个求解斐波那契数列的递归算法示例:```c#include <stdio.h>int fibonacci(int n) {if (n == 0 || n == 1) {return n;} else {return fibonacci(n-1) + fibonacci(n-2);}}int main() {int n = 10;int result = fibonacci(n);printf("The %dth Fibonacci number is: %d\n", n, result);return 0;}```在上述代码中,`fibonacci`函数通过递归调用自身来求解斐波那契数列的第n个数。
如果n为0或者1,那么直接返回n,否则将问题划分为求解第n-1个数和第n-2个数的和,并通过递归调用来解决子问题。
三、递归算法的优缺点递归算法具有以下优点:1. 递归算法可以简化问题的解决过程,将大问题划分为小问题,降低了问题解决的复杂度。
2. 递归算法的逻辑清晰,代码简洁,易于理解和维护。
然而,递归算法也存在一些缺点:1. 递归算法需要占用大量的系统栈空间,函数的调用层级过深可能导致栈溢出的问题。
递归的实现算法理解

递归的实现算法理解
递归是一种算法设计和编程技巧,它通过将问题分解为更小的子问题来解决复杂的问题。 在递归算法中,函数会调用自身来解决同类型的子问题,直到达到基本情况(递归终止条件 )并返回结果。
递归算法的实现通常包括两个关键要素:递归调用和递归终止条件。
1. 递归调用:在递归算法中,函数会调用自身来解决同类型的子问题。通过递归调用,问 题的规模会不断减小,直到达到基本情况。
递归的实现算法理解
பைடு நூலகம்需要注意的是,递归算法在实现时需要考虑以下几点:
- 确保递归调用能够趋近于终止条件,避免无限递归。 - 确保每次递归调用都能够缩小问题的规模,否则可能导致递归深度过大,影响性能。 - 确保递归终止条件正确且完备,否则可能导致递归无法终止或返回错误的结果。
总结起来,递归是一种强大的算法技巧,通过将问题分解为更小的子问题来解决复杂的问 题。理解递归的实现过程和注意事项,能够帮助我们更好地设计和编写递归算法。
递归的实现算法理解
3. 缩小问题规模:在递归函数中,需要将原始问题分解为更小的子问题。通过缩小问题规 模,递归函数可以逐步解决子问题,直到达到终止条件。
4. 调用递归函数:在递归函数中,需要调用自身来解决子问题。通过递归调用,问题的规 模会逐渐减小,直到达到终止条件。
5. 处理子问题的结果:在递归函数中,需要处理子问题的结果,并将其合并为原始问题的 解。
递归的实现算法理解
2. 递归终止条件:为了避免无限递归,递归算法必须定义一个终止条件,当满足终止条件 时,递归调用将停止并返回结果。
递归算法的实现过程可以用以下步骤描述:
1. 定义递归函数:首先,需要定义一个递归函数,该函数将解决问题的大部分,并在需要 时调用自身来解决子问题。
【算法分析】递归算法的几个经典例子

【算法分析】递归算法的⼏个经典例⼦例⼀:整数划分问题 将正整数n表⽰成⼀系列正整数之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。
正整数n的这种表⽰称为正整数n的划分。
求正整数n的不同划分个数。
例如:正整数6有如下11种不同的划分:6;5+1;4+2,4+1+1;3+3,3+2+1,3+1+1+1;2+2+2,2+2+1+1,2+1+1+1+1;1+1+1+1+1+1在本例中,如果设p(n)为正整数n的划分数,则难以找到递归关系,因此考虑增加⼀个⾃变量:将最⼤加数n1不⼤于m的划分个数记作q(n,m)。
下⾯对可能出现的四种情况进⾏分析:① m=1: 当m等于1时,对n的划分只可能1+1+1+……+1这⼀种情况。
②m>n时: 当m⼤于n时,由于划分中不可能出现负数,所以{n1, n2, n2,… , nk}(n = n1+n2+n3+……+nk)只可能出现⼩于等于n的整数。
故有q(n, m)=q(n, n)⑤m=n时: 当m等于n时,包含n⾃⾝的划分和没有n的划分两个部分。
⽽包含n⾃⾝的划分只有⼀种情况,故有有q(n, n)=1+q(n,n-1)④m<n时: n的m划分有包含m和不包含m两个部分。
其中包含m的部分⽤集合可表⽰为{m, {x1, x2, x3, 4,…, xk}}(其中x1+x2+……+xk=n-m)【详解见图1】,这部分的划分数为q(n-m, m);⽽不包含m的划分中,最⼤值不能为m,故划分数就等于q(n, m)。
所以在m<n时整数n的划分数为:q(n, m)=q(n, m-1)+q(n-m, m)。
【图1:ipad坏了,⼀时找不到纸,后⾯再补吧。
】递归求整数划分:1int q(int n, int m){2if(m==1){3return1;4 }5else if(m>n){6return q(n,n);7 }8else if(m==n){9return q(n,n-1)+1;10 }11else if(m<n){12return q(n-m, m)+q(n,m-1);13 }14 }。
递归及递归算法图解

递归问题的提出
第一步:将问题简化。 – 假设A杆上只有2个圆盘,即汉诺塔有2层,n=2。
A
B
C
递归问题的提出
A
B
C
对于一个有 n(n>1)个圆盘的汉诺塔,将n个圆盘分 为两部分:上面的 n-1 个圆盘和最下面的n号圆盘。将 “上面的n-1个圆盘”看成一个整体。
– 将 n-1个盘子从一根木桩移到另一根木桩上
1
当n 1时
n ! n (n 1)! 当n 1时
long int Fact(int n)
{ long int x;
if (n > 1)
{ x = Fact(n-1);
/*递归调用*/
return n*x; }
else return 1;
/*递归基础*/
}
Fact(n) 开始 传进的参数n N n>1
两种不同的递归函数--递归与迭代
21
(2)递归和迭代有什么差别?
递归和迭代(递推)
迭代(递推):可以自递归基础开始,由前向后依次计算或直
接计算;
递归:可以自递归基础开始,由前向后依次计算或直接计算;
但有些,只能由后向前代入,直到递归基础,寻找一条路径, 然后再由前向后计算。
递归包含了递推(迭代),但递推(迭代)不能覆盖递归。
递归的概念 (5)小结
战德臣 教授
组合 抽象
构造 递归
用递归 定义
用递归 构造
递归计 算/执行
递归 基础
递归 步骤
两种不同的递归函数
递归
迭代
两种不同的递归函数--递归与迭代
20
(1)两种不同的递归函数?
递归和递推:比较下面两个示例
全排列问题的递归算法

全排列问题是一种经典的算法问题,它要求对一组元素进行排列,得到所有可能的排列方式。
全排列问题可以使用递归算法进行求解。
递归算法的基本思路是将原问题分解为若干个子问题,然后求解这些子问题,最后将子问题的解组合起来得到原问题的解。
对于全排列问题,可以将其分解为两个子问题:
1.考虑第一个元素在排列中的位置,将其与后面的元素进行全排列。
2.不考虑第一个元素在排列中的位置,对后面的元素进行全排列。
3.通过递归地求解这两个子问题,可以得到所有可能的排列方式。
具体实现过程如下:
1.定义一个递归函数permute,它接受一个整数n和一个整数数组arr作为参
数。
n表示要排列的元素个数,arr表示要排列的元素。
2.如果n等于0,说明已经排列完了所有的元素,此时直接返回空数组。
3.如果n等于1`,说明只有一个元素需要排列,此时直接返回包含这个元素的
数组。
4.否则,将arr数组分成两部分:第一个元素和后面的元素。
递归地求解以下
两个子问题:
a. 考虑第一个元素在排列中的位置,将其与后面的元素进行全排列。
b. 不考虑第一个元素在排列中的位置,对后面的元素进行全排列。
5.将两个子问题的解组合起来,得到原问题的解。
6.返回原问题的解。
这个算法的时间复杂度是指数级的,因为对于每一个排列方式,它需要递归地求解两个子问题。
因此,当元素个数较大时,这个算法可能会非常耗时。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
递 归冯文科一、递归的基本概念。
一个函数、概念或数学结构,如果在其定义或说明内部直接或间接地出现对其本身的引用,或者是为了描述问题的某一状态,必须要用至它的上一状态,而描述上一状态,又必须用到它的上一状态……这种用自己来定义自己的方法,称之为递归或递归定义。
在程序设计中,函数直接或间接调用自己,就被称为递归调用。
二、递归的最简单应用:通过各项关系及初值求数列的某一项。
在数学中,有这样一种数列,很难求出它的通项公式,但数列中各项间关系却很简单,于是人们想出另一种办法来描述这种数列:通过初值及n a 与前面临近几项之间的关系。
要使用这样的描述方式,至少要提供两个信息:一是最前面几项的数值,一是数列间各项的关系。
比如阶乘数列1、2、6、24、120、720……如果用上面的方式来描述它,应该是:⎩⎨⎧>==-1,1,11n na n a n n如果需要写一个函数来求n a 的值,那么可以很容易地写成这样:这就是递归函数的最简单形式,从中可以明显看出递归函数都有的一个特点:先处理一些特殊情况——这也是递归函数的第一个出口,再处理递归关系——这形成递归函数的第二个出口。
递归函数的执行过程总是先通过递归关系不断地缩小问题的规模,直到简单到可以作为特殊情况处理而得出直接的结果,再通过递归关系逐层返回到原来的数据规模,最终得出问题的解。
以上面求阶乘数列的函数)(n f 为例。
如在求)3(f 时,由于3不是特殊值,因此需要计算)2(*3f ,但)2(f 是对它自己的调用,于是再计算)2(f ,2也不是特殊值,需要计算)1(*2f ,需要知道)1(f 的值,再计算)1(f ,1是特殊值,于是直接得出1)1(=f ,返回上一步,得2)1(*2)2(==f f ,再返回上一步,得62*3)2(*3)3(===f f ,从而得最终解。
用图解来说明,就是下面再看一个稍复杂点的例子。
【例1】数列}{n a 的前几项为1、111+、11111++、1111111+++、……输入n ,编程求n a 的精确分数解。
分析:这个题目较易,发现11=a ,其它情况下有111-+=n n a a 。
如要求实数解的话,这基本已经可以写出递归函数了。
但由于题目要求精确的分数解,还需做一些调整。
设pq a n =-1,则由递归关系,有qp p pq a a n n +=+=+=-11111,再约分化简,即得n a 。
但发现一个问题:求出1-n a 时,需要返回两个整数:分子q 与分母p ,而通常的函数只能返回一个整数。
这个问题一般有两类解决办法,一种是让求值函数返回一个结构体变量,这样就可以返回两个变量了(其实还可以不只两个呢);另一种是在求值函数的参数表中加入两个指针变量或引用变量,通过参数给带回数值。
但由于后一种做法会使程序结构不清晰——返回值是由参数表得到的,因此我们使用前一种方法。
另外,在通过p q a n =-1得出qp pa 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 ,则有r b a r q p mod )(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 a r q p mod )(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,即q p p +是最简分数。
虽然这是个要求1-n a (即pq)是最简分数的结论,但由于数列第二项为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) {1 3 5 7 90 2 4 6 8int 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;}六、练习【练习】为给定的表达式建立表达式树,并求值。
给定的表达式中,所有数字都是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)第1页第2页第3页第4页第5页第6页第7页第8页第9页第10页第11页第12页第13页第14页第15页第16页第17页第18页递 归冯文科一、递归的基本概念。