JAVA递归

1.递归作为一种算法在程序设计语言中广泛应用,是指函数/过程/子程序在运行过程中直接或间接调用自身而产生的重入现象。

2.递归算法一般用于解决三种问题:

1)数据的定义是按递归定义的。( Fibonacci(斐波那契)函数)。

2)问题解决按递归算法实现。(回溯)

3)数据的结构形式是按递归定义的。(数的便利,图的搜索)

递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。

在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。在实际编程中尤其要注意栈溢出问题。

借助递归方法,我们可以把一个相对复杂的问题转化为一个与原问题相似的规模较小的问题来求解,递归方法只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。但在带来便捷的同时,也会有一些缺点,也即:通常用递归方法的运行效率不高。

/**
* 计算二进制中1的个数
* N为奇数,二进制中1的个数为N/2
* @author 伟1
*
*/
public class Ditui {
/*
* num=13
* 1.getNum(13/2=6)+1;
* 2.getNum(6/2=3)+1;
* 3.getNum(3/2=1)+1+1;
* 4.getNumm(1)+1+1;
*/
public static int getNum(int num) {
if (num==1) {
return 1;
}else if (0==num%2) {
return getNum(num/2);
}else {
return getNum(num/2)+1;
}

}

public static void main(String[] args) {

System.out.println(new Ditui().getNum(13));
}
}

二叉树遍历

在计算机科学中,二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。

一颗简单的二叉树

二叉树的遍历分为三种:前(先)序、中序、后序遍历。

设L、D、R分别表示二叉树的左子树、根结点和遍历右子树,则先(根)序遍历二叉树的顺序是DLR,中(根)序遍历二叉树的顺序是LDR,后(根)序遍历二叉树的顺序是LRD。还有按层遍历二叉树。这些方法的时间复杂度都是O(n),n为结点个数。

假设我们有一个包含值的value和指向两个子结点的left和right的树结点结构。我们可以写出这样的过程:

先序遍历(递归实现):

1

2

3

4

visit(node)

print node.value

if node.left  != null then visit(node.left)

if node.right != null then visit(node.right)

 中序遍历(递归实现):

1

2

3

4

visit(node)

if node.left  != null then visit(node.left)

print node.value

if node.right != null then visit(node.right)

 后序遍历(递归实现):

1

2

3

4

visit(node)

if node.left  != null then visit(node.left)

if node.right != null then visit(node.right)

print node.value

字符串全排列

问题:

写一个函数返回一个串的所有排列。

解析:

对于一个长度为n的串,它的全排列共有A(n, n)=n!种。这个问题也是一个递归的问题, 不过我们可以用不同的思路去理解它。为了方便讲解,假设我们要考察的串是”abc”, 递归函数名叫permu。

思路一:

我们可以把串“abc”中的第0个字符a取出来,然后递归调用permu计算剩余的串“bc” 的排列,得到{bc, cb}。然后再将字符a插入这两个串中的任何一个空位(插空法), 得到最终所有的排列。比如,a插入串bc的所有(3个)空位,得到{abc,bac,bca}。 递归的终止条件是什么呢?当一个串为空,就无法再取出其中的第0个字符了, 所以此时返回一个空的排列。代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

typedef vector<string> vs;

vs permu(string s){

vs result;

if(s == ""){

result.push_back("");

return result;

}

string c = s.substr(0, 1);

vs res = permu(s.substr(1));

for(int i=0; i<res.size(); ++i){

string t = res[i];

for(int j=0; j<=t.length(); ++j){

string u = t;

u.insert(j, c);

result.push_back(u);

}

}

return result; //调用result的拷贝构造函数,返回它的一份copy,然后这个局部变量销毁(与基本类型一样)

}

思路二:

我们还可以用另一种思路来递归解这个问题。还是针对串“abc”, 我依次取出这个串中的每个字符,然后调用permu去计算剩余串的排列。 然后只需要把取出的字符加到剩余串排列的每个字符前即可。对于这个例子, 程序先取出a,然后计算剩余串的排列得到{bc,cb},然后把a加到它们的前面,得到 {abc,acb};接着取出b,计算剩余串的排列得到{ac,ca},然后把b加到它们前面, 得到{bac,bca};后面的同理。最后就可以得到“abc”的全序列。代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

vs permu1(string s){

vs result;

if(s == ""){

result.push_back("");

return result;

}

for(int i=0; i<s.length(); ++i){

string c = s.substr(i, 1);

string t = s;

vs res = permu1(t.erase(i, 1));

for(int j=0; j<res.size(); ++j){

result.push_back(c + res[j]);

}

}

return result;

}

时间: 2024-10-08 06:50:12

JAVA递归的相关文章

JAVA递归、非递归遍历二叉树(转)

原文链接: JAVA递归.非递归遍历二叉树 import java.util.Stack; import java.util.HashMap; public class BinTree { private char date; private BinTree lchild; private BinTree rchild; public BinTree(char c) { date = c; } // 先序遍历递归 public static void preOrder(BinTree t) {

欧几里得求最大公约数--JAVA递归实现

欧几里得算法求最大公约数算法思想: 求p和q的最大公约数,如果q=0,最大公约数就是p:否则,p除以q余数为r,p和q的最大公约数即q和r的最大公约数. java实现代码: 1 public class Demo0 { 2 public static void main(String[] args) { 3 4 System.out.println(gcd(24,120)); 5 } 6 7 8 public static int gcd(int p,int q){ 9 10 if(q==0)

java——递归调用

递归调用是调用自身的函数,并传给自身的相应的参数,这一运算过程是一层层的进行的,直到满足一定条件时,才停止调用. 递归函数的特点 1.函数要直接或间接调用自身. 2.要有递归终止条件检查,即递归终止的条件被满足后,则不再调用自身函数. 3.如果不满足递归终止的条件,则调用涉及递归调用的表达式.在调用函数自身时,有关终止条件的参数要发生变化,而且需向递归终止的方向变化. 举例: 计算5的阶乘? public class TestWudejiecheng { public static void m

JAVA递归删除目录及包含的全部文件

JAVA递归删除目录及包含的全部文件/** * 递归删除某一个目录 * @param objDir 目标目录文件 * @return 是否删除成功,true为成功 */ public static boolean deleteDir(File objDir) { if (objDir.exists()) { File[] dirs = objDir.listFiles(); for (int i = 0; i < dirs.length; i++) { if (dirs[i].isDirecto

字符串数组元素排列与组合的Java递归实现

排列与组合的Java递归实现 (参考) 我们在笔试面试过程中经常会遇到关于排列与组合的问题,其实这些可以通过递归简单的实现,看下面两个例子: (1)关于字符串排列的问题 输入一个字符串,打印出该字符串中字符的所有排列.例如输入字符串abc,则输出由字符a.b.c所能排列出来的所有字符串abc.acb.bac.bca.cab和cba. 可以这样想:固定第一个字符a,求后面两个字符bc的排列.当两个字符bc的排列求好之后,我们把第一个字符a和后面的b交换,得到bac,接着我们固定第一个字符b,求后面

Java递归获得TreeJson

联合MyBatis,由Map获取 源码如下 package com.zl.demo; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Java递归获取TreeJson * @author ZhangLi * @date 2019年6月18日 上午11:10:45 * @WeiXin zl4828 * @备注 沫沫金原创提供,仅供参考 *

JAVA递归实现线索化二叉树

JAVA递归实现线索化二叉树 基础理论 首先,二叉树递归遍历分为先序遍历.中序遍历和后序遍历. 先序遍历为:根节点+左子树+右子树 中序遍历为:左子树+根节点+右子树 后序遍历为:左子树+右子树+根节点 (只要记住根节点在哪里就是什么遍历,且都是先左再右) 线索化 现在有这么一棵二叉树,它的数据结构由左节点+权+右节点构成. 可以看到4,5,6,7这几个节点的左右节点空间被浪费了.因此,线索化是指有效利用这些空间. 中序遍历的顺序为:4 2 5 1 6 3 7 现在引入前驱节点以及后继节点. 前

java递归删除文件及目录

package base; import java.io.File; public class delete { public static void main(String[] args) { deleteFileAndFoder("../yang"); } static void deleteFileAndFoder(String path){ File f=new File(path); if(f.isDirectory()){//假设是文件夹.先递归删除 String[] li

Java 递归、尾递归、非递归 处理阶乘问题

n!=n*(n-1)! import java.io.BufferedReader; import java.io.InputStreamReader; /** * n的阶乘,即n! (n*(n-1)*(n-2)*...1). * 0!为什么=1,由于1!=1*0!.所以0!=1 * * @author stone * @date 2015-1-6 下午18:48:00 */ public class FactorialRecursion { static long fact(long n) {

Java 递归输出文件

import java.io.File;public class TestAddressSet {************递归输出文件下的所有目录**********    public static void main(String[] args) {        // TODO Auto-generated method stub        File file= new File("E:/张敬轩");        myList(file);    } private sta