快速排序递归详解流程图(大框架)
- 格式:pptx
- 大小:70.48 KB
- 文档页数:79
1 如果 n=0,n=1f(n)=nf(n) 如果 n>1图1:以递归的方式计算4的阶乘上图(1)展示了利用递归计算4!的过程。
它也说明了递归过程中的两个基本阶段:递推和回归。
在递推阶段,每一个递归调用通过进一步调用自己来记住这次递归过程。
当其中有调用满足终止条件时,递推结束。
比如,在计算n!时,终止条件是当n=1和n=0,此时函数只需简单的返回1即可。
每一个递归函数都必须拥有至少一个终止条件;否则递推阶段永远不会结束了。
一旦递推阶段结束,处理过程就进入回归阶段,在这之前的函数调用以逆序的方式回归,直到最初调用的函数为止,此时递归过程结束。
以递归的方式计算n的阶乘的函数实现:C函数fact的工作方式如下:它接受一个整数n作为参数,如果n小于0,该函数直接返回0,这代表一个错误。
如果n等于0或1,该函数返回1,这是因为0!和1!都等于1,以上是终止递归的条件。
否则,函数返回n-1的阶乘的n倍。
而n-1的阶乘又会以递归的方式再次调用fact来计算,如此继续。
代码实例(1):fact.c1/*fact.c*/2#include "fact.h"3int fact(int n){4if (n<0)5return0;6else if(n==0)7return1;8else if(n==1)9return1;10else11return n*f(n-1);12}为理解递归究竟是如何工作的,有必要先看看C语言中函数的执行方式。
我们先来看看C程序在内存中的组织方式(见图2-a)。
基本上,一个可执行程序由4个区域组成:代码段、静态数据区、堆与栈。
代码段包含程序运行时所执行的机器指令。
静态数据区包含在程序生命周期内一直持久的数据,比如全局变量和静态局部变量。
堆包含程序运行时动态分配的存储空间,比如malloc分配的内存。
栈包含函数调用的信息。
当C中调用了一个函数时,栈中会分配一块空间来保存与这个调用相关的信息。
递归查找方法
1.二分查找法:递归地在有序数组中查找目标元素。
该方法
首先将数组的中间元素与目标元素进行比较,如果相等则返回
该元素的索引,如果目标元素小于中间元素,则在数组的左半
部分继续查找,否则在数组的右半部分继续查找,直到找到目
标元素或者数组为空。
2.深度优先搜索算法(DFS):在图结构中查找目标元素。
DFS通过递归地遍历图的邻接节点来查找目标元素。
具体实现时,需要使用一个布尔数组来标记已经访问过的节点,以避免
重复访问。
3.广度优先搜索算法(BFS):同样用于图结构中查找目标
元素。
BFS通过递归地遍历图的邻接节点,但是与DFS不同的是,BFS通过使用一个队列来实现节点的访问顺序。
具体实现时,首先将起始节点入队列,然后按照先入先出的顺序逐个出
队列并访问节点的邻接节点,直到找到目标元素或者队列为空。
4.递归遍历树结构:在树结构中查找目标元素的最直接方法
是通过递归地遍历树的每个节点来查找。
这种方法可以使用前序、中序或后序遍历三种方式来实现,具体选择哪种方式取决
于具体问题的要求。
快速排序(QuickSort)⼀、思路快速排序是⼀种分治排序算法。
快速排序先把数组重新整理分割两个⼦数组,然后对两个⼦数组进⾏排序。
快速排序和归并排序是互补的:归并排序中,算法先将数组分为两个⼦数组进⾏排序,再将两个⼦数组进⾏归并成⼀个有序的数组。
快速排序中,算法先对数组进⾏重新整理分割成两个⼦数组,再对两个⼦数组进⾏排序,当两个⼦数组是有序时,整个数组即为有序的。
归并排序中,递归调⽤发⽣在处理整个数组之前。
快速排序中,递归调⽤发⽣在处理整个数组之后。
归并排序数组是对半平分的,快速排序数组切分位置取决于数组的内容。
归并排序代码: private static void sort(Comparable[] input, int lo, int hi) {if(lo >= hi)//just one entry in arrayreturn;int mid = lo + (hi-lo)/2;sort(input, lo, mid);sort(input, mid+1, hi);merge(input, lo, mid, hi);}快速排序代码: private static void sort(Comparable[] a, int lo, int hi) {if(hi <= lo)return;int j = partition(a, lo, hi);sort(a, lo, j-1);sort(a, j+1, hi);}快速排序的关键在于partition⽅法,执⾏完partition⽅法之后应该达到,a[j]就是最终位置,a[lo~(j-1)]都要⼩于或等于a[j],a[j+1~hi]都要⼤于或等于a[j]。
策略:1、选a[lo]作为切分元素2、从数组左端开始查找⼤于或等于a[lo]的元素(下标i<=hi)3、从数组右端开始查找⼩于或等于a[lo]的元素(下标j>=lo)4、交换这两个元素。
人教版必修三1.1.2程序框图[例1]利用梯形的面积公式计算上底为2,下底为4,高为5的梯形面积,设计出该问题的算法及程序框图.[自主解答]算法如下:第一步,a=2,b=4,h=5.其次步,S=12(a+b)h.第三步,输出S.该算法的程序框图如图所示:——————————————————(1)挨次结构的适用范围:数学中很多问题都可以按挨次结构设计算法,如运用公式进行计算、几何中的作图步骤等.(2)应用挨次结构表示算法的步骤:①认真审题,理清题意,找到解决问题的方法;②梳理解题步骤;③用数学语言描述算法,明确输入量、计算过程、输出量;④用程序框图表示算法过程.——————————————————————————————————————1.已知圆的半径,设计一个算法求圆的周长和面积的近似值,并用程序框图表示.解:算法步骤如下:第一步,输入圆的半径R. 其次步,计算L=2πR. 第三步,计算S=πR2.第四步,输出L和S.程序框图:条件结构[例2]设计一个算法推断由键盘输入的一个整数是不是偶数,并画出程序框图.(提示:看被2除的余数是否为零)[自主解答]算法分析:第一步,输入整数x.其次步,令y是x除以2所得的余数.第三步,推断y是否为零,若y是零,输出“是偶数”,结束算法;若y不是零,输出“不是偶数”,结束算法.程序框图:——————————————————1.凡是依据条件作出推断,再打算进行哪一个步骤的问题,在使用程序框图时,必需引入推断框,应用条挨次结构件结构,如分段函数求值,数据的大小比较及含“若……,则……”字样的问题等2.解题时应留意:经常先推断条件,再打算程序流向推断框有两个出口,但在最终执行程序时,选择的路线只有一条.——————————————————————————————————————2.儿童乘坐火车时,若身高不超过1.2 m ,则无需购票;若身超群过1.2 m ,但不超过1.5 m ,可买半票;若超过1.5 m ,应买全票,请设计一个算法,并画出程序框图.解:依据题意,该题的算法中应用条件结构,首先以身高为标准,分成买票和免费,在买票中再分出半票和全票.买票的算法步骤如下:第一步:测量儿童身高h .其次步:假如h ≤1.2 m ,那么免费乘车,否则若h ≤1.5 m ,则买半票,否则买全票. 程序框图如图所示:如图所示,是求函数y =|x -3|的函数值的程序框图,则①处应填________,②处应填________.[巧思] 借助学习过函数y =|x -3|=⎩⎪⎨⎪⎧x -3, x ≥3,3-x , x <3.故而①处应推断x <3?,若条件为否也就是x ≥3,则执行y =x -3.[妙解] ∵y =|x -3|=⎩⎪⎨⎪⎧x -3, x ≥3,3-x , x <3.∴①中应填x <3? 又∵若x ≥3,则y =x -3. ∴②中应填y =x -3. [答案] x <3? y =x -3[例1] 设计求12+22+32+…+n 2的一个算法,并画出相应的程序框图. [自主解答] 第一步,令i =1,S =0. 其次步,S =S +i 2. 第三步,i =i +1.第四步,若i 不大于n ,则转到其次步,否则输出S . 程序框图:——————————————————1.用循环结构描述算法,需确定三件事 (1)确定循环变量和初始条件;(2)确定算法中反复执行的部分,即循环体;(3)确定循环的循环条件.2.留意事项(1)不要漏掉流程线的箭头.(2)与推断框相连的流程线上要标注“是”或“否”.(3)循环结构要在某个条件下终止循环,这就需要用条件结构来推断,因此循环结构中肯定包含条件结构,但不允许是死循环.3.一个循环结构可以使用当型,也可以使用直到型,但依据条件限制的不同,有时用当型比用直到型要好,关键是看题目中给定的条件,有时用两种循环都可以.当型循环结构是指当条件满足时执行循环体,直到。
八大排序算法排序的基本概念排序是将一批(组)任意次序的记录重新排列成按关键字有序的记录序列的过程。
排序算法有许多,但就全面性能而言,还没有一种公认为最好的。
每种算法都有其优点和缺点,分别适合不同的数据量和硬件配置。
评价排序算法的标准有:执行时间和所需的辅助空间,其次是算法的稳定性。
若排序算法所需的辅助空间不依赖问题的规模n,即空间复杂度是O(1) ,则称排序方法是就地排序,否则是非就地排序。
排序的分类待排序的记录数量不同,排序过程中涉及的存储器的不同,有不同的排序分类。
① 待排序的记录数不太多:所有的记录都能存放在内存中进行排序,称为内部排序;② 待排序的记录数太多:所有的记录不可能存放在内存中, 排序过程中必须在内、外存之间进行数据交换,这样的排序称为外部排序。
内部排序的基本操作对内部排序地而言,其基本操作有两种:◆ 比较两个关键字的大小;◆ 存储位置的移动:从一个位置移到另一个位置。
第一种操作是必不可少的;而第二种操作却不是必须的,取决于记录的存储方式,具体情况是:① 记录存储在一组连续地址的存储空间:记录之间的逻辑顺序关系是通过其物理存储位置的相邻来体现,记录的移动是必不可少的;② 记录采用链式存储方式:记录之间的逻辑顺序关系是通过结点中的指针来体现,排序过程仅需修改结点的指针,而不需要移动记录;③ 记录存储在一组连续地址的存储空间:构造另一个辅助表来保存各个记录的存放地址(指针) :排序过程不需要移动记录,而仅需修改辅助表中的指针,排序后视具体情况决定是否调整记录的存储位置。
①比较适合记录数较少的情况;而②、③则适合记录数较少的情况。
为讨论方便,假设待排序的记录是以①的情况存储,且设排序是按升序排列的;关键字是一些可直接用比较运算符进行比较的类型。
一交换类排序法所谓交换排序法是指借助数据元素之间互相交换进行排序的方法。
冒泡排序与快速排序法都属于交换类排序方法。
交换排序— 冒泡排序:基本思想:1.比较相邻的元素。
c++分治算法详解摘要:1.分治算法概述2.C++分治算法实现a.快速排序b.归并排序c.赫夫曼编码3.分治算法的优势和应用4.C++分治算法案例分析a.快速排序案例b.归并排序案例c.赫夫曼编码案例5.总结正文:C++分治算法详解分治算法是一种将大问题分解为若干个相同或相似的小问题,然后逐个解决小问题,最后将小问题的解合并得到大问题的解的算法。
这种算法的设计思想是将一个难以直接解决的问题,分割成一些规模较小的相同问题,以便各个击破。
分治算法广泛应用于计算机科学、数学、物理学等领域,其中快速排序、归并排序、赫夫曼编码等是常见的分治算法。
C++分治算法实现1.快速排序快速排序是一种常用的分治算法,它采用分治策略将待排序的数组划分为较小和较大的两个子数组,然后递归地对子数组进行排序,最终合并得到有序数组。
快速排序的平均时间复杂度为O(nlogn),它有效地提高了排序速度。
2.归并排序归并排序也是一种分治算法,它将待排序的数组划分为较小和较大的两个子数组,然后递归地对子数组进行排序,最后将有序的子数组合并得到有序数组。
归并排序的时间复杂度为O(nlogn),空间复杂度为O(n)。
3.赫夫曼编码赫夫曼编码是一种基于分治思想的压缩算法,它将原始数据分为若干个子数据,然后对子数据进行编码,最后将编码后的子数据合并得到压缩后的数据。
赫夫曼编码能够实现最优压缩,即压缩后的数据长度最短。
分治算法的优势和应用分治算法具有以下优势:1.将大问题分解为小问题,降低问题的复杂度,便于解决。
2.递归地解决小问题,可以减少代码的编写。
3.分治算法可以有效地提高排序速度。
分治算法广泛应用于排序、查找、压缩等领域。
例如,快速排序和归并排序用于对数组进行排序,赫夫曼编码用于数据压缩。
C++分治算法案例分析1.快速排序案例假设有一个长度为10 的数组{5, 2, 9, 1, 5, 6},采用快速排序进行排序。
首先,将数组划分为较小和较大的两个子数组,即{1, 2, 5, 5}和{9, 6}。
递归的用法递归是一种编程技巧,它允许函数在其定义中调用自身。
递归的用法广泛且强大,能够解决许多复杂问题。
在理解递归的用法时,我们首先要明白其基本概念和适用场景。
递归的基本思想是将一个复杂问题分解为两个或多个相同或相似的子问题,直到子问题变得足够简单,可以直接解决。
然后,通过组合这些简单问题的解,我们可以得到原始复杂问题的解。
递归的用法在多种场合下都非常有用。
以下是一些常见的递归应用场景:阶乘计算:阶乘是递归的经典示例之一。
n的阶乘可以定义为n乘以(n-1)的阶乘,直到n为1时停止递归。
这种递归定义非常直观,并且很容易用代码实现。
斐波那契数列:斐波那契数列是另一个递归的经典示例。
每个数字是前两个数字的和,可以通过递归函数轻松计算。
树形结构遍历:在数据结构中,树形结构(如二叉树)的遍历(前序、中序、后序遍历)经常使用递归实现。
通过递归调用,我们可以轻松遍历整个树形结构。
深度优先搜索(DFS):在图形算法中,深度优先搜索是一种常用的搜索算法,它通过递归的方式访问图形的顶点。
解析表达式:在编译器设计中,解析表达式(如算术表达式或逻辑表达式)通常使用递归实现。
通过递归调用,我们可以轻松地解析复杂的嵌套表达式。
除了以上几个例子外,递归还在许多其他领域得到应用,如动态规划、分治算法等。
然而,需要注意的是,递归虽然强大,但也可能导致性能问题,特别是在处理大规模数据时。
因此,在使用递归时,我们需要仔细考虑其适用性和性能影响。
总之,递归是一种非常有用的编程技巧,能够解决许多复杂问题。
通过理解递归的基本思想和适用场景,我们可以更好地利用这一工具,编写出更高效、更简洁的代码。
一插入排序1.1 直接插入排序基本思想:每次将一个待排序额记录按其关键码的大小插入到一个已经排好序的有序序列中,直到全部记录排好序。
图解:代码实现:[cpp]view plaincopy1.//直接顺序排序2.void InsertSort(int r[],int n)3.{4.for(int i=2;i<n;i++)5.{6.r[0]=r[i];//设置哨兵7.for(int j=i-1;r[0]<r[j];j--)//寻找插入位置8.r[j+1]=r[j];//记录后移9.r[j+1]=r[0];10.}11.for(int k=1;k<n;k++)12.cout<<r[k]<<"";13.cout<<"\n";14.}1.2 希尔排序基本思想是:先将整个待排序记录序列分割成若干个子序列,在在序列内分别进行直接插入排序,待整个序列基本有序时,再对全体记录进行一次直接插入排序。
图解:代码实现:[cpp]view plaincopy1.<spanstyle="font-size:14px;">//希尔排序2.void ShellSort(int r[],int n)3.{4.int i;5.int d;6.int j;7.for(d=n/2;d>=1;d=d/2)//以增量为d进行直接插入排序8.{9.for(i=d+1;i<n;i++)10.{11.r[0]=r[i];//暂存被插入记录12.for(j=i-d;j>0&&r[0]<r[j];j=j-d)13.r[j+d]=r[j];//记录后移d个位置14.r[j+d]=r[0];15.}16.}17.for(i=1;i<n;i++)18.cout<<r[i]<<"";19.cout<<"\n";20.}</span>二交换排序2.1 起泡排序起泡排序是交换排序中最简单的排序方法,其基本思想是:两两比较相邻记录的关键码,如果反序则交换,直到没有反序的记录为止。
冒泡排序流程图冒泡排序是一种简单且经典的排序算法。
其基本思想是通过相邻元素之间的比较和交换,将较大的元素往后移动,直到所有元素都按照从小到大的顺序排列。
下面是一篇关于冒泡排序的流程图和详细解析。
冒泡排序的流程图如下:```开始冒泡排序设定标志flag为true,表示本轮比较存在交换操作FOR i=0 TO 数组长度-1IF flag为false退出循环flag设为falseFOR j=0 TO 数组长度-i-2IF 第j个元素 > 第j+1个元素交换第j个元素和第j+1个元素flag设为true输出排序后的数组```接下来详细解析一下流程图:1. 首先,开始冒泡排序,并且设置一个标志flag为true,用来表示本轮比较时是否有交换操作。
2. 使用两个嵌套循环来进行比较和交换操作。
外层循环控制比较的轮数,内层循环控制每轮比较的次数。
3. 在内层循环开始前,先判断flag的值是否为false,如果为false,表示上一轮比较没有任何交换操作,即数组已经有序,此时退出循环。
4. 将flag设为false,表示本轮比较开始时还没有交换操作。
5. 进入内层循环,在每轮比较中,依次比较相邻的两个元素,如果前一个元素大于后一个元素,则交换这两个元素。
6. 如果发生交换操作,则将flag设为true,表示本轮比较存在交换操作。
7. 继续进行下一次内层循环,直到内层循环结束。
8. 外层循环递增,继续进行下一轮比较。
9. 循环结束后,输出排序完成的数组。
冒泡排序是一种简单但效率较低的排序算法。
其时间复杂度为O(n^2),其中n为数组的长度。
在最坏情况下,即数组逆序排列时,冒泡排序需要进行大约n*(n-1)/2次比较和交换操作。
在实际应用中,冒泡排序在数据量较大时效率较低,但是由于其实现简单,易于理解,所以在学习算法和理解排序原理时仍然具有一定的参考价值。
同时,冒泡排序也可以通过一些优化措施来提高效率,比如添加一个标志位flag来判断是否进行过交换操作,如果某一轮比较中没有进行任何交换,说明数组已经有序,可以直接退出循环,从而减少无效比较和交换的次数。
[转载]快速排序法(VB和VBA版、递归法版)先从数据序列中选一个元素,并将序列中所有比该元素小的元素都放到它的右边或左边,再对左右两边分别用同样的方法处之直到每一个待处理的序列的长度为1, 处理结束。
在当前无序区R[1..H]中任取一个数据元素作为比较的"基准"(不妨记为X),用此基准将当前无序区划分为左右两个较小的无序区:R[1..I-1]和R[I+1..H],且左边的无序子区中数据元素均小于等于基准元素,右边的无序子区中数据元素均大于等于基准元素,而基准X则位于最终排序的位置上,即R[1..I-1]≤X.Key≤R[I+1..H](1≤I≤H),当R[1..I-1]和R[I+1..H]均非空时,分别对它们进行上述的划分过程,直至所有无序子区中的数据元素均已排序为止快速排序的基本思想是基于分治策略的。
对于输入的子序列L[p..r],如果规模足够小则直接进行排序(比如用前述的冒泡、选择、插入排序均可),否则分三步处理:分解(Divide):将待排序列L[p..r]划分为两个非空子序列L[p..q]和L[q+1..r],使L[p..q]中任一元素的值不大于L[q+1..r]中任一元素的值。
具体可通过这样的途径实现:在序列L[p..r]中选择数据元素L[q],经比较和移动后,L[q]将处于L[p..r]中间的适当位置,使得数据元素L[q]的值小于L[q+1..r]中任一元素的值。
递归求解(Conquer):通过递归调用快速排序算法,分别对L[p..q]和L[q+1..r]进行排序。
合并(Merge):由于对分解出的两个子序列的排序是就地进行的,所以在L[p..q]和L[q+1..r]都排好序后不需要执行任何计算L[p..r]就已排好序,即自然合并。
对于基数基本是取最左边一位、最中间一位或最后一位,后面的代码小Y按最中间那位做为基数,进行递归排序。
另外:小Y是非计算机专业的,有些坏毛病总是改不过来,习惯于把数组的最小的下标设置为“1”。
递归和尾递归的运⾏流程解释递归和尾递归的运⾏流程解释递归定义递归(英语:recursion)在计算机科学中是指⼀种通过重复将问题分解为同类的⼦问题⽽解决问题的⽅法。
递归式⽅法可以被⽤于解决很多的计算机科学问题,因此它是计算机科学中⼗分重要的⼀个概念。
绝⼤多数编程语⾔⽀持函数的⾃调⽤,在这些语⾔中函数可以通过调⽤⾃⾝来进⾏递归。
计算理论可以证明递归的作⽤可以完全取代循环,因此有很多在函数编程语⾔(如Scheme)中⽤递归来取代循环的例⼦。
(摘⾃维基百科)尾递归定义在计算机学⾥,尾调⽤是指⼀个函数⾥的最后⼀个动作是返回⼀个函数的调⽤结果的情形,即最后⼀步新调⽤的返回值直接被当前函数的返回结果。
此时,该尾部调⽤位置被称为尾位置。
尾调⽤中有⼀种重要⽽特殊的情形叫做尾递归。
经过适当处理,尾递归形式的函数的运⾏效率可以被极⼤地优化。
尾调⽤原则上都可以通过简化函数调⽤栈的结构⽽获得性能优化(称为“尾调⽤消除”),但是优化尾调⽤是否⽅便可⾏取决于运⾏环境对此类优化的⽀持程度如何。
(摘⾃维基百科)前提知识递归我将它分为两个过程,⼀个我将它称为递归,另⼀个我将它称为回溯. 递归的函数的运⾏主要有这两个流程,递归的进⼊,回溯的退出,这两个过程的分界是以递归出⼝为分界的.递归的实现形式是使⽤栈,递归函数的进⼊(递归)类似与压栈,递归函数的退出(回溯)类似于出栈.递归样例和解释【编程题】幂运算三(递归函数)题⽬ID:1137【问题描述】求x^n。
【输⼊形式】⼀⾏2个数,第⼀个整数表⽰x,第⼆个⼤于等于零的整数表⽰n,⼆数之间⽤空格分隔。
【输出形式】⼀⾏⼀个整数,表⽰x的n次⽅【样例输⼊】2 3【样例输出】8【样例说明】2的3次⽅结果为8【评分标准】5组测试⽤例,每组2分,共计10分【测试⽤例】1)输⼊:2 3输出:82)输⼊:3 5输出:2433)输⼊:-17 4输出:835214)输⼊:22 0输出:15)输⼊:-1287 0输出:1//普通递归#include<stdio.h>long my_pow1(long x,int n){if(n==0) return 1; //递归出⼝return x*(my_pow1(x,--n)); //除了调⽤⾃⾝外还乘多了个x,即⼀般的递归}int main(){long x;int n;scanf("%ld%d",&x,&n);printf("%ld\n",my_pow1(x,n));return 0;}运⾏图解解释:普通的递归过程是在⼀个函数中,结果依靠⾃⾝的调⽤来得出,例如求幂运算,pow(2,3)代表求2的3次⽅,由于pow(2,3)未知,我们可以把它分解成2*pow(2,2),pow(2,2)也未知,⼜可分解成2*pow(2,1),以此类推,直到pow(2,0)可知(if中定义0时返回1),即pow(2,0)返回值是1.在这个递归过程中,pow函数的建⽴就是⼀个个压栈的过程我把它称为函数栈压栈压⼊所以函数后,直到最后⼀个,可以获得最后⼀个函数的返回值,由这个返回值可以依次推出栈内所有函数的返回值(回溯),即退栈,pow(2,0)返回1,推的pow(2,1)返回2*pow(2,0),即2*1=2,pow(2,2)返回2*pow(2,1),即2*2=4,直到退到栈内最后⼀个函数pow(2,3),可获得pow(2,3)的返回值为2*pow(2,2)即8;尾递归样例和解释【编程题】吃糖(尾递归函数)题⽬ID:1135【问题描述】⼩樱是个爱吃糖的⼥孩, 哥哥送了她n(1<=n<=30)颗糖,怎么吃?⼀天吃1颗;⼀天吃2颗。
程序算法描述流程图程序算法流程图算法的方法递推法递推是序列计算机中的一种常用算法。
它是按照一定的规律来计算序列中的每个项,通常是通过计算机前面的一些项来得出序列中的指定项的值。
其是把一个复杂的庞大的计算过程转化为简单过程的多次重复,该算法利用了计算机速度快和不知疲倦的机器特点。
递归法程序调用自身的编程技巧称为递归(recurion)。
一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的能力在于用有限的语句来定义对象的无限集合。
一般来说,递归需要有边界条件、递归前进段和递归返回段。
当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
注意:(1)递归就是在过程或函数里调用自身;(2)在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
穷举法穷举法,或称为暴力破解法,其基本思路是:对于要解决的问题,列举出它的所有可能的情况,逐个判断有哪些是符合问题所要求的条件,从而得到问题的解。
它也常用于对于密码的破译,即将密码进行逐个推算直到找出真正的密码为止。
例如一个已知是四位并且全部由数字组成的密码,其可能共有10000种组合,因此最多尝试10000次就能找到正确的密码。
理论上利用这种方法可以破解任何一种密码,问题只在于如何缩短试误时间。
因此有些人运用计算机来增加效率,有些人辅以字典来缩小密码组合的范围。
贪心算法贪心算法是一种对某些求最优解问题的更简单、更迅速的设计技术。
用贪心法设计算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,它省去了为找最优解要穷尽所有可能而必须耗费的大量时间,它采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解,虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪婪法不要回溯。