递归与分治

合集下载

递归算法的优缺点

递归算法的优缺点

递归算法得优缺点:3优点:结构清晰,可读性强,而且容易用数学归纳法来证明算法得正确性,因此它为设计算法、调试程序带来很大方便。

3缺点:递归算法得运行效率较低,无论就是耗费得计算时间还就是占用得存储空间都比非递归算法要多。

边界条件与递归方程就是递归函数得二个要素应用分治法得两个前提就是问题得可分性与解得可归并性以比较为基础得排序算法得最坏倩况时间复杂性下界为0(n I o g2n)。

回溯法以深度优先得方式搜索解空间树T,而分支限界法则以广度优先或以最小耗费优先得方式搜索解空间树T。

舍伍德算法设计得基本思想:设A就是一个确定性算法,当它得输入实例为x时所需得计算时间记为tA(x)。

设Xn就是算法A得输入规模为n得实例得全体,则当问题得输入规模为n时,算法A所需得平均时间为这显然不能排除存在x€Xn使得得可能性。

希望获得一个随机化算法B,使得对问题得输入规模为n得每一个实例均有拉斯维加斯(Las Vegas )算法得基本思想:设p(x)就是对输入x调用拉斯维加斯算法获得问题得一个解得概率。

一个正确得拉斯维加斯算法应该对所有输入x均有p(x)>0。

设t(x)就是算法obst in ate找到具体实例x得一个解所需得平均时间,s(x)与e(x)分别就是算法对于具体实例x求解成功或求解失败所需得平均时间,则有:解此方程可得:蒙特卡罗(Monte Carlo)算法得基本思想:设p就是一个实数,且1/2<p<1。

如果一个蒙特卡罗算法对于问题得任一实例得到正确解得概率不小于p,则称该蒙特卡罗算法就是p正确得,且称p1/2就是该算法得优势。

如果对于同一实例,蒙特卡罗算法不会给出2个不同得正确解答,则称该蒙特卡罗算法就是一致得。

线性规划基本定理:如果线性规划问题有最优解,则必有一基本可行最优解。

单纯形算法得特点就是:(1) 只对约束条件得若干组合进行测试,测试得每一步都使目标函数得值增加;(2) 一般经过不大于m或n次迭代就可求得最优解。

分治算法知识点总结

分治算法知识点总结

分治算法知识点总结一、基本概念分治算法是一种递归的算法,其基本思想就是将原问题分解成多个相互独立的子问题,然后分别解决这些子问题,最后将子问题的解合并得到原问题的解。

分治算法的核心思想可以用一句话概括:分而治之,分即是将原问题分解成若干个规模较小的子问题,治即是解决这些子问题,然后将子问题的解合并起来得到原问题的解。

分治算法通常包括三个步骤:(1)分解:将原问题分解成若干个规模较小的子问题;(2)解决:递归地解决这些子问题;(3)合并:将子问题的解合并起来得到原问题的解。

分治算法的典型特征包括递归和合并。

递归指的是将原问题分解成若干个规模较小的子问题,然后递归地解决这些子问题;合并指的是将子问题的解合并得到原问题的解。

通常来说,分治算法的递归实现方式很容易编写,但有时可能会面临大量的重复计算,因此需要合并操作来避免这种情况。

二、原理分治算法的原理可以通过一个简单的例子来说明。

我们以计算数组中的最大值为例,具体的步骤如下:(1)分解:将数组分解成两个规模相等的子数组;(2)解决:递归地在这两个子数组中分别找到最大值;(3)合并:比较这两个子数组的最大值,得到原数组的最大值。

从这个例子可以看出,分治算法将原问题分解成两个子问题:分别在左边子数组和右边子数组中找到最大值,然后将这两个子问题的解合并起来得到原数组的最大值。

这种将问题分解成若干个规模较小的子问题,然后合并子问题的解得到原问题的解的方法正是分治算法的核心原理。

分治算法的优势在于它可以将原问题分解成多个规模较小的子问题,然后并行地解决这些子问题,最后合并子问题的解得到原问题的解。

这种并行的设计思路使得分治算法非常适合于并行计算,能够有效地提高计算效率。

三、应用分治算法在计算机科学领域有着广泛的应用,包括排序、搜索、图论、动态规划等多个方面。

下面我们将以排序算法和搜索算法为例,来介绍分治算法在实际应用中的具体情况。

1. 排序算法排序算法是计算机科学领域中一个重要的问题,分治算法在排序算法中有着广泛的应用。

常见的程序设计方法

常见的程序设计方法

常见的程序设计方法程序设计是指将问题拆解为一系列可执行的指令或算法,并将其转化为计算机能够识别和执行的代码。

常见的程序设计方法包括顺序、选择、循环、递归、分治和动态规划等。

1.顺序:顺序是最简单和最常见的程序设计方法。

顺序程序设计是按照定义的顺序依次执行一系列的语句或指令,每个语句按照顺序执行,直到程序结束。

顺序程序设计常用于简单的计算和数据处理任务。

2.选择:选择是根据特定条件选择不同的执行路径。

常见的选择结构有if语句和switch语句。

if语句根据条件的真假执行不同的代码块,而switch语句根据不同的表达式值执行相应的代码块。

选择结构常用于根据用户的输入或条件的满足来决定程序的执行逻辑。

3.循环:循环是根据特定条件重复执行段代码。

常见的循环结构有while循环、do-while循环和for循环。

这些循环结构可根据循环条件的真假来确定循环的执行次数,从而实现重复执行特定操作的功能。

循环结构常用于处理大量数据或重复需要进行的任务。

4.递归:递归是指在函数或算法的实现中,调用自身来解决更小规模的同类问题。

递归算法是将一个复杂问题分解为更简单的子问题,并通过反复调用自身来解决子问题,最终达到解决原问题的目的。

递归常用于解决具有相似结构的问题,如数学问题、图形问题等。

5.分治:分治是指将问题划分成独立的子问题,对每个子问题进行求解,最后将子问题的解合并成原问题的解。

分治算法的核心思想是将复杂问题分解成多个规模较小且结构相同的子问题,并通过递归地解决这些子问题,最终得到整个问题的解。

分治算法常用于解决问题、排序问题等。

6.动态规划:动态规划是一种将问题划分为重叠子问题并缓存子问题解的方法。

与分治算法不同的是,动态规划算法会通过缓存已求解的子问题的解来避免重复计算,从而提高算法的效率。

动态规划常用于解决优化问题,如背包问题、最短路径问题等。

除以上常见的程序设计方法外,还有一些高级的方法如面向对象编程、函数式编程和事件驱动编程等。

计算机算法设计五大常用算法的分析及实例

计算机算法设计五大常用算法的分析及实例

计算机算法设计五⼤常⽤算法的分析及实例摘要算法(Algorithm)是指解题⽅案的准确⽽完整的描述,是⼀系列解决问题的清晰指令,算法代表着⽤系统的⽅法描述解决问题的策略机制。

也就是说,能够对⼀定规范的输⼊,在有限时间内获得所要求的输出。

如果⼀个算法有缺陷,或不适合于某个问题,执⾏这个算法将不会解决这个问题。

不同的算法可能⽤不同的时间、空间或效率来完成同样的任务。

其中最常见的五中基本算法是递归与分治法、动态规划、贪⼼算法、回溯法、分⽀限界法。

本⽂通过这种算法的分析以及实例的讲解,让读者对算法有更深刻的认识,同时对这五种算法有更清楚认识关键词:算法,递归与分治法、动态规划、贪⼼算法、回溯法、分⽀限界法AbstractAlgorithm is the description to the problem solving scheme ,a set of clear instructions to solve the problem and represents the describe the strategy to solve the problem using the method of system mechanism . That is to say, given some confirm import,the Algorithm will find result In a limited time。

If an algorithm is defective or is not suitable for a certain job, it is invalid to execute it. Different algorithms have different need of time or space, and it's efficiency are different.There are most common algorithms: the recursive and divide and conquer、dynamic programming method、greedy algorithm、backtracking、branch and bound method.According to analyze the five algorithms and explain examples, make readers know more about algorithm , and understand the five algorithms more deeply.Keywords: Algorithm, the recursive and divide and conquer, dynamic programming method, greedy algorithm、backtracking, branch and bound method⽬录1. 前⾔ (4)1.1 论⽂背景 (4)2. 算法详解 (5)2.1 算法与程序 (5)2.2 表达算法的抽象机制 (5)2.3 算法复杂性分析 (5)3.五中常⽤算法的详解及实例 (6)3.1 递归与分治策略 (6)3.1.1 递归与分治策略基本思想 (6)3.1.2 实例——棋盘覆盖 (7)3.2 动态规划 (8)3.2.1 动态规划基本思想 (8)3.2.2 动态规划算法的基本步骤 (9)3.2.3 实例——矩阵连乘 (9)3.3 贪⼼算法 (11)3.3.1 贪⼼算法基本思想 (11)3.3.2 贪⼼算法和动态规划的区别 (12)3.3.3 ⽤贪⼼算法解背包问题的基本步骤: (12)3.4 回溯发 (13)3.4.1 回溯法基本思想 (13)3.3.2 回溯发解题基本步骤 (13)3.3.3 实例——0-1背包问题 (14)3.5 分⽀限界法 (15)3.5.1 分⽀限界法思想 (15)3.5.2 实例——装载问题 (16)总结 (18)参考⽂献 (18)1. 前⾔1.1 论⽂背景算法(Algorithm)是指解题⽅案的准确⽽完整的描述,是⼀系列解决问题的清晰指令,算法代表着⽤系统的⽅法描述解决问题的策略机制。

分治法的概念

分治法的概念

分治法的概念分治法的概念一、引言在计算机科学和数学领域中,分治法是一种重要的算法设计技术。

它将一个大问题划分成若干个小问题,然后递归地解决每个小问题,并将它们的结果组合起来得到原问题的解。

分治法通常用于解决那些具有重叠子问题和具有相对独立性的子问题的问题。

二、分治法的基本思想分治法是一种递归式算法,其基本思想可以概括为三个步骤:1. 分解:将原问题划分成若干个规模较小、相互独立且与原问题形式相同的子问题。

2. 解决:递归地求解每个子问题。

如果子问题足够小,则直接求解。

3. 合并:将所有子问题的解合并成原问题的解。

三、分治法应用举例1. 归并排序归并排序是一种经典的排序算法,它采用了分治策略。

该算法将待排序数组不断切割为两半,直到每个子数组只剩下一个元素为止。

然后,对这些单元素数组进行合并操作,直到最终得到完整有序数组。

2. 快速排序快速排序也是一种经典的排序算法,它同样采用了分治策略。

该算法选择一个基准元素,将数组中小于等于基准元素的元素放到左边,大于基准元素的元素放到右边。

然后递归地对左右子数组进行排序。

3. 棋盘覆盖问题棋盘覆盖问题是一道经典的计算机科学问题,它可以用分治法来解决。

该问题要求在一个大小为2^n x 2^n的棋盘上,用L型骨牌覆盖所有空格,其中每个L型骨牌占据三个格子且不能重叠。

该问题可以通过将棋盘划分为四个大小相等、形状相似的子棋盘,并递归地解决每个子棋盘来得到解决。

四、分治法的优缺点1. 优点:分治法通常具有高效性和可扩展性。

由于它将大问题划分成若干个小问题,并且每个小问题都可以独立地求解,因此可以很容易地将算法并行化以提高效率。

2. 缺点:分治法通常需要额外的空间来存储子问题和合并结果。

此外,在实践中,分治法的递归深度可能非常大,这可能会导致堆栈溢出等问题。

五、总结分治法是一种重要的算法设计技术,它将一个大问题划分成若干个小问题,并递归地解决每个小问题,最终将它们的结果组合起来得到原问题的解。

分治法的步骤

分治法的步骤

分治法的步骤分治法是一种常见的算法设计策略,它将问题分解成更小的子问题,然后递归地解决每个子问题,最后将这些子问题的解合并起来得到原问题的解。

下面将详细介绍分治法的步骤。

一、分治法的定义和基本思想分治法是一种算法设计策略,它将一个大问题分解成若干个相互独立且结构相同的小问题,递归地求解这些小问题,并将它们的结果组合起来得到原问题的解。

在实际应用中,分治法通常用于处理那些具有重复性质或者可以通过递归实现的计算任务。

二、分治法的步骤1. 分解:首先将原问题划分为若干个规模较小、结构相似且独立的子问题。

这个过程通常称为“分解”(divide)。

2. 解决:对每个子问题进行递归求解。

如果子问题足够小而可以直接求解,则直接求解。

这个过程通常称为“解决”(conquer)。

3. 合并:将所有子问题的结果合并成原问题的结果。

这个过程通常称为“合并”(combine)。

三、应用场景1. 排序算法:例如归并排序、快速排序等。

2. 查找算法:例如二分查找。

3. 图论算法:例如最大子数组、矩阵乘法、汉诺塔等。

四、分治法的优缺点1. 优点:分治法可以有效地解决一些具有重复性质或者可以通过递归实现的计算任务,具有较高的效率和可扩展性。

2. 缺点:分治法需要额外的空间来存储子问题的结果,而且在递归过程中可能会出现栈溢出等问题,需要进行合理的优化。

同时,如果分解得不够合理或者子问题之间存在依赖关系,则可能会导致算法效率下降。

五、总结分治法是一种常见的算法设计策略,它将一个大问题划分为若干个规模较小、结构相似且独立的子问题,并递归地求解这些子问题。

在实际应用中,分治法通常用于处理那些具有重复性质或者可以通过递归实现的计算任务。

虽然分治法具有较高的效率和可扩展性,但也存在额外空间开销和栈溢出等问题,需要进行合理优化。

主方法,递归法

主方法,递归法

主方法,递归法
"主方法" 和 "递归法" 通常在算法和数据结构的课程中提到,尤其是在介绍
排序算法的时候。

在这里,我将对它们进行简要的解释:
1. 主方法(Master Method):这是用于分析某些特定的分治算法(如快
速排序和归并排序)的时间复杂度的方法。

主方法主要基于递归关系的分析,以及对于最坏、平均和最好情况下的时间复杂度估计。

2. 递归法(Recursive Method):这是一种解决问题的方法,其中问题被
分解为更小的子问题,然后这些子问题的解被用来解决原始问题。

递归是许多算法(包括排序算法)的核心思想,因为它允许我们处理大规模数据集,通过将它们分解为更小的部分来简化问题。

在排序算法中,递归通常与分治策略一起使用。

例如,快速排序就是一个使用递归和分治的例子。

快速排序的基本思想是选择一个"主元",然后将数组分为两部分,左边的元素都比主元小,右边的元素都比主元大。

然后对这两部分递归地进行排序。

如果你是在询问编程中的方法或函数,那么"主方法"可能是指某个特定语言或框架的主要入口点,如Java的`public static void main(String[] args)`。

在这种情况下,"递归法"可能是指一种通过反复调用自身来解决问题的编程技术。

希望这能帮到你!如果你有关于这两个概念的具体问题或需要更详细的解释,请告诉我!。

用递归算法实现汉诺塔问题。

用递归算法实现汉诺塔问题。

用递归算法实现汉诺塔问题。

汉诺塔问题是一个经典的递归问题,它涉及到的思维方式是分治法,而递归则是实现分治法的一种方式。

要解决汉诺塔问题,我们需要了解其规则和思路。

汉诺塔游戏的规则如下:1. 有三根柱子A、B、C,开始时A柱上有一些大小不等的圆盘,按大小从上到下依次叠放。

2. 目标是把A柱上的圆盘全部移到C柱上,可以借助B柱。

3. 每次只能移动一个圆盘,且大圆盘不能叠在小圆盘上。

解决汉诺塔问题的思路:1. 对于每个规模为n的问题,我们可以分解为三个步骤:将A柱上的n-1个圆盘移到B柱上,将A柱上的最大圆盘移到C柱上,最后将B柱上的n-1个圆盘移到C柱上。

2. 每个步骤都是一个规模为n-1的子问题,因此可以使用递归来解决。

接下来,我们用递归算法实现汉诺塔问题。

```pythondef hanoi(n, A, B, C):"""递归函数hanoi参数:n:表示A柱上的圆盘数量A:表示原柱子B:表示辅助柱子C:表示目标柱子"""if n == 1: # 如果只有一个圆盘,直接从A柱移到C柱print(f"将第1个圆盘从 {A} 移动到 {C}")returnelse:# 将A柱上的n-1个圆盘移到B柱上hanoi(n-1, A, C, B)# 将A柱上的最大圆盘移到C柱上print(f"将第{n}个圆盘从 {A} 移动到 {C}")# 将B柱上的n-1个圆盘移到C柱上hanoi(n-1, B, A, C)# 测试n = 3 # 圆盘数量为3hanoi(n, 'A', 'B', 'C')```对于圆盘数量为3的情况,我们可以得到以下步骤:将第1个圆盘从 A 移动到 C将第2个圆盘从 A 移动到 B将第1个圆盘从 C 移动到 B将第3个圆盘从 A 移动到 C将第1个圆盘从 B 移动到 A将第2个圆盘从 B 移动到 C将第1个圆盘从 A 移动到 C通过递归的方式,我们可以解决汉诺塔问题并打印出每一步的移动过程。

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

分治算法一、分治算法分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。

求出子问题的解,就可得到原问题的解。

分治法解题的一般步骤:(1)分解,将要解决的问题划分成若干规模较小的同类问题;(2)求解,当子问题划分得足够小时,用较简单的方法解决;(3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。

当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。

对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。

如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。

这就是分治策略的基本思想。

下面通过实例加以说明。

【例1】[找出伪币] 给你一个装有1 6个硬币的袋子。

1 6个硬币中有一个是伪造的,并且那个伪造的硬币比真的硬币要轻一些。

你的任务是找出这个伪造的硬币。

为了帮助你完成这一任务,将提供一台可用来比较两组硬币重量的仪器,利用这台仪器,可以知道两组硬币的重量是否相同。

比较硬币1与硬币2的重量。

假如硬币1比硬币2轻,则硬币1是伪造的;假如硬币2比硬币1轻,则硬币2是伪造的。

这样就完成了任务。

假如两硬币重量相等,则比较硬币3和硬币4。

同样,假如有一个硬币轻一些,则寻找伪币的任务完成。

假如两硬币重量相等,则继续比较硬币5和硬币6。

按照这种方式,可以最多通过8次比较来判断伪币的存在并找出这一伪币。

另外一种方法就是利用分而治之方法。

假如把1 6硬币的例子看成一个大的问题。

第一步,把这一问题分成两个小问题。

随机选择8个硬币作为第一组称为A组,剩下的8个硬币作为第二组称为B组。

这样,就把1 6个硬币的问题分成两个8硬币的问题来解决。

第二步,判断A和B组中是否有伪币。

可以利用仪器来比较A组硬币和B组硬币的重量。

假如两组硬币重量相等,则可以判断伪币不存在。

假如两组硬币重量不相等,则存在伪币,并且可以判断它位于较轻的那一组硬币中。

最后,在第三步中,用第二步的结果得出原先1 6个硬币问题的答案。

若仅仅判断硬币是否存在,则第三步非常简单。

无论A组还是B组中有伪币,都可以推断这1 6个硬币中存在伪币。

因此,仅仅通过一次重量的比较,就可以判断伪币是否存在。

现在假设需要识别出这一伪币。

把两个或三个硬币的情况作为不可再分的小问题。

注意如果只有一个硬币,那么不能判断出它是否就是伪币。

在一个小问题中,通过将一个硬币分别与其他两个硬币比较,最多比较两次就可以找到伪币。

这样,1 6硬币的问题就被分为两个8硬币(A组和B组)的问题。

通过比较这两组硬币的重量,可以判断伪币是否存在。

如果没有伪币,则算法终止。

否则,继续划分这两组硬币来寻找伪币。

假设B是轻的那一组,因此再把它分成两组,每组有4个硬币。

称其中一组为B1,另一组为B2。

比较这两组,肯定有一组轻一些。

如果B1轻,则伪币在B1中,再将B1又分成两组,每组有两个硬币,称其中一组为B1a,另一组为B1b。

比较这两组,可以得到一个较轻的组。

由于这个组只有两个硬币,因此不必再细分。

比较组中两个硬币的重量,可以立即知道哪一个硬币轻一些。

较轻的硬币就是所要找的伪币。

【例2】在n个元素中找出最大元素和最小元素。

我们可以把这n个元素放在一个数组中,用直接比较法求出。

算法如下:void maxmin1(int A[],int n,int *max,int *min){ int i;*min=*max=A[0];for(i=2;i < n;i++){ if(A> *max) *max= A;if(A < *min) *min= A;}}上面这个算法需比较2(n-1)次。

能否找到更好的算法呢?我们用分治策略来讨论。

把n个元素分成两组:A1={A[1],...,A[int(n/2)]}和A2={A[INT(N/2)+1],...,A[N]}分别求这两组的最大值和最小值,然后分别将这两组的最大值和最小值相比较,求出全部元素的最大值和最小值。

如果A1和A2中的元素多于两个,则再用上述方法各分为两个子集。

直至子集中元素至多两个元素为止。

例如有下面一组元素:-13,13,9,-5,7,23,0,15。

用分治策略比较的过程如下:图中每个方框中,左边是最小值,右边是最大值。

从图中看出,用这种方法一共比较了10次,比直接比较法的14次减少4次,即约减少了1/3。

算法如下:void maxmin2(int A[],int i,int j,int *max,int *min)/*A存放输入的数据,i,j存放数据的范围,初值为0,n-1,*max,int *m in 存放最大和最小值*/{ int mid,max1,max2,min1,min2;if (j==i) {最大和最小值为同一个数;return;}if (j-1==i) {将两个数直接比较,求得最大会最小值;return;}mid=(i+j)/2;求i~mid之间的最大最小值分别为max1,min1;求mid+1~j之间的最大最小值分别为max2,min2;比较max1和max2,大的就是最大值;比较min1和min2,小的就是最小值;}利用分治策略求解时,所需时间取决于分解后子问题的个数、子问题的规模大小等因素,而二分法,由于其划分的简单和均匀的特点,是经常采用的一种有效的方法,例如二分法检索。

运用分治策略解决的问题一般来说具有以下特点:1、原问题可以分解为多个子问题,这些子问题与原问题相比,只是问题的规模有所降低,其结构和求解方法与原问题相同或相似。

2、原问题在分解过程中,递归地求解子问题,由于递归都必须有一个终止条件,因此,当分解后的子问题规模足够小时,应能够直接求解。

3、在求解并得到各个子问题的解后,应能够采用某种方式、方法合并或构造出原问题的解。

不难发现,在分治策略中,由于子问题与原问题在结构和解法是的相似性,用分治方法解决的问题,大都采用了递归的形式。

在各种排序方法中,如归并排序、堆排序、快速排序等,都存在有分治的思想。

递归算法递归算法:是一种直接或者间接地调用自身的算法。

在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。

递归算法的特点递归过程一般通过函数或子过程来实现。

递归算法:在函数或子过程的内部,直接或者间接地调用自己的算法。

递归算法的实质:是把问题转化为规模缩小了的同类问题的子问题。

然后递归调用函数(或过程)来表示问题的解。

递归算法解决问题的特点:(1) 递归就是在过程或函数里调用自身。

(2) 在使用递增归策略时,必须有一个明确的递归结束条件,称为递归出口。

(3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。

所以一般不提倡用递归算法设计程序。

(4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。

递归次数过多容易造成栈溢出等。

所以一般不提倡用递归算法设计程序。

递归算法所体现的“重复”一般有三个要求:一是每次调用在规模上都有所缩小(通常是减半);二是相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入);三是在问题的规模极小时必须用直接给出解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),无条件递归调用将会成为死循环而不能正常结束。

例子如下:描述:把一个整数按n(2<=n<=20)进制表示出来,并保存在给定字符串中。

比如121用二进制表示得到结果为:“1111001”。

参数说明:s: 保存转换后得到的结果。

n: 待转换的整数。

b: n进制(2<=n<=20)voidnumbconv(char *s, int n, int b){int len;if(n == 0) {strcpy(s, "");return;}/* figure out first n-1 digits */numbconv(s, n/b, b);/* add last digit */len = strlen(s);s[len] = "0123456789ABCDEFGHIJKLMNOPQRSTUVW XYZ"[n%b];s[len+1] = '\0';}voidmain(void){char s[20];int i, base;FILE *fin, *fout;fin = fopen("palsquare.in", "r");fout = fopen("palsquare.out", "w");assert(fin != NULL && fout != NULL);fscanf(fin, "%d", &base);/*PLS set START and END*/for(i=START; i <= END; i++) {numbconv(s, i*i, base);fprintf(fout, "%s\n", s);}exit(0);}递归算法简析(PASCAL语言)递归是计算机科学的一个重要概念,递归的方法是程序设计中有效的方法,采用递归编写程序能是程序变得简洁和清晰.一递归的概念1.概念一个过程(或函数)直接或间接调用自己本身,这种过程(或函数)叫递归过程(或函数).如:procedure a;begin...a;...end;这种方式是直接调用.又如:procedure b; procedure c;begin begin. .. .. .c; b;. .. .. .end; end;这种方式是间接调用.例1计算n!可用递归公式如下:1 当n=0 时fac(n)={n*fac(n-1) 当n>0时可编写程序如下:program fac2;varn:integer;function fac(n:integer):real;beginif n=0 then fac:=1 else fac:=n*fac(n-1) end;beginwrite('n=');readln(n);writeln('fac(',n,')=',fac(n):6:0);end.例2 楼梯有n阶台阶,上楼可以一步上1阶,也可以一步上2阶,编一程序计算共有多少种不同的走法.设n阶台阶的走法数为f(n)显然有1 n=1f(n)={f(n-1)+f(n-2) n>2可编程序如下:program louti;var n:integer;function f(x:integer):integer;beginif x=1 then f:=1 elseif x=2 then f:=2 else f:=f(x-1)+f(x-2);end;beginwrite('n=');read(n);writeln('f(',n,')=',f(n))end.二,如何设计递归算法1.确定递归公式2.确定边界(终了)条件三,典型例题例3 梵塔问题如图:已知有三根针分别用1,2,3表示,在一号针中从小放n个盘子,现要求把所有的盘子从1针全部移到3针,移动规则是:使用2针作为过度针,每次只移动一块盘子,且每根针上不能出现大盘压小盘.找出移动次数最小的方案.程序如下:program fanta;varn:integer;procedure move(n,a,b,c:integer);beginif n=1 then writeln(a,'--->',c)else beginmove(n-1,a,c,b);writeln(a,'--->',c);move(n-1,b,a,c);end;end;beginwrite('Enter n=');read(n);move(n,1,2,3);end.例4 快速排序快速排序的思想是:先从数据序列中选一个元素,并将序列中所有比该元素小的元素都放到它的右边或左边,再对左右两边分别用同样的方法处之直到每一个待处理的序列的长度为1, 处理结束.程序如下:program kspv;const n=7;typearr=array[1..n] of integer;vara:arr;i:integer;procedure quicksort(var b:arr; s,t:integer);var i,j,x,t1:integer;begini:=s;j:=t;x:=b ;repeatwhile (b[j]>=x) and (j>i) do j:=j-1;if j>i then begin t1:=b; b:=b[j];b[j]:=t1;end;while (b<=x) and (i<j) do i:=i+1;if i<j then begin t1:=b[j];b[j]:=b;b:=t1; enduntil i=j;b:=x;i:=i+1;j:=j-1;if s<j then quicksort(b,s,j);if i<t then quicksort(b,i,t);end;beginwrite('input data:');for i:=1 to n do read(a);writeln;quicksort(a,1,n);write('output data:');for i:=1 to n do write(a:6);writeln;end.二叉树遍历二叉树的遍历搜索路径遍历概念:所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。

相关文档
最新文档