递归调用

算法分析之递归与分治策略

二次信任 提交于 2019-11-30 20:40:45
递归与分治策略 直接或间接地调用自身的算法称为递归算法。用函数自身给出定义的函数称为递归函数。 在计算机算法设计与分析中,使用递归技术往往使函数的定义和算法的描述简洁且易于理解。 例1 阶乘函数 可递归地定义为: 其中: n=0 时,n!=1为边界条件 n>0 时,n!=n(n-1)!为递归方程 边界条件与递归方程是递归函数的二个要素,递归函数只有具备了这两个要素,才能在有限次计算后得出结果。 例2 Fibonacci数列 无穷数列1,1,2,3,5,8,13,21,34,55,…,被称为Fibonacci数列。它可以递归地定义为: 第n个Fibonacci数可递归地计算如下: int fibonacci(int n){ if (n <= 1) return 1; return fibonacci(n-1)+fibonacci(n-2); } 递归需要有边界条件、递归前进段和递归返回段。 当边界条件不满足时,递归前进; 当边界条件满足时,递归返回。 注意:在使用递增归策略时,必须有一个明确的递归结束条件,称为递归出口,否则将无限进行下去(死锁)。 递归的缺点: 递归算法解题的运行效率较低。 在递归调用过程中,系统为每一层的返回点、局部变量等开辟了堆栈来存储。递归次数过多容易造成堆栈溢出等。 例3逆序输出一个正数中的每一位数 例如,对于数12345,依次输出5 4 3 2 1 分析:

非递归的扩展欧几里得算法

一个人想着一个人 提交于 2019-11-30 20:20:03
$\DeclareMathOperator{\extgcd}{extgcd}$ 作者按:写这篇随笔是为了解释 tourist 的逆元模板 template <typename T> T inverse(T a, T m) { T u = 0, v = 1; while (a != 0) { T t = m / a; m -= t * a; swap(a, m); u -= t * v; swap(u, v); } assert(m == 1); return u; // 注意:u 可能为负数 } 一般的扩展欧几里德算法是求 $x, y$ 使得 $ax + by = \gcd(a,b)$ 。若 $a$ 和 $m$ 互素,扩展欧几里得算法可以用来求 $a$ 在模 $m$ 下的逆元,常见的实现如下 int extgcd(int a, int b, int& x, int& y) { int d = a; if (b != 0) { d = extgcd(b, a % b, y, x); y -= (a / b) * x; } else { x = 1; y = 0; } return d; } int mod_inverse(int a, int m) { int x, int y; extgcd(a, m, x, y); return (m + x % m) % m; } 求 $a$

用Java实现二叉查找树

回眸只為那壹抹淺笑 提交于 2019-11-30 19:46:13
二叉查找树的实现 1. 原理    二叉查找树,又称为二叉排序树、二叉搜索树。对于树中每一个节点X,它的左子树中所有项的值小于X中的项,而它的右子树中所有项的值大于X中的项。二叉查找树的平均深度为O(log N),搜索元素的时间复杂度也是O(log N)。是两种库集合类TreeSet、TreeMap实现的基础。 2. public API void makeEmpty( ) --> 置空boolean isEmpty( ) --> 判空AnyType findMin( ) --> 寻找最小值AnyType findMax( ) --> 寻找最大值boolean contains( x ) --> 是否存在元素xvoid insert( x ) --> 插入元素xvoid remove( x ) --> 删除元素xvoid printTree( ) --> 遍历二叉树 3. 核心思想图解:递归 !寻找最小值 此处用递归实现: !寻找最大值 此处用非递归实现,也可以用递归实现: !是否存在元素x 从root开始往下找,找到含有项X的节点,则此操作返回true,没有找到则返回false。 !插入元素x 从root开始往下找到合适的插入位置,然后插入。 !删除元素x 从root开始往下找到元素x,找到则删除,并且处理好后续工作。 4. BinarySearchTree代码实现 类中

Python递归函数

僤鯓⒐⒋嵵緔 提交于 2019-11-30 19:31:31
Python递归函数   本篇主要介绍Python中函数的递归,还是从三个方面了解:什么是递归;递归有什么好处;递归的具体用法是什么样的; 一、什么是递归?   在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。记住哦->在函数内部调用其他函数不是函数的嵌套,而在函数内部定义子函数才是函数的嵌套。 递归的特性:   1、递归函数必须有一个明确的结束条件。   2、每进入更深一层的递归时,问题规模相对于上一次递归都应减少   3、相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入)。   4、递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)   先看一个例子,一个关于实现叠加的两种方法的例子: import sys #通过循环来实现叠加 def sum1(n): ''' 1 to n,The sum function ''' sum = 0 for i in range(1,n + 1): sum += i return sum #通过函数的递归来实现叠加 def sum2(n): ''' 1 to n,The sum

python--递归函数讲解

核能气质少年 提交于 2019-11-30 16:59:15
递归算法是一种直接或间接调用自身算法的过程。 递归算法解决问题的特点: (1)递归就是在过程或函数里调用自身 (2)在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。 (3)递归算法解题通常显得很简洁,但递归算法解题的运行效率较低,所以一般不提倡用递归算法设计程序。 (4)在递归调用的过程中系统为每一层的返回点、局部量等开辟了栈来存储,递归次数过多容易造成栈溢出等。 2、递归的要求 递归算法所体现的“重复”一般有三个要求: (1)每次调用在规模上都有所缩小(通常是减半) (2)是相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出作为后一次的输入) (3)在问题的规模极小时必须用直接给出解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模位达到直接解答的大小为条件)无条件递归调用将会成为死循环而不能正常结束。 实例:写函数,利用递归获取斐波那契数列中的第10个数,并将该值返回给调用者。 1 def foo(depth, a1, a2): 2 if depth == 10: 3 return a1 4 a3 = a1 + a2 5 r = foo(depth + 1, a2, a3) 6 return r 7 8 ret = foo(1, 0, 1) 9 print(ret) View Code 来源: https://www.cnblogs

算法图解学习笔记之算法

浪子不回头ぞ 提交于 2019-11-30 16:08:03
一、二分查找 二分查找的输入是一个有序的元素列表。如果元素在列表中,返回其位置,否则返回null 二分查找每次都将列表分成两半,分别与查询元素对比。舍弃其中一半。然后再另一半中查找元素。 每次都可以排除一半的元素。所以其效率为O(logn以2为底) 二分查找查询的速度非常快,但是要求也比较严格,需要有序的列表。如果是无序的列表,就不能每次排查一半了。 二、递归 递归应该不算算法的一种,但是还是稍微提一下 递归其实就是循环调用某个函数,直到满足条件才退出。 递归中很重要的是基线条件和递归条件 基线条件是退出递归的条件,如果没有基线条件,那么递归不会停止。陷入无限的循环中。 递归条件是满足这些条件才循环调用函数。 两者缺一不可 三、快速排序(排序算法的一种,简称快排) 快排经常会和递归一起使用 其基线条件为,数组为空或者只包含一个元素。因为为空和只有一个元素就不需要排序了,直接返回。 递归条件为,从数组中取出一个元素,将其他元素分成两部分,一部分大于该元素,一部分小于该元素(等于可以包含再大于或者小于之中,都可以),然后递归调用大于该元素的数组和小于该元素的数组。返回大于元素的数组(递归调用结束后有序)+元素+小于元素的数组(递归调用结束后有序)。 快排的最好情况效率是O(n*logn),最坏情况是O(n*n) 假设传入的是一个有序的数组 我们选择的元素是数组第一个元素。

python之迭代器 生成器 枚举 常用内置函数 递归

蓝咒 提交于 2019-11-30 15:11:36
迭代器 迭代器对象:有__next__()方法的对象是迭代器对象,迭代器对象依赖__next__()方法进行依次取值 with open('text.txt','rb',) as f: res = f.__next__() # 第一行内容 print(res) res = f.__next__() # 第二行内容 print(res) 生成器 在 Python 中,使用了 yield 的函数被称为生成器(generator)。 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。 调用一个生成器函数,返回的是一个迭代器对象。 以下实例使用 yield 实现斐波那契数列: import sys def fibonacci(n): # 生成器函数 - 斐波那契 a, b, counter = 0, 1, 0 while True: if (counter > n): return yield a a, b = b, a + b counter += 1 f = fibonacci(10) # f 是一个迭代器,由生成器返回生成 while True: try:

递归算法应用

你离开我真会死。 提交于 2019-11-30 14:45:07
一、递归的定义 递归就是程序在运行的过程中调用自己(用自己定义自己) 递归的三要素: 边界条件 递归前进段 递归返回段 递归和栈     递归和栈有这紧密的联系,大多数编译器都是使用栈来实现递归的,当调用方法时,编译器会把这个方法的所有参数和返回地址都压入栈中,然后把控制转移给这个方法。当方法返回时,这些值退栈。参数消失了,并且控制权重新回到返回地址处。     调用一个方法时,所进行的步骤:     1)当一个方法被调用时,它的参数和返回地址压入栈中     2)这个方法可以通过获取栈顶元素访问参数     3)当这个方法返回时,它查看栈已获取返回地址,然后这个地址和所有参数退栈,并且销毁   下图是求阶乘的图示,帮助理解:    二、求整数n的阶乘  1 /** 2 * 求整数n的阶乘 3 * 4 * @param n 整数n 5 * @return 6 */ 7 public static int factorial(int n) { 8 if (n < 0) { 9 return -1;//返回-1证明参数有问题 10 } 11 if (n == 1 || n == 0) { 12 return 1; 13 } else { 14 return n * factorial(n - 1); 15 } 16 } 三、在有序数组中查找目标值(二分法) 1 /** 2 *

六.递归函数

浪尽此生 提交于 2019-11-30 13:52:29
楔子 在讲今天的内容之前,我们先来讲一个故事,讲的什么呢?从前有座山,山里有座庙,庙里有个老和尚讲故事,讲的什么呢?从前有座山,山里有座庙,庙里有个老和尚讲故事,讲的什么呢?从前有座山,山里有座庙,庙里有个老和尚讲故事,讲的什么呢?从前有座山,山里有座庙,庙里有个老和尚讲故事,讲的什么呢......这个故事你们不喊停我能讲一天!我们说,生活中的例子也能被写成程序,刚刚这个故事,让你们写,你们怎么写呀? while True: story = " 从前有个山,山里有座庙,庙里老和尚讲故事, 讲的什么呢? " print(story) 你肯定是要这么写的,但是,现在我们已经学了函数了,什么东西都要放到函数里去调用、执行。于是你肯定会说,我就这么写: def story(): s = """ 从前有个山,山里有座庙,庙里老和尚讲故事, 讲的什么呢? """ print(s) while True: story() 但是大家来看看,我是怎么写的! def story(): s = """ 从前有个山,山里有座庙,庙里老和尚讲故事, 讲的什么呢? """ print(s) story() story() 先不管函数最后的报错,除了报错之外,我们能看的出来,这一段代码和上面的代码执行效果是一样的。 返回顶部 初识递归 递归的定义—— 在一个函数里再调用这个函数本身

递归函数的使用

房东的猫 提交于 2019-11-30 13:35:53
一,概念 直接或间接地调用自身的算法称为 递归算法 。 用函数自身给出定义的函数称为 递归函数 。 二,实例 实例1 : 阶乘函数 。 通过分析可知,要求一个数的阶乘,只要知道它前一位数的阶乘便可求出。 即: n!=n*(n-1)! 而要求前一位数的阶乘,只要知道它前前一位数的阶乘即可,即 :(n-1)!=(n-1)*(n-2)!, 因为每次 计算的方式都相同,所以考虑用递归的方式求解。 递归关系:f(n)=n*f(n-1) 递归结束条件:n=1 (因为我们很容易知道1阶乘是1,因此求解其他数的阶乘时,可从1的阶乘开始求起) 代码实现 : 1 import java.util.*; 2 public class HW8 { 3 public static void main(String[] args) { 4 Scanner in=new Scanner(System.in); 5 System.out.println("请输入所要求的数值:"); 6 int n=in.nextInt(); //输入所要遍历的数 7 int number=funtion(n); 8 System.out.println(n+"的阶乘为:"+number); 9 10 } 11 12 /** 13 * 求第n个数的阶乘!!! 14 * @param n 所要求的数的值 15 * @return