递归算法

递归算法

只愿长相守 提交于 2020-02-12 15:35:40
递归(recursion):程序调用自身的编程技巧。 递归满足2个条件: 1)有反复执行的过程(调用自身) 2)有跳出反复执行过程的条件(递归出口) 递归例子: (1)阶乘 n! = n * (n-1) * (n-2) * ...* 1(n>0) //阶乘 int recursive(int i) { int sum = 0; if (0 == i) return (1); else sum = i * recursive(i-1); return sum; } (2)河内塔问题 //河内塔 void hanoi(int n,int p1,int p2,int p3) { if(1==n) cout<<“盘子从”<<p1<<“移到”<<p3<<endl; else { hanoi(n-1,p1,p3,p2); cout<<“盘子从”<<p1<<“移到”<<p3<<endl; hanoi(n-1,p2,p1,p3); } } (3)全排列 从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。 如1,2,3三个元素的全排列为: 1,2,3 1,3,2 2,1,3 2,3,1 3,1,2 3,2,1 //全排列 inline void Swap(int &a,int &b) { int temp=a

2-路归并排序的递归写法

最后都变了- 提交于 2020-02-12 08:15:21
《算法笔记》中摘取 2-路归并排序的递归写法非常简单,只需要反复将当前区间[left, right]分为两半,对两个子区间[left, mid]与[mid +1, right]分别递归进行归并排序,然后将两个已经有序的合并为有序序列即可。 const int maxn = 100; //将数组A的[L1, R1]与[L2, R2]区间合并为有序区间(此处L2记为R1 + 1) void merge(int A[], int L1, int R1, int L2, int R2) { int i = L1, j = L2; //i指向A[L1], j指向A[L2] int temp[maxn], index = 0; //temp临时存放合并后的数组,index为其下标 while(i <= R1 && j <= R2) { if(A[i] <= A[j]) { //如果A[i] <= A[j] temp[index++] = A[i++]; //将A[i]加入序列temp } else { //如果A[i] > A[j] temp[index++] = A[j++];//将A[j]加入序列temp } } while(i <= R1) temp[index++] = A[i++]; //将[L1, R1]的剩余元素加入序列temp while(j <= R2) temp[index

递归算法之基础练习

拜拜、爱过 提交于 2020-02-11 23:54:40
递归的定义: 一个函数自己直接或间接调用自己。 我们只要把下面两个基本的问题搞明白就差不多理解了递归的含义。 ( 这里需要注意的是我们写递归的时候一定要有个递归出口、不然会导致栈溢出异常 ) /** * 递归的复习与巩固 * @author qiu * 定义:一个函数自己直接或间接调用自己。 */ public class Recursion { public static void main ( String [ ] args ) { //求阶乘 n!的问题可以看成n*(n-1)! int num = factorial ( 10 ) ; System . out . println ( num ) ; //求1+2+3....+n的和 int sum = factorial1 ( 5 ) ; System . out . println ( sum ) ; } public static int factorial ( int N ) { //递归函数 if ( N == 1 || N == 0 ) { //递归结束出口 return 1 ; } else if ( N < 0 ) { //递归结束出口 return - 1 ; } else { return N * factorial ( N - 1 ) ; } } private static int factorial1

关于递归的一些小练习

一笑奈何 提交于 2020-02-11 06:59:31
递归 什么是递归 在程序中, 所谓的递归, 就是函数自己直接或间接的调用自己. 直接调用自己 间接调用自己 就递归而言最重要的就是跳出结构. 因为跳出了才可以有结果. 所谓的递归就是化归思想 递归的调用, 写递归函数, 最终还是要转换为自己这个函数. 假如有一个函数 f, 如果它是递归函数的话, 那么也就是说 函数体内的问题还是转换为 f 的形式. 递归思想就是将一个问题转换为一个已解决的问题来实现 function f() { ... f( ... ) ... } 例子: 1, 2, 3, 4, 5, ..., 100 首先假定递归函数已经写好, 假设是 foo. 即 foo( 100 ) 就是求 1 到 100 的和 寻找递推关系. 就是 n 与 n-1, 或 n-2 之间的关系: foo( n ) == n + foo( n - 1 ) var res = foo( 100 ); var res = foo( 99 ) + 100; 将递推结构转换为 递归体 function foo( n ) { return n + foo( n - 1 ); } * 将 求 100 转换为 求 99 * 将 求 99 转换为 求 98 * ... * 将求 2 转换为 求 1 * 求 1 结果就是 1 * 即: foo( 1 ) 是 1 将临界条件加到递归体中 function foo(

C++算法程序整理——递归算法

♀尐吖头ヾ 提交于 2020-02-10 20:47:31
递归算法 递归,定义一个过程或函数时出现调用本过程或本函数的成分,称之为递归。 一般来说,能够用递归解决的问题应该满足以下三个条件: 需要解决的问题可以转化为一个或多个同构(或同样性质的)子问题来求解,而这些子问题的求解方法与原问题完全相同,只是在数量规模上不同。 递归调用的次数必须是有限的。 必须有结束递归的条件来终止递归。 什么情况下使用递归: 定义是递归的,如n!,Fibonacci数列等,求解这类问题可将其递归定义直接转换成对应的递归算法。 数据结构(如树,单链表等)是递归的。结构体中的指针指向了自身的类型,是一种递归的数据结构。对于这类递归结构,采用递归的方法编写算法既方便,又高效。 问题的求解方法是递归的, 如 Hanoi 问题的求解。 递归模型,递归模型是递归算法的抽象,它反映了一个递归问题的递归结构。以求解n!为例,其递归模型如下: fun(1) = 1 (1) fun(n) = n*fun(n-1) n > 1 (2) 递归模型一般由 递归出口 和 递归体 组成。 递归出口 给出了递归的终止条件, 递归体 给出了 fun(n) 的值与 fun(n-1) 的值之间的联系。 递归算法的执行过程, 一个正确的递归程序虽然每次调用的是相同的子程序,但它的参量、输入数据等均有变化。 在正常的情况下,随着调用的不断深入,必定会出现调用到某一层的函数时

day19_File丶递归

巧了我就是萌 提交于 2020-02-09 17:04:07
File类 概述 File类是文件和目录路径名的抽象表示形式。 java把电脑中的文件和文件夹(目录)封装为了一个File类,我们可以使用File类对文件和文件夹进行操作我们可以使用File类的方法,创建一个文件/文件夹或删除文件/文件夹或获取文件/文件夹或判断文件/文件夹是否存在或对文件夹进行遍历或获取文件的大小。File类是一个与系统无关的类,任何的操作系统都可以使用这个类中的方法 。 常用的静态变量 public static String pathSeparator 与系统有关的路径分隔符,为了方便,它被表示为一个字符串。 public static char pathSeparatorChar 与系统有关的路径分隔符。 public static String separator 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。 public static char separatorChar 与系统有关的默认名称分隔符。 代码演示 package demo01; import java.io.File; public class Demo01File { public static void main(String[] args) { /* 注意:工作中获取操作路径:路径不能写死了,一定要使用下面的方式获取 "C:"+File.separator+

二叉树的遍历

淺唱寂寞╮ 提交于 2020-02-09 07:50:28
二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的。对于二叉树,有前序、中序以及后序三种遍历方法。因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易理解而且代码很简洁。而对于树的遍历若采用非递归的方法,就要采用栈去模拟实现。在三种遍历中,前序和中序遍历的非递归算法都很容易实现,非递归后序遍历实现起来相对来说要难一点。 前序遍历 递归 void preOrder1(BinTree *root) //递归前序遍历 { if(root!=NULL) { cout<<root->data<<" "; preOrder1(root->lchild); preOrder1(root->rchild); } } 非递归 根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下: 对于任一结点P: 1)访问结点P,并将结点P入栈; 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P; 3)直到P为NULL并且栈为空,则遍历结束。 void preOrder2

非递归遍历二叉树

旧城冷巷雨未停 提交于 2020-02-08 23:06:54
#类名称:BinaryTreeNode #类说明:定义一个二叉树的结点 #类释义:分别有左孩子LeftChild,右孩子RightChild和数据data class BinaryTreeNode(object): def __init__(self): self.data='#' self.LeftChild=None self.RightChild=None class TreeState(object): def __init__(self,BinaryTreeNode,VisitedFlag): self.BinaryTreeNode = BinaryTreeNode self.VisitedFlag = VisitedFlag #类说明:定义一个二叉树 class BinaryTreeNonRecursive(BinaryTreeNode): #创建二叉树的函数 def CreateBinaryTree(self,Root): data=input('->') if data=='#': Root=None else: Root.data=data Root.LeftChild=BinaryTreeNode() self.CreateBinaryTree(Root.LeftChild) Root.RightChild=BinaryTreeNode() self

二分查找法的实现和应用汇总

醉酒当歌 提交于 2020-02-08 17:33:43
二分查找法的实现和应用汇总 关于二分查找法 二分查找法 主要是解决在“一堆数中找出指定的数 ”这类问题。 而想要应用二分查找法,这“一堆数”必须有一下特征: 存储在数组中 有序排列 所以如果是用 链表 存储的,就无法在其上应用 二分查找法 了。(曽在面试被问二分查找法可以什么数据结构上使用:数组?链表?) 至于是顺序递增排列还是递减排列,数组中是否存在相同的元素都不要紧。不过一般情况,我们还是希望并假设数组是递增排列,数组中的元素互不相同。 二分查找法的基本实现 二分查找法在算法家族大类中属于“ 分治法 ”,分治法基本都可以用 递归 来实现的,二分查找法的递归实现如下: int bsearch(int array[], int low, int high, int target){ if (low > high) return -1; int mid = (low + high)/2; if (array[mid]> target) return binarysearch(array, low, mid -1, target); if (array[mid]< target) return binarysearch(array, mid+1, high, target); //if (midValue == target) return mid;}

算法复习:递归

爷,独闯天下 提交于 2020-02-07 21:51:10
leedcode 10. 正则表达式匹配 递归解法,时间复杂度比较高,后面要尝试改成动规 bool end_or_not(string p) { for(int i=0;i<p.size();i+=2) { if(((p[i]>='a'&&p[i]<='z')||p[i]=='.')&&p[i+1]=='*') continue; return false; } return true; } bool check(string s, string p) { int donser[27]; memset(donser,0,sizeof(donser)); for(int i=0;i<p.size();i++) { if(p[i]=='.'||p[i]=='*') continue; if(donser[p[i]-'a']==0) { donser[p[i]-'a']=1; int lable=0; if(p[i+1]=='*') continue; for(int j=0;j<s.size();j++) { if(s[j]==p[i]) { lable=1; break; } } if(lable==0) return false; } } return true; } class Solution { public: bool isMatch(string s, string p)