研究了一天的尾递归 还是又一些不明白

maocheng82 2016-06-11 05:38:03
一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第30位数是多少, 用递归算法实现。
答:public class MainClass
{
public static void Main()
{
Console.WriteLine(Foo(30));
}
public static int Foo(int i)
{
if (i <= 0)
return 0;
else if(i > 0 && i <= 2)
return 1;
else return Foo -1) + Foo(i - 2);
}
}


为了演示这尾递归执行的顺序 我只执行 Foo(5), 执行i从5到2 等于2返回1 当返回1 下个步骤是执行的什么??是执行Foo(i - 2)这个函数吗???




...全文
405 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
xuzuning 2016-06-14
  • 打赏
  • 举报
回复
你做一下退格处理就更清楚了
HaoYuan 2016-06-14
  • 打赏
  • 举报
回复
你要明白递归首先要明白什么是递归
秋的红果实 2016-06-14
  • 打赏
  • 举报
回复
就是个算法问题,怎么跟编译器,线程扯上关系了? 测试代码:

static List<int> l = new List<int>();
static int f(int i)
{
    l.Add(i);

    if (i <= 0)
    {
        return 0;
    }
    else if (i <= 2)
    {
        return 1;
    }
    else
    {
        return f(i - 1) + f(i - 2);

    }
}
static void Main(string[] args)
{
    Console.WriteLine(f(5));
    Console.WriteLine("-------------");
    
    foreach(int i in l)
    {
        Console.WriteLine(i.ToString());

    }
    Console.Read();

}

输出:
threenewbee 2016-06-13
  • 打赏
  • 举报
回复
http://bbs.csdn.net/topics/390317532
maocheng82 2016-06-13
  • 打赏
  • 举报
回复
引用 15 楼 xuzuning 的回复:
为了便于观察,修改成如下
        public static int Foo(int i, string msg="") 
        {
            Console.WriteLine(msg);
            if (i <= 0) 
                return 0; 
            else if(i > 0 && i <= 2) 
                return 1;
            else return Foo(i - 1, string.Format("f({0} - 1)", i)) + Foo(i - 2, string.Format("f({0} - 2)", i)); 
        } 
执行次序一目了然
是的 正如上面14楼楼主所说 没有一个固定的顺序 跟编译器有关,跟线程有关。 事先一次for循环,计算出fx(1)到fx(1000)的值:fx(1)=fx(2)=1; fx(n)=fx(n-1)+fx(n-2)。 为什么这么说呢 把I改为7 即执行foo(7) 得到的却是
xuzuning 2016-06-13
  • 打赏
  • 举报
回复
为了便于观察,修改成如下
        public static int Foo(int i, string msg="") 
{
Console.WriteLine(msg);
if (i <= 0)
return 0;
else if(i > 0 && i <= 2)
return 1;
else return Foo(i - 1, string.Format("f({0} - 1)", i)) + Foo(i - 2, string.Format("f({0} - 2)", i));
}
执行次序一目了然
我叫小菜菜 2016-06-13
  • 打赏
  • 举报
回复
5,4,3,2,3,1,3,4,2,4,5,3,2,3,1,3,5 这是递归子函数时计算顺序问题,比如f(x)+f(y),是先计算f(x)还是先计算f(y),其实就是树的前序、中序和后序遍历问题。跟编译器有关,跟线程有关。 这个不就是著名的斐波那契数列嘛,把递归改为迭代,就是最大的优化。 事先一次for循环,计算出fx(1)到fx(1000)的值:fx(1)=fx(2)=1; fx(n)=fx(n-1)+fx(n-2)。 需要哪个值n=k,就直接取fx(k)即可。
秋的红果实 2016-06-13
  • 打赏
  • 举报
回复
引用 9 楼 maocheng82 的回复:
[quote=引用 8 楼 From_TaiWan 的回复:] if (i <= 0) return 0; else if(i > 0 && i <= 2) return 1; else return Foo -1) + Foo(i - 2); 红色部分很重要:1、这里计算出真正的数据(数值),而上边递推都是函数表达式,不是具体数值;2、函数从此退出调用自己,避免了无限调用自己,陷入死循环
谢谢你的解答 本来看你的图 有点了解了 我为了测试它的具体流程 我在输出设置了个断点 看见i是如何变化的, 更糊涂了 5,4,3,2,3,1,3,4,2,4,5,3,2,3,1,3,5 先前四个步骤 很好理解 5,4,3,2后面变成3,1,3.。。。。。。不知怎么计算得来的??[/quote]顺序见下图箭头 好象先序遍历二叉树 不知道你怎么得到5,4,3,2,3,1,3,4,2,4,5,3,2,3,1,3,5的,应该是:5,4,3,2,1,2,3,2,1
maocheng82 2016-06-13
  • 打赏
  • 举报
回复
引用 7 楼 From_TaiWan 的回复:
Foo(i)当I是1或2时,函数都返回1,此时,递推完成;以后就回归了,见下图,图有点丑 所谓回归,就是计算上图中的1+1+1+1+1,也是我们要的结果
又研究了了哈 我想知道它的执行顺序 首先执行的时候比如,赋值是 ,即Foo(5)开始 执行 返回Foo(4),执行Foo(4) 而不是Foo(4)+Foo(3), 那第二个函数什么时候开始执行呢 只有把左边的值得到了,即得到Foo(4) 的值 才开始执行右边的函数 即当返回, return 数字+Foo(3)的时候 才开始执行右边的函数 不知道分析的正确不正确 请大家指教
秋的红果实 2016-06-12
  • 打赏
  • 举报
回复
if (i <= 0) return 0; else if(i > 0 && i <= 2) return 1; else return Foo -1) + Foo(i - 2); 红色部分很重要:1、这里计算出真正的数据(数值),而上边递推都是函数表达式,不是具体数值;2、函数从此退出调用自己,避免了无限调用自己,陷入死循环
秋的红果实 2016-06-12
  • 打赏
  • 举报
回复
Foo(i)当I是1或2时,函数都返回1,此时,递推完成;以后就回归了,见下图,图有点丑 所谓回归,就是计算上图中的1+1+1+1+1,也是我们要的结果
threenewbee 2016-06-12
  • 打赏
  • 举报
回复
伪递归的本质就是循环。我之前分享过尾递归的帖子的。
maocheng82 2016-06-12
  • 打赏
  • 举报
回复
引用 8 楼 From_TaiWan 的回复:
if (i <= 0) return 0; else if(i > 0 && i <= 2) return 1; else return Foo -1) + Foo(i - 2); 红色部分很重要:1、这里计算出真正的数据(数值),而上边递推都是函数表达式,不是具体数值;2、函数从此退出调用自己,避免了无限调用自己,陷入死循环
谢谢你的解答 本来看你的图 有点了解了 我为了测试它的具体流程 我在输出设置了个断点 看见i是如何变化的, 更糊涂了 5,4,3,2,3,1,3,4,2,4,5,3,2,3,1,3,5 先前四个步骤 很好理解 5,4,3,2后面变成3,1,3.。。。。。。不知怎么计算得来的??
吉普赛的歌 2016-06-12
  • 打赏
  • 举报
回复
无论你想知道哪一步, 都可以用单步跟踪来实现的。 学会调试
maocheng82 2016-06-12
  • 打赏
  • 举报
回复
引用 2 楼 sp1234 的回复:
基本上,两点学习要点: 1. 要动手打印(例如 WriteLine 或者 Debug.Pring)、调试操作、测试驱动。要自己动手然后理解。这是你学的东西,而不是看天书。 2. 避免标题党。在你还明明什么都没有看见的时候,起码不要欺骗自己而说皇帝一定穿了新装。
我知道没有啥意义 只是想知道它的执行规律 返回了 下一步执行哪个操作?
hhddzz 2016-06-12
  • 打赏
  • 举报
回复
你这个哪里是尾递归了,再说csc又不支持尾递归优化,研究也没用。
xuzuning 2016-06-11
  • 打赏
  • 举报
回复
都返回了,还执行什么?
  • 打赏
  • 举报
回复
基本上,两点学习要点: 1. 要动手打印(例如 WriteLine 或者 Debug.Pring)、调试操作、测试驱动。要自己动手然后理解。这是你学的东西,而不是看天书。 2. 避免标题党。在你还明明什么都没有看见的时候,起码不要欺骗自己而说皇帝一定穿了新装。
  • 打赏
  • 举报
回复
我不知道你这个问题中纠结“尾递归”这个词儿有什么意义呢? 如果要打印一下程序运行时的输入参数 i,你就打印输出好了。电脑打印出来执行顺序,而用不着用“下个步骤是执行的什么”这种靠瞎猜的做法啊。

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧