用递归代替 while 循环

Replacing while-loop with recursion

快速简单的问题:

这是:

private static void SetupConnection()
{
    try
    {
        TcpClient client = new TcpClient(myServer, myPort);
        //Do whatever...
    }
    catch (SocketException)
    {
        //Server is closed. Retry in 10 minutes.
        Thread.Sleep(600000);
        SetupConnection();
    }

一个可行的替代方案:

private static void SetupConnection()
{
    while (true)
    {
        try
        {
            TcpClient client = new TcpClient(myServer, myPort);
            //Do whatever...
            break;
        }
        catch (SocketException)
        {
            //Server is closed. Retry in 10 minutes.
            Thread.Sleep(600000);
        }
    }
}

虽然第二个看起来 "cleaner" 我仍然很好奇第一个是否也可以接受 – 如果不是,那为什么不呢?

递归在这种情况下很糟糕,因为如果您的程序运行时间过长并且重试连接,您最终会遇到 WhosebugException。

为什么递归不好?

您需要了解什么是调用堆栈。

这是一个保存在内存中的堆栈。每次调用新方法时,该方法的引用和参数都会添加到此堆栈中。该堆栈将保存在内存 (RAM) 中。

使用递归,如果你在没有任何边界条件的情况下继续调用方法,堆栈将继续增长。

一段时间后,它将处于无法接受任何进一步条目的状态,因为没有足够的内存来容纳它。

那时你会得到 "Stack Overflow Exception"。

我们可以在不使用递归的情况下重写每个递归算法吗?

是的,你可以。该方法通常称为 "Iterative approach".

在任何情况下,您都可以使用辅助堆栈/列表/变量组来保存您在递归中使用的参数。

然后你可以迭代这些变量,直到达到边界条件。

这样,您无需一次又一次地调用您的方法即可获得相同的结果。 使用这种方法总是更好。

那为什么要写递归算法呢?

有时候,递归算法很容易阅读。迭代方法代码可能不容易阅读,这就是人们多次尝试编写递归代码的原因。

您可以根据以下两点决定是使用迭代方法还是递归方法:

  • 输入样本

  • 代码可维护性

如果你还想写递归方法,不要忘记添加递归停止的边界条件。

例如。树遍历代码(pre order, in order , post order)写递归算法更容易理解。 只要您对树中的节点/级别数量有一定限制,这就可以正常工作。如果您已经知道您的树非常庞大,您可能会采用迭代方法。

希望这能帮助您更好地理解这些方法。