优化递归方法调用

时间:2014-02-07 18:03:29

标签: c# recursion

我正在阅读的其中一本学习C#的书要求我编写一个方法,该方法取1到99999之间的整数,并按顺序显示该整数中的每个数字,将每个数字分隔2个空格。例如:int 87564将作为8 7 5 6 4写入控制台。

这很简单,可以将输入用作字符串,将其转换为char数组,或使用foreach循环遍历字符串,并为每个字符打印出格式化的字符串。

虽然为了好玩而且主要是为了挑战自己,但我喜欢解决这些问题,因为它们仅供第一次学习概念的人使用。本章是关于方法的,并简要介绍了递归。很明显,作者的意图是你使用除法和模数运算来解决这个问题,然后选出每个数字,然后将它们写出来。

因此,在本书中学到的材料方面,解决这个问题的方法确实有限。您可以选择每个数字并将其存储为自己的变量,然后将其按顺序写出来,因为您知道整数范围。

我决定通过真正允许任何非负整数和我的方法涉及递归来使该方法更有用。我真的没有经验使用递归,所以我想得到一些关于我的实现的反馈,看看我能做得更好。

    static void DisplayDigits(int value)
    {
        if (value < 10)
        {
            Console.Write("{0}  ", value);
            return;
        }
        DisplayDigits(value / 10);
        Console.Write("{0}  ", value % 10);
    }

它似乎适用于我尝试过的所有非负数。我甚至写了一个带有ulong并传递它UInt64.MaxValue的重载,它打印出来的一切都很好。我不禁觉得它可能在某种程度上更好。任何批评,建议,更多阅读材料的链接将不胜感激。

2 个答案:

答案 0 :(得分:1)

尝试

static void Digits( uint n )
{
  if ( n == 0 ) return ;
  Digits( n / 10 ) ;
  Console.WriteLine( "{0}  " , n % 10 ) ;
  return ;
}

但是因为递归等同于使用堆栈 - 调用堆栈是你正在使用的堆栈 - 而且,由于Stack<T>也是IEnumerable<T>,递归很容易被转换成等价的< / p>

static void Digits( uint n )
{
   Stack<char> digits = new Stack<digits>() ;
   for ( uint i = n ; i > 0 ; i/=10 )
   {
      digits.Push( '0'+ i%10 ) ;
   }
   Console.WriteLine( string.Join("  ", digits ) ) ;
   return ;
}

只是为了好玩,一个直接的迭代解决方案,除了最基本的基础之外不使用任何东西:

static void WriteDigits( uint n )
{
  string s = "" ;
  do
  {
    if ( s.Length > 0 ) s += "  " ;
    s += (n%10).ToString() ;
    n /= 10 ;
  } while ( n > 0 ) ;
  Console.WriteLine( string.Reverse() ) ;
}

或者,更简单,只使用string的属性和方法的单行:

static void WriteDigits( uint n )
{
  Console.WriteLine( string.Join( "  " , n.ToString().ToCharArray() ) ;
}

答案 1 :(得分:1)

查找“Tail Recursion”

基本上,您希望递归调用是最后一次调用,以便编译器可以通过重用堆栈来优化(不向堆栈添加另一个级别)。

然而,在实践中我发现很难构建。

以下是一个例子:

static string DisplayDigits(int value, string after)
{
    var t = string.Format("{0}  ", value % 10);

    if (value < 10)
    {
        return t + after;
    }

    return DisplayDigits(value / 10, t + after);
}

我建议您将代码结构与数据进行匹配。

对于顺序数据,使用循环(或更好的linq表达式,以实现并行)。

应为分层数据(多个孩子)保留递归调用。