(c#)数据结构与算法分析 --递归

递归
    不知道有新手听没听过别人拿剥糖块来形容递归,诸如一层层地剥好比一层层地进入递归。这种比喻可是误导了我,只想着剥了,其实剥完皮儿,取出糖块,再把皮儿一层层地穿上才算个完整的递归。    

    递归就是自己调用自己的函数或方法了,一般情况,像我这样的新手刚接触递归的时候,迷就迷在了不明白递归的原理上,在 (c#)数据结构与算法分析 --栈与队列 中说过,编译器一般用栈来实现递归,具体就看那篇文章吧。

    这里先举一个用到递归的例子。

    求第n项的三角数字,三角数字就是数列中,第n项的值是第n-1项加上n得来的。这里可不是那个斐波那契数列。
    1,3,6,10,15,21......... 这些个数就是三角数字。

    这个递归方法就是计算第n项的三角数字:

 1 //使用递归求第n项的三角数
 2 private int triangle(int n)
 3         {
 4             if (n == 1//这是递归的基准情形,一个递归没有基准的话,就没法跳出递归。
 5             {
 6                 return n;
 7             }
 8             else
 9             {
10                 return (n + triangle(n - 1)); //调用本方法
11             }
12         }


很简单的一个算法,可用 第n个三角数字=(n*n+n)/2 这个公式来验证其正确性。

仔细看看这个图就会完全明白递归到底怎么递归了。

n=5时,开始调用

第1层

n=5

第2层

n=4

第3层

n=3

第4层

n=2

第3层

n=1

返回 1
                                            <strong><span>加 2<br>
                                            返回 3</span></strong></td>
                                        </tr>
                                    </tbody>
                                </table></div>
                                <strong><span>加 3<br>
                                返回 6</span></strong></td>
                            </tr>
                        </tbody>
                    </table></div>
                    <strong><span>加 4<br>
                    返回 10</span></strong></td>
                </tr>
            </tbody>
        </table></div>
        <strong><span>加 5<br>
        返回 15</span></strong><p></p>
        </td>
    </tr>
</tbody>


返回15
(这个表格在firefox下显示有点问题)

    这时,应该把递归理顺了吧,自己可以试试用递归求阶乘,然后试着解决汉诺塔问题,google搜一下会有很多汉诺塔问题的源码。

    很明显,上面那个递归是尾递归,在某些情况下,比如函数体比较庞大,有很多局部变量,则很容易引起栈溢出。有时候应该消除递归。
   
    这就用到栈了,下面这个源码,功能和上面一样,只不过用栈来消除递归了。

 1 //消除递归,使用栈代替递归
 2         private int triangleStack(int n)
 3         {
 4             Stack<int> traingle = new Stack<int>(); //这个栈来模拟递归中的环境变量
 5 
 6             while (n >= 1//相当于递归中的基准了
 7             {
 8                 traingle.Push(n); //将每次递减的值压入栈,相当于逐层调用递归
 9                 n = n - 1;
10             }
11 
12             while (traingle.Count > 0//这个相当于逐层跳出递归
13             {
14                 n = n + traingle.Pop(); //计算
15             }
16 
17             return n;
18         }


    不是很难吧,主要把递归的原理理清,思路自然就明了了。

    要注意的是,使用递归千万可别忘了基准情形,不然就永远递归不出来了。递归的效率有时候比较低,这样就可以用栈或循环来代替递归了。

posted on   黑暗伯爵  阅读(3039)  评论(2编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述

导航

< 2008年4月 >
30 31 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 1 2 3
4 5 6 7 8 9 10

统计

点击右上角即可分享
微信分享提示