算法—— 递归思想

#region 二叉树的先序遍历
2 /// <summary>
3  /// 二叉树的先序遍历
4  /// </summary>
5  /// <typeparam name="T"></typeparam>
6  /// <param name="tree"></param>
7          public void BinTree_DLR<T>(ChainTree<T> tree)
8          {
9              if (tree == null)
10                  return;
11  
12              //先输出根元素
13              Console.Write(tree.data + "\t");
14  
15              //然后遍历左子树
16              BinTree_DLR(tree.left);
17  
18              //最后遍历右子树
19              BinTree_DLR(tree.right);
20          }
21          #endregion
22  
23          #region 二叉树的中序遍历
24          /// <summary>
25  /// 二叉树的中序遍历
26  /// </summary>
27  /// <typeparam name="T"></typeparam>
28  /// <param name="tree"></param>
29          public void BinTree_LDR<T>(ChainTree<T> tree)
30          {
31              if (tree == null)
32                  return;
33  
34              //优先遍历左子树
35              BinTree_LDR(tree.left);
36  
37              //然后输出节点
38              Console.Write(tree.data + "\t");
39  
40              //最后遍历右子树
41              BinTree_LDR(tree.right);
42          }
43          #endregion
44  
45          #region 二叉树的后序遍历
46          /// <summary>
47  /// 二叉树的后序遍历
48  /// </summary>
49  /// <typeparam name="T"></typeparam>
50  /// <param name="tree"></param>
51          public void BinTree_LRD<T>(ChainTree<T> tree)
52          {
53              if (tree == null)
54                  return;
55  
56              //优先遍历左子树
57              BinTree_LRD(tree.left);
58  
59              //然后遍历右子树
60              BinTree_LRD(tree.right);
61  
62              //最后输出节点元素
63              Console.Write(tree.data + "\t");
64          }
65          #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的规模不大时,我们可以用递归拿下。

 1 static void Main(string[] args) 2         { 3             while (true) 4             { 5                 //阶乘问题 6                 Console.WriteLine("\n请输入一个求阶乘的一个数:"); 7  8                 int num = int.Parse(Console.ReadLine()); 9 10                 Console.WriteLine("\n阶乘的结果为:" + fact(num));11             }12         }13 14         static int fact(int n)15         {16             if (n == 1)17                 return 1;18 19             return n * fact(n - 1);20         }

第一次: 输入5的时候能够正确求出。

第二次: 输入10的时候求出来竟然362万之多,可见多恐怖,如果俺们的时间复杂度是n!,那程序也就Game Over了,

第三次:输入100,已经超过了int.MaxValue了,

第四次: 输入10w,蹦出著名了“堆栈溢出”,好家伙,我们知道“递归”在程序中使用“栈”的形式存放的,每一次“递归”中,方法的返回值

包括函数中的参数都会存放在栈中,C#中每个线程分配的栈空间为1M,所以当N的规模非常大时,就把栈玩爆了。

<2> 在大一时上计算机文化基础的时候我们就接触过”进制转换问题“,比如将”十进制“转化为”二进制“。

思路:采用除2取余法,取余数为相应二进制数的最低位,然后再用商除以2得到次低位.......直到最后一次相除商为0时得到二进制的最高位,

比如(100)10=(1100100)2,   仔细分析这个问题,会发现它是满足”递归“的三要素的,

① 进制转换中,数据规模会有所缩小。

② 当商为0时,就是我们递归的出口。

所以这个问题我们就可以用递归拿下。

  static void Main(string[] args)        {            Console.WriteLine("请输入一个十进制数:");

            int num = int.Parse(Console.ReadLine());

            string result = string.Empty;

            Console.WriteLine("转化的二进制为:" + ConvertToBinary(ref result, num));

            Console.ReadLine();

        }

        static string ConvertToBinary(ref string str, int num)        {            //递的过程            if (num == 0)                return string.Empty;

            ConvertToBinary(ref str, num / 2);

            //归的过程            return str += (num % 2);        }

时间: 2024-10-08 19:40:51

算法—— 递归思想的相关文章

Python算法——递归思想

编程语言在构建程序时的基本操作有:内置数据类型操作.选择.循环.函数调用等,递归实际属于函数调用的一种特殊情况(函数调用自身),其数学基础是数学归纳法.递归在计算机程序设计中非常重要,是许多高级算法实现的基础 编写递归程序的几个要点: 1.终止条件:最简单情况(避免无限循环) 2.递归公式:相邻两次调用间的关系(递归算法核心) 3.忽略调用具体细节:假设所有调用都会达到终止条件(从思想上接受递归算法的关键) 4.效率:递归算法有时效率较低,可考虑其他更高效的实现方式(见问题5) 下面我们通过几个

Java算法——递归思想

描述递归(recursion):程序调用自身的编程技巧. 递归满足2个条件:1)有反复执行的过程(调用自身)2)有跳出反复执行过程的条件(递归出口) 递归与栈的关系下面演示的是求n的阶乘 int Factorial(int n){ if (n == 0) return 1; return n * Factorial(n - 1); } 常常听到 “递归的过程就是出入栈的过程”,这句话怎么理解?我们以上述代码为例,取 n=3,则过程如下: 第 1~4 步,都是入栈过程,Factorial(3)调用

算法之递归思想

树的遍历的实现就是典型的递归思想. /* * description:树的遍历示例,递归 * 访问顺序: * 前序: 当前节点 - 左子树 - 右子树 * 中序: 左子树 - 当前节点 - 右子树 * 后序: 左子树 - 右子树 - 当前节点 * * writeby: nick * date: 2012-10-22 23:56 */ #include <iostream> using namespace std; struct node { int item; node *l, *r; nod

区域增长算法的设计与实现(递归思想和堆栈数据结构)

程序员:左正康           发表时间:2013年12月16日 0:56    代号:与老鼠共处一室的日子 算法设计思想:算法中主要有2个函数,分别是CreateSeed函数和Decide函数,CreateSeed函数:创建种子点:Decide函数:决定连通点是否进入生长区域,进入生长区域的连通点作为下一个种子点递归调用CreateSeed函数,直到生长区域不再长大,结束递归. 程序测试展示:

python算法之递归思想

#递归思想#基本原理:函数内部调用函数本身,注意:至少有一个终止条件#例1.斐波那契数列def fib(x): if x==1 or x==2: return 1 else: return fib(x-1) + fib(x-2)def fibList(x): fibList = [] for i in range(x): fibList.append(fib(i+1)) return fibListprint(fibList(9)) #例2.n的阶乘(n*(n-1)*(n-2)*...2*1)d

第二篇 递归思想

今天说说递归思想,在我们编码时,有的时候递归能够让我们的算法更加通俗易懂,并且代码量也是大大的减少.比如我先前的系列中说到了 关于树的“先序,中序和后序”遍历,那么看看用递归来描叙这个问题是多少的简洁,多么的轻松. 1 #region 二叉树的先序遍历 2 /// <summary> 3 /// 二叉树的先序遍历 4 /// </summary> 5 /// <typeparam name="T"></typeparam> 6 /// &

算法--递归策略

本文地址:http://www.cnblogs.com/archimedes/p/algorithm-recursion.html,转载请注明源地址. 递归的概念与基本思想 一个函数.过程.概念或数学结构,如果在其定义或说明内部又直接或间接地出现有其本身的引用,则称它们是递归的或者是递归定义的.在程序设计中,过程或函数直接或者间接调用自己,就被称为递归调用. 递归的实现方法 递归是借助于一个递归工作栈来实现:递归=递推+回归: 递推:问题向一极推进,这一过程叫做递推:这一过程相当于压栈. 回归:

分治策略结合递归思想求最大子序列和

我的主力博客:半亩方塘 对于 <数据结构与算法分析--C语言描述> 一书第 20 页所描述的算法 3,相信会有很多人表示不怎么理解,下面我由具体问题的求解过程出发,谈谈我自己的理解: 首先,什么是分治法呢?所谓 分治法,就是 将一个问题的求解过程分解为两个大小相等的子问题进行求解,如果分解后的子问题本身也可以分解的话,则将这个分解的过程进行下去,直至最后得到的子问题不能再分解为止,最后将子问题的解逐步合并并可能做一些少量的附加工作,得到最后整个问题的解.在求解原来整个问题的算法思想,与求解每一

五大算法基本思想—分治,动态规划,贪心,回溯,分支界限

一.算法理解 算法是什么,即是按照一定的步骤,一步步去解决某个问题,解决问题的方法步骤就称为算法,例如数学中我们学过的做一个运算,解一个方程,等等,都需要有一个清晰的思路,一步步地去完成.可以说算法就在身边. 算法和计算机有什么关系,计算机它是机器,没有人类的大脑可以思考,但是它怎么完成我们交给他的人物的呢,就是通过算法(当然是人为预先设计好的),计算机解决任何问题都要依赖于算法,没有算法也就没有计算机. 为了计算机能更好更有效率的运行,算法就必须足够好,既要正确易理解,又要可靠效率.下面来研究