递归调用

java基础篇笔记18

一曲冷凌霜 提交于 2019-11-27 07:14:17
java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作。 File类:文件和目录路径名的抽象表示形式。 java把电脑中的文件和文件夹(目录)封装为了一个File类,我们可以使用File类对文件和文件夹进行以下操作: 创建一个文件/文件夹 删除文件/文件夹 获取文件/文件夹 判断文件/文件夹是否存在 对文件夹进行遍历 获取文件的大小 File类是一个与系统无关的类,任何操作系统都可以使用这个类中的方法。 重点,记住三个单词: file:文件 ; directory:文件夹 ; path:路径 路径分隔符 Windows是分号; Linux系统是冒号: 名称分隔符 Windows是反斜杠\ Linux系统是斜杠/ 对于操作路径,不能写死,所以可以使用separator (分隔符) 例如:C:\develop\a\a.txt 应写作:“C:”+File.separator+“develop”+File.separator+“a”+File.separator+“a.txt” 绝对路径:从盘符开始的路径,这是一个完整的路径。 c:\a.txt 相对路径:相对于项目目录的路径,这是一个便捷的路径,开发中经常使用。 c:\demo\b.txt 简化为->b.txt 相对指的是相对于当前项目的根目录 如果使用当前项目的根目录,路径可以简化书写 注意

解决Python递归栈溢出的问题

梦想的初衷 提交于 2019-11-27 02:23:24
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。 举个例子,我们来计算阶乘 n! = 1 x 2 x 3 x ... x n ,用函数 fact(n) 表示,可以看出: fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n 所以, fact(n) 可以表示为 n x fact(n-1) ,只有n=1时需要特殊处理。 于是, fact(n) 用递归的方式写出来就是: def fact(n): if n==1: return 1 return n * fact(n - 1) 上面就是一个递归函数。可以试试: >>> fact(1) 1 >>> fact(5) 120 >>> fact(100) 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000L 如果我们计算 fact(5) ,可以根据函数定义看到计算过程如下: ===> fact(5) ===> 5 * fact(4) ===> 5 * (4 *

递归与迭代

寵の児 提交于 2019-11-27 02:05:54
递归与迭代都是基于控制结构:迭代用重复结构,而递归用选择结构。递归与迭代都涉及重复:迭代显式使用重复结构,而递归通过重复函数调用实现重复。递归与迭代都涉及终止测试:迭代在循环条件失败时终止,递归在遇到基本情况时终止。使用计数器控制重复的迭代和递归都逐渐到达终止点:迭代一直修改计数器,直到计数器值使循环条件失败;递归不断产生最初问题的简化副本,直到达到基本情况。迭代和递归过程都可以无限进行:如果循环条件测试永远不变成false,则迭代发生无限循环;如果递归永远无法回推到基本情况,则发生无穷递归。 递归有许多缺点,它重复调用机制,因此重复函数调用的开销很大,将占用很长的处理器时间和大量的内存空间。每次递归调用都要生成函数的另一个副本(实际上只是函数变量的另一个副本).从而消耗大量内存空间。迭代通常发生在函数内,因此没有重复调用函数和多余内存赋值的开销。那么,为什么选择递归呢? 来源: http://www.cnblogs.com/slave2/archive/2009/03/25/1421018.html

递归与迭代

只愿长相守 提交于 2019-11-27 02:05:35
( 递推算法的首要问题是得到相邻的数据项间的关系(即递推关系)。递推算法避开了求通项公项的麻烦,把一个复杂的问题的求解,分解成了连续的若干步简单运算。一般说来,可以将递推算法看成是一种特殊的迭代算法。) 递归(调用本身)与迭代(新值换旧值)都是基于控制结构:迭代用重复结构,而递归用选择结构。递归与迭代都涉及重复:迭代显式使用重复结构,而递归通过重复函数调用实现重复。递归与迭代都涉及终止测试:迭代在循环条件失败时终止,递归在遇到基本情况时终止。使用计数器控制重复的迭代和递归都逐渐到达终止点:迭代一直修改计数器,直到计数器值使循环条件失败;递归不断产生最初问题的简化副本,直到达到基本情况。迭代和递归过程都可以无限进行:如果循环条件测试永远不变成false,则迭代发生无限循环;如果递归永远无法回推到基本情况,则发生无穷递归。 递归有许多缺点,它重复调用机制,因此重复函数调用的开销很大,将占用很长的处理器时间和大量的内存空间。每次递归调用都要生成函数的另一个副本(实际上只是函数变量的另一个副本).从而消耗大量内存空间。迭代通常发生在函数内,因此没有重复调用函数和多余内存赋值的开销。那么,为什么选择递归呢? --------------------------------------------------------------------------- 摘要:在算法的分析与设计中

递归与迭代

别说谁变了你拦得住时间么 提交于 2019-11-27 02:05:12
  对于递归与迭代的关系,也许很多人都不是很清晰,其实本质上递归与迭代时间复杂度方面是等价的(在不考虑函数调用开销和函数调用产生的堆栈开销),而递归主要是每递归一次,都会在栈中分配函数的空间,造成空间消耗过大,而且是与递归的深度成正比。从实际上说,所有的迭代可以转换为递归,但递归不一定可以转换为迭代。以下为引用: < 作者: Enoch Wang 引用自: http://chinawangquan.spaces.live.com > 所谓递归,简而言之就是应用程序自身调用自身,以实现层次数据结构的查询和访问。 递归的使用可以使代码更简洁清晰,可读性更好(对于初学者到不见得),但由于递归需要系统堆栈,所以空间消耗要比非递归代码要大很多,而且,如果递归深度太大,可能系统资源会不够用。 往往有这样的观点:能不用递归就不用递归,递归都可以用迭代来代替。 诚然,在理论上,递归和迭代在时间复杂度方面是等价的(在不考虑函数调用开销和函数调用产生的堆栈开销),但实际上递归确实效率比迭代低,既然这样,递归没有任何优势,那么是不是就,没有使用递归的必要了,那递归的存在有何意义呢? 万物的存在是需要时间的检验的,递归没有被历史所埋没,即有存在的理由。从理论上说,所有的递归函数都可以转换为迭代函数,反之亦然,然而代价通常都是比较高的。但从算法结构来说,递归声明的结构并不总能够转换为迭代结构

递归与迭代

自闭症网瘾萝莉.ら 提交于 2019-11-27 02:04:57
关于c语言部分函数的一些总结和注意事项: 递归是一种强有力的技巧,但是和其他技巧一样,它也可能被误用。这里就有一个例子。阶乘的定义往往就是以递归的形式描述的。factorial(n)=1,n<=0; factorial(n)=n*factorial(n-1),n>0; 这个定义同时具备了递归所需要的两个特性:1、存在限制条件,当符合这个条件时递归便不再继续;2、每次递归调用之后越来越接近这个限制条件。用这种方式定义阶乘往往引导人们使用递归来实现阶乘函数。程序如下所示: 1 //用递归方法计算n的阶乘 2 3 long factorial(int n) 4 5 { 6 7 if(n<=0) 8 9 return 1;10 11 else12 13 return n*factorial(n-1);14 15 } 但它不是递归的良好用法。为什么呢?因为递归函数调用将涉及一些运行时开销——参数必须压到堆栈中,为局部变量分配内存空间(所有递归均如此,并非特指这个例子),寄存器的值必须保存等。当递归函数的每次调用返回时,上述这些操作必须还原,恢复成原来的样子。所以,基于这些开销,对于这个程序而言,它并没有简化问题的解决方案。下面这个函数是尾部递归的一个例子,由于函数在递归调用返回后不再执行任何任务,所以尾部递归可以很方便的转换成一个简单循环,完成相同的任务 ,程序效率更为有效。 1 /

递归、尾递归与迭代

橙三吉。 提交于 2019-11-27 02:04:39
很久以前写过一篇《递归与迭代》,写得不是很好。可能是我自己也没把思路理清楚,现在就有了个重新整理思路炒冷饭的机会,也算是一个新的开始吧。 首先解释一个术语叫“尾调用”。直接从wiki的“ 尾调用 ”条目抄:尾调用是指一个函数里的最后一个动作是一个函数调用的情形:即这个调用的返回值直接被当前函数返回的情形。这种情形下称该调用位置为尾位置。若这个函数在尾位置调用本身(或是一个尾调用本身的其他函数等等),则称这种情况为尾递归,是递归的一种特殊情形。 比如,下面这个是尾调用: return f(); 而这个不是: return 1 + f(); 关于尾调用,有个重要的优化叫做尾调用消除。经过尾调用消除优化后的程序在执行尾调用时不会导致调用栈的增长。其实,这个优化可能不算是优化。因为在某些计算模型中,尾调用天然不会导致调用栈的增长。在EOPL提到过一个原理: 导致调用栈增长的,是对参数的计算,而不是函数调用。 由于尾调用不会导致调用栈的增长,所以尾调用事实上不像函数调用,而更接近GOTO。尾递归则等同于迭代,只是写法上的不同罢了。 下面以计算幂为例,分别用递归、尾递归和迭代三种方法实现程序。其中尾递归方法是递归方法的改进,而迭代方法纯粹是从尾递归方法翻译而来。 问题 已知数(整数,或浮点数,这里假设是整数)\(b\) 和非负整数\(n\) ,求\(b\)的\(n\)次幂\(b^n\)。

递归再一次让哥震惊了

怎甘沉沦 提交于 2019-11-26 23:57:18
递归再一次让哥震惊了 先说那两个让哥震惊的递归问题: 1:用递归实现单链表的倒序输出 2:从二叉查找树中删除节点,并保证还是二叉查找树 同学们可以开始思考这两个问题了,当然你可能N年前就遇到过这两个问题,那么不妨看看,看你是否真的理解了递归。实现这两个问题的代码当然很简单,就在下面。 百度百科中递归的名片:递归做为一种算法在程序设计语言中广泛应用.是指函数/过程/子程序在运行过程中直接或间接调用自身而产生的重入现象.递归是计算机科学的一个重要概念,递归的方法是程序设计中有效的方法,采用递归编写程序能使程序变得简洁和清晰。 刚开始学习的递归的时候,觉得他好强大,实现某些功能不用递归可能要几十行代码,用递归可能几行就搞定了,而且代码清晰简洁。一直以为递归也就是自己调用自己,有一个出口条件,让他停止递归,退出函数,其实的特点并非就这些。 递归还有一个非常重要的特点: 先进后出 ,跟栈类似,先递进去的后递出来。由于递归一直在自己调用自己,有时候我们很难清楚的看出,他的返回值到底是哪个,只要你理解了先进后出这个特点,你就会明白,第一次调用时,作为返回值的那个变量的值就是递归函数的返回值。先进后出吗,他是第一个进来,也就是最后出去的那个,当然就是递归的返回值啦。 第一个让哥震惊的问题:用递归实现单链表的倒序输出。 我前段时间写过一篇博客《 四种方式实现--从尾到头输出链表 》

递归

落花浮王杯 提交于 2019-11-26 22:20:54
递归:函数中调用函数自己(递归一定要有结束条件,否则会不断调用自己,陷入死循环) var i=0; function f1(){ i++; if(i<6){ f1(); }; console.log("从前有座山,山里有座庙,庙里有个老和尚,天天给小和尚讲故事:从前。。。"); } 来源: https://www.cnblogs.com/huihuihero/p/11333860.html

并发数据结构 : .NET Framework 中提供的读写锁

て烟熏妆下的殇ゞ 提交于 2019-11-26 21:43:18
在多线程编程时,开发人员经常会遭遇多个线程读写某个资源的情况。这就需要进行线程同步来保证线程安全。一般情况下,我们的同步措施是使用锁机制。但是,假如线程只对资源进行读取操作,那么根本不需要使用锁;反之,假如线程只对资源进行写入操作,则应当使用互斥锁(比如使用 Monitor 类等)。还有一种情况,就是存在多个线程对资源进行读取操作,同时每次只有一个线程对资源进行独占写入操作。这正是本文主题--读写锁的用武之地。 ReaderWriterLock 类 .NET Framework BCL 在 1.1 版本时,给我们提供了一个 ReaderWriterLock 类来面对此种情景。但是很遗憾,Microsoft 官方不推荐使用该类。Jeffrey Richter 也在他的《CLR via C#》一书中对它进行了严厉的批判。下面是该类不受欢迎的主要原因: 性能。这个类实在是太慢了。比如它的 AcquireReaderLock 方法比 Monitor 类的 Enter 方法要慢 5 倍左右,而等待争夺写锁甚至比 Monitor 类慢 6 倍。 策略。假如某个线程完成写入操作后,同时面临读线程和写线程等待处理。ReaderWriterLock 会优先释放读线程,而让写线程继续等待。但我们使用读写锁是因为存在大量的读线程和非常少的写线程,这样写线程很可能必须长时间地等待,造成写线程饥饿