递归

Java API —— 递归

笑着哭i 提交于 2020-01-28 05:02:18
1、方法定义中调用方法本身的现象 2、递归注意实现 1) 要有出口,否则就是死递归 2) 次数不能太多,否则就内存溢出 3) 构造方法不能递归使用 3、递归解决问题的思想和图解: 例子1:求5的阶乘 package diguidemos; /** * Created by gao on 15-12-27. */ /* * 需求:请用代码实现求5的阶乘。 * * 有几种方案实现呢? * A:循环实现 * B:递归实现 * a:做递归要写一个方法 * b:出口条件 * c:规律 */ public class DiGuiDemo01 { public static void main(String[] args) { int jc = 1; for (int i = 2; i <= 5; i++) { jc *= i; } System.out.println("5的阶乘是:" + jc); //5的阶乘是:120 System.out.println("5的阶乘是:"+jieCheng(5)); } /* * 做递归要写一个方法: * 返回值类型:int * 参数列表:int n * 出口条件: * if(n == 1) {return 1;} * 规律: * if(n != 1) {return n*方法名(n-1);} */ public static int jieCheng

全排列

旧街凉风 提交于 2020-01-28 04:41:25
全排列 全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。 1、设计一个递归算法生成n个元素{r1,r2,…,rn}的全排列(所有元素按不同顺序所有的组合)。 以{1, 2, 3, 4, 5}为例说明全排列的递归算法。 先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头和5的全排列和以5开头和4的全排列。 再看后三个数3, 4, 5。它们的全排列为3 4 5、3 5 4、4 3 5、4 5 3、5 3 4、5 4 3 六组数。即以3开头和45的全排列的、以4开头和35的全排列和以5开头和34的全排列。 //全排列 (递归) # include <iostream> # include <algorithm> using namespace std ; int a [ 100 ] ; int cnt = 0 ; void swap ( int & x , int & y ) { //交换两个数的值 int t = x ; x = y ; y = t ; } void Perm ( int j , int n ) { //从第j个元素开始,共n个元素 if ( j == n ) { //排完了,打印输出 cnt ++ ; for ( int i = 0 ; i < n ; i ++ ) cout << a [ i ] ; cout <<

递归文件遍历

本秂侑毒 提交于 2020-01-28 03:38:29
递归的最大深度是1000层,从1开始到998层就会被停止报错 递归函数, 自己调用自己 count = 1 def func(): global count print("我想找个女朋友", count) count = count + 1 func() func() 上面的是递归的一个小例子,话不说多上代码 遍历文件夹, 打印出所有的文件和普通文件的文件名 import os def func(filepath, n): # d:/sylar/ # 1,打开这个文件夹 files = os.listdir(filepath) # 2. 拿到每一个文件名 for file in files: # 文件名 # 3. 获取到路径 f_d = os.path.join(filepath, file) # d:/sylar/文件名/ # 4. 判断是否是文件夹 if os.path.isdir(f_d): # 5. 如果是文件夹. 继续再来一遍 print("\t"*n, file,":") # 打印文件名 func(f_d, n + 1) else: # 不是文件夹. 普通文件 print("\t"*n, file) func("d:/sylar",0) 来源: https://www.cnblogs.com/fangyanwangshijie/p/9505848.html

快排算法的非递归实现

怎甘沉沦 提交于 2020-01-28 02:26:10
我的Partition(),功能是以传入的finish序号的数的数值为分界线,把数组分成两部分,前半的数值都比他小,其余的都比那个值大,并返回分界的序号。这个过程中就操作数组换位,具体见算法注释。 而sort函数的工作就是反复的利用Partition函数查找那个中间值,在这个过程中就对数组进行操作,将其分成两段。把一个大的数列改为一个个小的,甚至长度为一的序列,当达到这个条件时,实际上已经排好序了。 这一点上和递归函数没区别,因为算法一样。建议按序看我的注释,并且自己举个数列的例子来操作。可以先看Partition()的,因为两个函数是独立的。 可以,我就写写算法了。因为这个代码是算法代码而其年久失修,你自己人工序列试试就知道了。关键在后面的交换顺序并找到分界点的地方 Sort() { stack s;//构造栈 start =arr;//arr为要排序的序列 finish = m_arr + m_len - 1; pivot = Partition(start, finish);//找到一个位置,使其前面的比他小,后面的比他大 s.push(pivot+1); // 后半段首尾存储仅存储序列号 s.push(finish); s.push(start); // 前半段首尾存储仅存储序列号 s.push(pivot-1); while (!s.empty())/

递归高级应用(汉诺塔)

拜拜、爱过 提交于 2020-01-28 02:19:06
一:汉诺塔问题 所有的盘子刚开始都是放在塔座A上,要求将所有的盘子从塔座A移动到塔座C上,每次只能移动一个盘子,任何盘子不能放在比自己小的盘子上. 二:移动子树 把上层的全部看成一个整体–子树 , 每次移动后子树都在减小,最后子树剩下一个,再放到C座即可 三:递归的解决 public class HanNuoTa { public static void main ( String [ ] args ) { moveTower ( 3 , 'A' , 'B' , 'C' ) ; } /* *移动盘子 * 参数; * 1.num: 移动的盘子数量 * 2.a: 塔座A * 3.b: 塔座B * 4.c: 塔座C */ public static void moveTower ( int num , char a , char b , char c ) { if ( num == 1 ) { //只有一个盘子的时候 System . out . println ( "盘子1 从" + a + "移动到" + c ) ; } else { //大于一个盘子的时候 //1.意思是把上面 num-1 个盘子 从 a 移动 到 b(此时 c 作为过度塔) moveTower ( num - 1 , a , c , b ) ; //2.移动最底下那个盘子到c System . out .

二叉树遍历 递归非递归

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

(N叉树 DFS 递归 BFS) leetcode 559. Maximum Depth of N-ary Tree

╄→尐↘猪︶ㄣ 提交于 2020-01-27 20:42:30
Given a n-ary tree, find its maximum depth. The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. For example, given a 3-ary tree: We should return its max depth, which is 3. Note: The depth of the tree is at most 1000 . The total number of nodes is at most 5000 . -------------------------------------------------------------------------------------------------------------------------------------- 这个和求二叉树的最大深度类似,只要掌握了二叉树的最大深度的解法以及理解了N叉树的原理,解决这个题就会很简单了。 递归/DFS: C++代码: /* // Definition for a Node. class Node { public: int val; vector

SICP学习笔记(1.2.1 ~ 1.2.2)

 ̄綄美尐妖づ 提交于 2020-01-27 20:12:42
SICP学习笔记(1.2.1 ~ 1.2.2) 周银辉 1, 递归过程 和 递归计算过程 在学习SICP前我还没注意过有这样的一个区分,因为我们始终停留在语法表面上的“递归过程(recursive procedure)”,而没有去理解其实质是否是“递归计算过程(recursive process)”。 递归过程:从语法书写层面上而言的,在过程的定义中,其直接或间接地引用该过程本身。 比如 F{F}或者 F{G{F}} 递归计算过程:从实际运算层面上而言的,一个在语法上按照递归过程书写的函数其在运算时可能是按照递归的方式也可能是按照迭代的方式进行的。这取决于解释器或编译器本身是否有对“递归”进行优化,比如Scheme解释器是“严格尾递归”的, 而C#之类的,即便在语法形式上是"尾递归"的,但其仍然不能被编译成迭代计算过程,当然,你可以使用for,while等. 要检测出一个递归过程在计算时到底是按照递归方式还是按照迭代方式进行的,非常容易,只要将其进行深度递归或无限次递归,如果Stack Overflow了,那么是按照递归方式计算的,仅仅是一个死循环似的不停计算但没有栈溢出,那么是按照迭代方式计算的。一般而言函数式编程语言(Scheme,Haskell等), 会按照迭代方式进行计算;命令式编程语言(C++,C#,Java等)会按照递归方式进行计算。 2,迭代计算过程 和 递归计算过程

21.合并有序链表 - (链表)

非 Y 不嫁゛ 提交于 2020-01-27 18:59:35
21.合并有序链表 - (链表) 题目描述:将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例: 输入:1->2->3, 1->2->3 输出:1->1->2->2->3->3 代码: /** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode * mergeTwoLists ( struct ListNode * l1 , struct ListNode * l2 ) { if ( l1 == NULL ) return l2 ; if ( l2 == NULL ) return l1 ; if ( l1 -> val >= l2 -> val ) { l2 -> next = mergeTwoLists ( l1 , l2 -> next ) ; return l2 ; } else { l1 -> next = mergeTwoLists ( l1 -> next , l2 ) ; return l1 ; } } 执行代码: # include <stdio.h> # include <stdlib.h> typedef struct Node {

写给自己看的单链表(2):进阶操作

牧云@^-^@ 提交于 2020-01-27 18:39:09
搬运自我的CSDN https://blog.csdn.net/u013213111/article/details/88666880 !!!Attention:以下操作中的单链表均带有头结点!!! 1.反转 方法有好几种,可以参考 看图理解单链表的反转 ,这里采用3个指针prev、current和s遍历单链表,逐个节点进行反转的方法。当节点数为0或1时没有必要进行反转,所以首先要进行判断。最后要注意把head指针指向正确的节点。 1 void ReverseList(Lnode *head) 2 { 3 if (head == NULL || head->next == NULL || head->next->next == NULL) 4 return; 5 Lnode *prev, *current, *s; 6 current = head->next; 7 prev = NULL; 8 while (current != NULL) { 9 s = current->next; 10 current->next = prev; 11 prev = current; 12 current = s; 13 } 14 head->next = prev; 15 } 2.合并 有就地合并和新建一个链表两种方法。这里采用就地合并,合并后原先的链表就不能再被使用了