递归算法

树的算法思想之递归

妖精的绣舞 提交于 2020-01-16 09:10:27
递归 解题关键: 找出递归关系 找出终止条件 确定返回值 例子 给定一个二叉树,判断它是否是高度平衡的二叉树 。 算法实现: int deep ( struct TreeNode * p ) { //确定出口 if ( p == NULL ) { return 0 ; } //递归关系 int left = 1 + deep ( p -> left ) ; int right = 1 + deep ( p -> right ) ; //确定返回值 return left > right ? left : right ; } bool isBalanced ( struct TreeNode * root ) { //确定出口 if ( root == NULL ) return true ; int ch = abs ( deep ( root -> left ) - deep ( root -> right ) ) ; //递归关系+递归返回值(根据题目具体情况分析) return ch < 2 && isBalanced ( root -> left ) && isBalanced ( root -> right ) ; } 给定一个二叉树,找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明: 叶子节点是指没有子节点的节点。 算法实现1: int

递归 VS 非递归 内涵

空扰寡人 提交于 2020-01-16 05:13:08
递归与非递归转换的基础知识是能够正确理解三种树的遍历方法:前序,中序和后序,第一篇就是关于这三种遍历方法的递归和非递归算法。 一、为什么要学习递归与非递归的转换的实现方法? 1)并不是每一门语言都支持递归的。 2)有助于理解递归的本质。 3)有助于理解栈,树等数据结构。 二、三种遍历树的递归和非递归算法 递 归与非递归的转换基于以下的原理:所有的递归程序都可以用树结构表示出来。需要说明的是,这个”原理”并没有经过严格的数学证明,只是我的一个猜 想,不过在至少在我遇到的例子中是适用的。学习过树结构的人都知道,有三种方法可以遍历树:前序,中序,后序。理解这三种遍历方式的递归和非递归的表达方 式是能够正确实现转换的关键之处,所以我们先来谈谈这个。需要说明的是,这里以特殊的二叉树来说明,不过大多数情况下二叉树已经够用,而且理解了二叉树的 遍历,其它的树遍历方式就不难了。 1)前序遍历 a)递归方式: void preorder_recursive(Bitree T) /* 先序遍历二叉树的递归算法 */ { if (T) { visit(T); /* 访问当前结点 */ preorder_recursive(T->lchild); /* 访问左子树 */ preorder_recursive(T->rchild); /* 访问右子树 */ } } b)非递归方式 void preorder

最长公共子序列(LCS)

て烟熏妆下的殇ゞ 提交于 2020-01-15 20:51:25
一,字串连续情况 LCS问题就是求两个字符串最长公共子串的问题。解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0。然后求出对角线最长的1序列,其对应的位置就是最长匹配子串的位置。 下面是字符串21232523311324和字符串312123223445的匹配矩阵,前者为X方向的,后者为Y方向的。不难找到,红色部分是最长的匹配子串。通过查找位置我们得到最长的匹配子串为:21232 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 1 0 0 1 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

博客作业04--树

僤鯓⒐⒋嵵緔 提交于 2020-01-15 14:58:26
1.学习总结 1.1树结构思维导图 1.2 树结构学习体会 学习树最痛苦的事情就是递归,最开始的先序,中序,后序的递归算法,看了好久才能大致的明白程序的思路,还有就是表达式树的建立,跟栈的中缀转后缀表达式有点类似,但是一用到递归就没那么好理解了,其实重点还是要多花时间去研究书上的代码,学习树的知识,如果对书本的内容不是很熟悉,很难对树有很好的理解,做起题目来也是非常累人的,因为根本不明白程序下一步要怎么走。 2.PTA实验作业 2.11题目: jmu-ds-表达式树 2.12设计思路(伪代码或流程图) void InitExpTree(BTree &T,string str) 建op栈,op.push('#') 初始化根节点栈:stacktree栈 while(表达式未结束) { if(str[i]==数字字符) 生成一个只有根节点的子树T。stacktree.push(T) if(str[i]==运算符) { while(str[i]<op栈顶运算符)栈顶优先级别高 { 创建一个树结点T,数据为op.top() stacktree弹出2个根节点T1,T2 T->lchild=T1;T->rchild=T2; stacktree.push(T); } if(str[i]>op栈顶元素运算符) op.push(str[i]) if(str[i]==op栈顶运算符) op.pop().

八大算法思想

拈花ヽ惹草 提交于 2020-01-15 09:28:39
八大算法思想分别是:枚举、递推、递归、分治、贪心、试探法、动态迭代和模拟算法思想。 1、比较“笨”的枚举算法思想 枚举最大的缺点是运算量比较大,解题效率不高。 如果题目的规模不是很大,在规定的时间与空间限制内能够求出解,那么最好是采用枚举法,而无须太在意是够还有更快的算法,这样可以使你有更多的时间去解答其他难题。 //枚举法解决“填写运算符”的问题 import java.util.Scanner; public class meijujisuan5ge5 { public static void main(String[] args) { // TODO Auto-generated method stub int j; int[] i=new int[5]; //用数组i来表示4个运算符 (5个数之间有四个符号,分别遍历出所有的情况) int sign;//累加运算时的符号 int count=0;//计数器,统计符合条件的方案 int num[]=new int[6];//保存操作数(输入值) float left,right; char[] oper={' ','+','-','*','/'}; System.out.println("请输入5个数,之间用空格隔开:"); Scanner in=new Scanner(System.in); for(j=1;j<=5;j++

帮助大家理解一下递归函数的返回值...

瘦欲@ 提交于 2020-01-15 09:28:07
如题: 递归函数往往可以简化我们的代码,尤其是对树的遍历和利用回溯算法写代码的时候,但是递归函数的返回值往往是困扰我们的。 总体来说,我们先要理解函数的调用过程,函数调用过程会用栈来保存函数的返回值和过程, 而递归函数就是调用自身函数的过程,所以也是用栈存储 ,这样就比较容易理解了。 下面一段代码可以帮助大家理解递归函数的返回值。 1 package test; 2 3 4 public class RecursionValueReturn { 5 6 /* 7 *目的: 8 * 递归返回值测试 9 */ 10 11 int recurse(int i) 12 { 13 if(i == 0) 14 { 15 return 0; 16 } 17 else 18 { 19 i--;//i--必须放在前面,由于函数的中间结果值用栈保存,不然i--无法执行,会使递归函数对系统的栈用光 20 recurse(i); 21 //i--; 22 } 23 24 System.out.print(" "+ i); 25 return i; 26 27 } 28 29 public static void main(String[] args) { 30 // TODO Auto-generated method stub 31 RecursionValueReturn result = new

递归和迭代的不同

倾然丶 夕夏残阳落幕 提交于 2020-01-15 08:12:31
递归的基本概念:程序调用自身的编程技巧称为递归,是函数自己调用自己. 一个函数在其定义中直接或间接调用自身的一种方法,它通常把一个大型的复杂的问题转化为一个与原问题相似的规模较小的问题来解决,可以极大的减少代码量.递归的能力在于用有限的语句来定义对象的无限集合. 使用递归要注意的有两点: 1)递归就是在过程或函数里面调用自身; 2)在使用递归时,必须有一个明确的递归结束条件,称为递归出口. 递归分为两个阶段: 1)递推:把复杂的问题的求解推到比原问题简单一些的问题的求解; 2)回归:当获得最简单的情况后,逐步返回,依次得到复杂的解. 利用递归可以解决很多问题:如背包问题,汉诺塔问题,...等. 斐波那契数列为:0,1,1,2,3,5... fib(0)=0; fib(1)=1; fib(n)=fib(n-1)+fib(n-2); [cpp] view plain copy int fib( int n) { if (0 == n) return 0; if (1 == n) return 1; if (n > 1) return fib(n-1)+fib(n-2); } 上面就是一个简单的递归调用了.由于递归引起一系列的函数调用,并且有可能会有一系列的重复计算,递归算法的执行效率相对较低. 迭代:利用变量的原值推算出变量的一个新值.如果递归是自己调用自己的话,迭代就是A不停的调用B

递归和迭代的差别

断了今生、忘了曾经 提交于 2020-01-15 08:12:05
递归的基本概念:程序调用自身的编程技巧称为递归,是函数自己调用自己. 一个函数在其定义中直接或间接调用自身的一种方法,它通常把一个大型的复杂的问题转化为一个与原问题类似的规模较小的问题来解决,能够极大的降低代码量.递归的能力在于用有限的语句来定义对象的无限集合. 使用递归要注意的有两点: 1)递归就是在过程或函数里面调用自身; 2)在使用递归时,必须有一个明白的递归结束条件,称为递归出口. 递归分为两个阶段: 1)递推:把复杂的问题的求解推到比原问题简单一些的问题的求解; 2)回归:当获得最简单的情况后,逐步返回,依次得到复杂的解. 利用递归能够解决非常多问题:如背包问题,汉诺塔问题,...等. 斐波那契数列为:0,1,1,2,3,5... fib(0)=0; fib(1)=1; fib(n)=fib(n-1)+fib(n-2); int fib(int n) { if(0 == n) return 0; if(1 == n) return 1; if(n > 1) return fib(n-1)+fib(n-2); } 上面就是一个简单的递归调用了.因为递归引起一系列的函数调用,而且有可能会有一系列的反复计算,递归算法的运行效率相对较低. 迭代:利用变量的原值推算出变量的一个新值.假设递归是自己调用自己的话,迭代就是A不停的调用B. 递归中一定有迭代,可是迭代中不一定有递归

递归和迭代的差别

一世执手 提交于 2020-01-15 08:11:31
递归的基本概念:程序调用自身的编程技巧称为递归,是函数自己调用自己. 一个函数在其定义中直接或间接调用自身的一种方法,它通常把一个大型的复杂的问题转化为一个与原问题类似的规模较小的问题来解决,能够极大的降低代码量.递归的能力在于用有限的语句来定义对象的无限集合. 使用递归要注意的有两点: 1)递归就是在过程或函数里面调用自身; 2)在使用递归时,必须有一个明白的递归结束条件,称为递归出口. 递归分为两个阶段: 1)递推:把复杂的问题的求解推到比原问题简单一些的问题的求解; 2)回归:当获得最简单的情况后,逐步返回,依次得到复杂的解. 利用递归能够解决非常多问题:如背包问题,汉诺塔问题,...等. 斐波那契数列为:0,1,1,2,3,5... fib(0)=0; fib(1)=1; fib(n)=fib(n-1)+fib(n-2); int fib(int n) { if(0 == n) return 0; if(1 == n) return 1; if(n > 1) return fib(n-1)+fib(n-2); } 上面就是一个简单的递归调用了.因为递归引起一系列的函数调用,而且有可能会有一系列的反复计算,递归算法的运行效率相对较低. 迭代:利用变量的原值推算出变量的一个新值.假设递归是自己调用自己的话,迭代就是A不停的调用B. 递归中一定有迭代,可是迭代中不一定有递归

0-1背包自顶向下非递归算法

三世轮回 提交于 2020-01-14 09:00:34
//0-1背包动态算法 //给出两点地杰斯特拉算法满足动态规划算法的需求 // A 到 b c d e f h 已知学生家的距离,求老师家到每个学生家的最短路径,好让王老师做出计划 // 写出0-1背包自顶向下的非递归动态规划算法 # include <iostream> # include <string> using namespace std ; int n ; int * input1 ( ) { cout << "请输入物品总数n:" << endl ; cin >> n ; int * w = new int [ n ] ; cout << "请输入个物品的重量:" << endl ; for ( int i = 0 ; i < n ; i ++ ) { cin >> w [ i ] ; } return w ; } int * input2 ( ) { int * v = new int [ n ] ; cout << "请输入各个物品的价值:" << endl ; for ( int i = 0 ; i < n ; i ++ ) cin >> v [ i ] ; return v ; } int min ( int a , int b ) { if ( a < b ) return a ; else return b ; } int max ( int a ,