今天说说递归思想,在我们编码时,有的时候递归能够让我们的算法更加通俗易懂,并且代码量也是大大的减少。比如我先前的系列中说到了
关于树的“先序,中序和后序”遍历,那么看看用递归来描叙这个问题是多少的简洁,多么的轻松。
#region 二叉树的先序遍历
/// <summary>
/// 二叉树的先序遍历
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tree"></param>
public void BinTree_DLR<T>(ChainTree<T> tree)
{
if (tree == null)
return;
//先输出根元素
Console.Write(tree.data + "\t");
//然后遍历左子树
BinTree_DLR(tree.left);
//最后遍历右子树
BinTree_DLR(tree.right);
}
#endregion
#region 二叉树的中序遍历
/// <summary>
/// 二叉树的中序遍历
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tree"></param>
public void BinTree_LDR<T>(ChainTree<T> tree)
{
if (tree == null)
return;
//优先遍历左子树
BinTree_LDR(tree.left);
//然后输出节点
Console.Write(tree.data + "\t");
//最后遍历右子树
BinTree_LDR(tree.right);
}
#endregion
#region 二叉树的后序遍历
/// <summary>
/// 二叉树的后序遍历
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tree"></param>
public void BinTree_LRD<T>(ChainTree<T> tree)
{
if (tree == null)
return;
//优先遍历左子树
BinTree_LRD(tree.left);
//然后遍历右子树
BinTree_LRD(tree.right);
//最后输出节点元素
Console.Write(tree.data + "\t");
}
#endregion
看看,多么简洁明了。当然递归都是可以改成非递归的,但是就不见得简洁和通俗易懂了。
一: 概念
递归,说白了就是直接或者间接的调用自己的一种算法。它是把求解问题转化为规模较小的子问题,然后通过多次递归一直到可以得出结果
的最小解,然后通过最小解逐层向上返回调用,最终得到整个问题的解。总之递归可以概括为一句话就是:“能进则进,不进则退”。
二:三要素
<1> 递归中每次循环都必须使问题规模有所缩小。
<2> 递归操作的每两步都是有紧密的联系,如在“递归”的“归操作时”,前一次的输出就是后一次的输入。
<3> 当子问题的规模足够小时,必须能够直接求出该规模问题的解,其实也就是必须要有结束递归的条件。
三: 注意
<1> 前面也说了,递归必须要有一个递归出口。
<2> 深层次的递归会涉及到频繁进栈出栈和分配内存空间,所以运行效率比较低,当问题规模较大时,不推荐使用。
<3> 在递归过程中,每次调用中的参数,方法返回点,局部变量都是存放在堆栈中的,如果当问题规模非常大时,容易造成堆栈溢出。
四: 举二个例子
<1> 相信大家在初中的时候都学过阶乘吧,比如:5!=5*4*3*2*1
思路:根据上面的阶乘特征很容易我们就可以推导出n!=n*(n-1)*(n-2)....*2*1,
那么进一步其实就是: n!=n*(n-1)! ,
(n-1)!=(n-1)*(n-2)!。
显然他是满足递归的三要素,当n的规模不大时,我们可以用递归拿下。
@Test
public void testJC() {
while (true) {
// 阶乘问题
System.out.println("请输入一个求阶乘的一个数:");
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
System.out.println("阶乘的结果为:" + fact(num));
}
}
public int fact(int n) {
if (n == 1)
return 1;
return n * fact(n - 1);
}
第一次: 输入5的时候能够正确求出。
第二次: 输入10的时候求出来竟然362万之多,可见多恐怖,如果俺们的时间复杂度是n!,那程序也就Game Over了,
第三次:输入100,已经超过了int.MaxValue了,
第四次: 输入10w,蹦出著名了“堆栈溢出”,好家伙,我们知道“递归”在程序中使用“栈”的形式存放的,每一次“递归”中,方法的返回值
包括函数中的参数都会存放在栈中,C#中每个线程分配的栈空间为1M,所以当N的规模非常大时,就把栈玩爆了。
<2> 在大一时上计算机文化基础的时候我们就接触过”进制转换问题“,比如将”十进制“转化为”二进制“。
思路:采用除2取余法,取余数为相应二进制数的最低位,然后再用商除以2得到次低位.......直到最后一次相除商为0时得到二进制的最高位,
比如(100)10=(1100100)2, 仔细分析这个问题,会发现它是满足”递归“的三要素的,
① 进制转换中,数据规模会有所缩小。
② 当商为0时,就是我们递归的出口。
所以这个问题我们就可以用递归拿下。
private StringBuffer mm = new StringBuffer();
@Test
public void testConvertToBinary() {
int num = 100;
convertToBinary(num);
System.out.println("十进制数字:"+num+", 转换为二进制为:"+mm);
}
public void convertToBinary(int num) {
int a = num % 2;
num = num / 2;
if (num > 0) {
convertToBinary(num);
}
mm.append(a);
}
扩展其他方式:
1、循环实现
@Test
public void test3(){
int a = 100;
String s ="";
while(a>0){
s = a%2 + s;
a /= 2;
}
System.out.println(s);
}
2、 java API实现
@Test
public void test2(){
int a = 100;
System.out.println(Integer.toBinaryString(a));
}
参考:http://blog.csdn.net/m13666368773/article/details/7531463
分享到:
相关推荐
在Java编程语言中,递归是一种非常重要的算法思想和技术手段。递归是指一个方法直接或间接地调用自身的过程。这种自我调用的方式可以用来解决很多复杂的问题,并且通常能够使代码更加简洁和易于理解。 #### 二、...
递归算法的核心思想是将问题分解成更小的子问题,然后通过函数调用自身来解决这些子问题。递归算法的优点是可以简洁地解决复杂的问题,但是需要注意递归深度以避免栈溢出。 在 Java 中,递归算法可以通过函数调用...
利用递归原理解八皇后 代码简单 注释也很详细 重要的是看你怎么分析递归操作
递归是一种常见的算法思想,在计算机科学中占有重要地位。简单来说,递归是指在函数的定义或执行过程中调用自身的方法。递归通常用于解决那些可以分解为相似子问题的问题,通过不断将大问题分解成小问题来求解。 ##...
它的基本思想是从输入字符串的开始符号出发,通过一系列的递归调用解析函数,尝试匹配输入串中的各个符号,直到整个输入被完全消耗。这种方法易于理解和实现,特别适合于构造简单的解析器。 在给定的压缩包中,有两...
在IT领域,构建树型结构是一...总结来说,这个Java程序利用递归思想和数据库操作,构建了一个基于数据的树型结构。理解这些核心概念对于进行类似项目开发至关重要,无论是数据可视化、文件系统管理还是复杂的算法实现。
### Java使用递归实现字符串反转 在Java编程语言中,递归是一种常用的方法来解决许多问题,特别是那些可以通过分解成更小子问题来解决的问题。本文将详细介绍如何使用递归来实现字符串的反转。 #### 一、递归基础...
在Java编程中,这两种算法都可以通过递归和分治策略进行实现,以提高效率和可读性。下面我们将深入探讨这两个算法的原理、实现方式以及它们在Java中的应用。 首先,快速排序是一种高效的排序算法,由C.A.R. Hoare在...
《旅行商问题(TSP)的递归Java实现解析》 ...虽然这种方法在大规模问题上效率较低,但它提供了一个理解问题和递归思想的良好起点。在实际应用中,结合动态规划和其他优化策略,可以提升算法的效率。
在给定的标题和描述中,我们看到的是如何使用Java递归遍历来遍历和构建树形菜单。 首先,我们需要了解递归的基本概念。递归是一种函数或方法调用自身的技术,通常在解决具有相同基本结构的问题时非常有用。在树形...
递归下降法的基本思想是将文法规则转化为一系列的Java方法,每个方法对应一个非终结符。当解析器遇到输入符号时,它会调用相应的解析方法。如果这个方法能够成功消耗掉输入符号并返回一个成功的结果,那么就表示输入...
递归算法是编程中一种非常重要的思想,尤其在Java这样的面向对象编程语言中,它的应用广泛且深入。递归的基本原理是将一个大问题分解为若干个相同或相似的小问题来解决,这些小问题同样可以用同样的方法去解决,直到...
递归算法的基本思想是将一个大问题分解成若干个与原问题相似的小问题来解决。在Java编程语言中,递归同样被广泛应用,尤其是在处理文件系统操作时。 #### 一、递归算法的基本概念 递归通常涉及两个主要部分: 1. *...
java基础编程:递归思想求解第5个人的年龄问题
总之,`Matrix.java`文件可能展示了如何使用Java递归遍历矩阵,无论是按行优先还是按列优先,都是通过分解大问题到小问题,然后逐个解决问题。理解递归遍历的思想和实现方式对于处理复杂的数据结构和算法非常重要。
一个Java小程序,利用递归思想实现的归并排序算法。其中有两个类,排序数据是写死在main方法中的。
递归的基本思想是将n个盘子的移动分解为先移动上面的n-1个盘子到辅助柱子,然后将最大的盘子移动到目标柱子,最后将那n-1个盘子从辅助柱子移动到目标柱子。递归调用本身非常简洁,但实际操作中需要注意递归调用的...
在Java编程中,递归是一种强大的工具,常用于解决涉及层次结构或树形结构的问题...通过结合`File`类的方法和递归思想,我们可以高效地完成这些任务。在实际项目中,正确使用递归可以极大地提高代码的可读性和可维护性。
递归的基本思想是将大问题分解为与原问题形式相同的小问题来解决,然后逐步合并这些小问题的解,最终得到原问题的解。 #### 二、递归的两个基本要素 递归算法的核心在于正确地定义递归基和递归步骤。 1. **递归基...
一个用JAVA编写的扫雷程序,原创! 可以输入界面的行列数和雷数,此程序的精髓在打开一个不是雷而且周围没有雷的格子时,用到了递归的思想。