递归看不懂

q312977 2012-06-14 09:55:10
有么有大牛 表达能力强的给我讲下递归啊 是在看不懂他怎么执行的?跳来跳去
static string Test(int i)
{
if (i == 10)
{
return i.ToString();//①
}
else
{
Test(++i);
return i.ToString();//②
}
}

Console.WriteLine(Test(1)); 结果居然是2,
1.为什么第①出 return不跳出?
2.当满足条件后执行else的 ② 为什么他也不出去,++居然成了--了 ,还有他为什么减到2才执行完?条件在哪里

不单单是这个例子 就大牛们帮忙解释下关于递归或许更麻烦的例子
...全文
682 44 打赏 收藏 转发到动态 举报
写回复
用AI写文章
44 条回复
切换为时间正序
请发表友善的回复…
发表回复
q312977 2012-06-15
  • 打赏
  • 举报
回复
谢谢各位热心解答,由于本人新手 每人一分都给不过来 十分抱歉,还是祝好人一生平安吧
  • 打赏
  • 举报
回复
这个例子四个很糟糕的递归例子,对初学者会造成困扰。

递归思想跟一个人受到的“数学归纳法”或者“形式逻辑解析方法”的训练息息相关。最初理解归纳方法时,我们都习惯于直观地看到收敛的效果。而这个题目却是以
T(n)=T(n+1); T(10)=N;
这种形式,跟任何一种经典的归纳法表达式相比,它都没有强调收敛并结束递归的效果。
nikolaichow 2012-06-14
  • 打赏
  • 举报
回复
return i.ToString();//② 去掉
草原的雨夜 2012-06-14
  • 打赏
  • 举报
回复
递归的运行机制是先递(正向循环,直至结束条件满足为止,本例中的i==10,到此完成了递),后归(就是你所说else里的多次运行,其实是回朔,递归完了在回朔这是递归的机制,回朔的过程就是出栈计算数据的过程)至于本例中为啥会返回结果是2那是因为你的i只是对于方法内部有效,外部是无效的。。。

理解了递归的两个过程及入栈出栈过程这个问题其实很好解释。。。
q312977 2012-06-14
  • 打赏
  • 举报
回复
我晕avphoenixi给的例子我刚明白一点点,我看你这个
static string Test(int i)
{
return i == 10 ? i.ToString() : Test(++i);
}

Console.WriteLine(Test(1));//输出10
怎么有晕了
他不是和 if else 相等么 他怎么会输出10呢??
Mourinho 2012-06-14
  • 打赏
  • 举报
回复
想要输出10可以这么写

static string Test(int i)
{
return i == 10 ? i.ToString() : Test(++i);
}

Console.WriteLine(Test(1));//输出10

Mourinho 2012-06-14
  • 打赏
  • 举报
回复
还看不懂的话就加断点调试,弄清楚递归执行顺序就明白了
Mourinho 2012-06-14
  • 打赏
  • 举报
回复
递归顺序
Test(1) i = 2 -> Test(2) i = 3 -> ... Test(9) i = 10 -> Test(10)
返回值
Test(10) i = 10 return 10 -> Test(9) i = 10 -> return 10 -> Test(8) i = 9 return 9 Test(7) -> ...-> Test(2) i = 3 return 3 -> Test(1) i = 2 -> return 2 -> 主线程调用函数

所以结果就是2
BinaryTreeEx 2012-06-14
  • 打赏
  • 举报
回复
[Quote=引用 37 楼 的回复:]

却是有点老火,没学过数据结构,高中毕业而已

理解有点困难,但是基本上 清楚了一点他的执行原理,
[/Quote]
楼主高中毕业能写到这个地步,那就不一样了,值得鼓励,相当不错。其实递归程序很容易写,也很容易调试。
关键是要用递归推导的思路来写程序,控制好什么时候递归结束,需要意识到每次递归时问题的规模都被减小了
一次。
xboxeer 2012-06-14
  • 打赏
  • 举报
回复
他不是没有跳出 建议你在
if (i == 10)
{
return i.ToString();//①
}

里面加一个这个
throw new Exception() 然后看一下StackTrack 也就是堆栈跟踪
[Quote=引用 23 楼 的回复:]
听上面这么多人说我明白了,i为什么是2,但是 当i满足条件为什么不跳出? return i.ToString();//① 他没有跳出这段函数

Test(++i);
return i.ToString();//②
}
当i满足10时候他会重复执行这一段, 等于return了 多次都没有跳出,但最终他跳出了 这时候i=2,想知道他为什么多执行了这么多次 还有i=2 时候怎么跳出了……
[/Quote]
q312977 2012-06-14
  • 打赏
  • 举报
回复
听上面这么多人说我明白了,i为什么是2,但是 当i满足条件为什么不跳出? return i.ToString();//① 他没有跳出这段函数

Test(++i);
return i.ToString();//②
}
当i满足10时候他会重复执行这一段, 等于return了 多次都没有跳出,但最终他跳出了 这时候i=2,想知道他为什么多执行了这么多次 还有i=2 时候怎么跳出了?为什么呢?
zhaohaifeng295 2012-06-14
  • 打赏
  • 举报
回复
static string Test(int i)
{
if (i == 10)
{
return i.ToString();//① //如果i大于10了,就不在递归了,返回i
}
else //只要i的值小于10,就以++i作为参数递归,此时i的值+1了
{
Test(++i);
return i.ToString();//②
}
}

__天涯寻梦 2012-06-14
  • 打赏
  • 举报
回复
static string Test(int i)
{
if (i == 10)
{
return i.ToString();//①
}
else
{
Test2(++i);
return i.ToString();//②
}
}

static string Test2(int i)
{
if (i == 10)
{
return i.ToString();//①
}
else
{
Test3(++i);
return i.ToString();//②
}
}

static string Test3(int i)
{
if (i == 10)
{
return i.ToString();//①
}
else
{
Test4(++i);
return i.ToString();//②
}
}

static string Test4(int i)
{
if (i == 10)
{
return i.ToString();//①
}
else
{
Test5(++i);
return i.ToString();//②
}
}

static string Test5(int i)
{
if (i == 10)
{
return i.ToString();//①
}
else
{
Test6(++i);
return i.ToString();//②
}
}

static string Test6(int i)
{
if (i == 10)
{
return i.ToString();//①
}
else
{
Test7(++i);
return i.ToString();//②
}
}

static string Test7(int i)
{
if (i == 10)
{
return i.ToString();//①
}
else
{
Test8(++i);
return i.ToString();//②
}
}

static string Test8(int i)
{
if (i == 10)
{
return i.ToString();//①
}
else
{
Test9(++i);
return i.ToString();//②
}
}

static string Test9(int i)
{
if (i == 10)
{
return i.ToString();//①
}
else
{
Test10(++i);
return i.ToString();//②
}
}

static string Test10(int i)
{
return i.ToString();//①
}

这个方法执行时展开就是上面这些,你把这些加到代码里替换原先的 Test 方法,执行 Console.WriteLine(Test(1)) ,单步看运行过程你就明白了
__天涯寻梦 2012-06-14
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 的回复:]
看到这么多人回复 很感动,但是我真的还没搞明白。
{
这根本不算递归,方法首次传入参数是1,第一个if不满足,因为1小于10,进到else里面,++i,此时i是2,虽然再次调用了Test,但不处理返回值,而且参数值类型传入的是副本,任你里面怎么处理,外面还是不变,最后i.ToString,就是‘2’。}

但是我单步调试的话,他会进到①里边,这时候为什么不跳出?
另外单步调试 当i==1……
[/Quote]
是会进到①里,但是进到①时的调用方并不是你的 Console.WriteLine(Test(1)) ,是 Test 方法,所以 跳出跳到 Test 方法里去了,而 Test 又不处理这个跳出的结果,等于说是这个结果被直接扔掉了,你在最外部的代码得不到这个值。
threenewbee 2012-06-14
  • 打赏
  • 举报
回复
递归可以加深你对函数形参、实参的认识,以及每次调用的数据会形成一个堆栈,我想老师讲解这些的时候都会画一个堆栈图。
xboxeer 2012-06-14
  • 打赏
  • 举报
回复
首先 你不知道对栈是否了解 每次调用 都会生产新的i在栈顶 每次return 都会让这个i退栈 但是由于i是值类型 所以说你看到的所谓i从10减到2不是在执行--操作 而是说这个i本身并没有被改变 而是在递归调用的时候传了一个复制进去 所以最终输出的只是++i的结果
threenewbee 2012-06-14
  • 打赏
  • 举报
回复
递归对于你学习函数调用来说,没有任何额外的知识,除了调用的函数是自己以外。

递归适合解决那些数学上可以用归纳法递推来解决问题。
fzamygsd 2012-06-14
  • 打赏
  • 举报
回复
不太懂。。。
一起学习
threenewbee 2012-06-14
  • 打赏
  • 举报
回复
我纠正下,有些回答可能会让你理解偏差。

这个程序算递归,判断递归的原则很简单,就是看程序有没有调用自己。

其实递归没有什么神秘的,只是自己调用自己会有些让人觉得混淆。

如同
foo()
{
int i = 3;
bar(3);
}
bar(int x)
{
int i; //这个i和foo中的i无关,不难理解吧
}
一样,
如果自己调用自己,那么下一层调用内的变量和上一层也没有关系。
q312977 2012-06-14
  • 打赏
  • 举报
回复
看到这么多人回复 很感动,但是我真的还没搞明白。
{
这根本不算递归,方法首次传入参数是1,第一个if不满足,因为1小于10,进到else里面,++i,此时i是2,虽然再次调用了Test,但不处理返回值,而且参数值类型传入的是副本,任你里面怎么处理,外面还是不变,最后i.ToString,就是‘2’。}

但是我单步调试的话,他会进到①里边,这时候为什么不跳出?
另外单步调试 当i==10执行完return i.ToString()。他会直接跳到最后一个大括号,然后返回
Test(++i) 然后一直执行 Test (++i) 和 return i.ToString()和最后一个大扩好,然后 i的值从10一直退到2,我只是想了解他的执行过程,他什么会这样执行,递归原理是啥,
加载更多回复(23)

110,533

社区成员

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

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

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