Language agnostic 递归的相关性

Language agnostic 递归的相关性,language-agnostic,recursion,Language Agnostic,Recursion,因此,我目前正试图掌握递归的概念,我理解我遇到的大多数问题,但我觉得它的使用似乎不适用于太多的计算问题。这只是一个新手的假设,所以我想问,作为程序员,递归有很多实际用途吗?还有,用它可以解决哪些典型问题?我见过的唯一的问题是堆排序和脑筋急转弯类型的问题,比如“河内塔”,它看起来非常具体,缺乏广泛的用途 感谢递归在编程中有过多的用途-一个经典的例子是导航树结构,在树结构中,你可以在发现每个子元素时调用导航函数,等等。这不是你每天都在使用的东西。但是许多关于搜索和排序数据的算法都可以利用它。一般来说

因此,我目前正试图掌握递归的概念,我理解我遇到的大多数问题,但我觉得它的使用似乎不适用于太多的计算问题。这只是一个新手的假设,所以我想问,作为程序员,递归有很多实际用途吗?还有,用它可以解决哪些典型问题?我见过的唯一的问题是堆排序和脑筋急转弯类型的问题,比如“河内塔”,它看起来非常具体,缺乏广泛的用途


感谢

递归在编程中有过多的用途-一个经典的例子是导航树结构,在树结构中,你可以在发现每个子元素时调用导航函数,等等。

这不是你每天都在使用的东西。但是许多关于搜索和排序数据的算法都可以利用它。一般来说,大多数情况下rsive算法也可以使用迭代编写;通常递归版本更简单。

我想这取决于你将要做什么。作为一名从事公司网站工作的C#/ASP.NET开发人员,我可能每年编写的递归函数不到一个。当我玩弄我的爱好代码时(主要是统计研究)我发现有更多的机会应用递归。一部分是主题,另一部分是我更依赖于第三方库,客户在进行公司工作时已经决定了第三方库(需要递归的算法是在第三方库中实现的)。

如果您检查列为“相关”的问题对于这个问题,您将发现大量关于递归的内容,这些内容将帮助您更好地理解它

递归不是什么新鲜事,它也不仅仅是一个玩具概念。递归算法在计算机出现之前就已经存在了

“阶乘”的经典定义就是一个很好的例子:

fact(x) =
if x < 0 then fact(x) is undefined
if x = 0 then fact(0) = 1
if x > 0 then fact(x) = x * fact(x-1)
事实(x)=
如果x<0,则事实(x)未定义
如果x=0,则事实(0)=1
如果x>0,则事实(x)=x*事实(x-1)

这并不是计算机极客们创造的东西,他们认为递归是一个很酷的玩具。这是标准的数学定义。

调用递归,作为一种程序构造,几乎不应该被使用,除非在非常高级的语言中,您希望编译器将其优化为不同的构造。调用递归的使用,除非您可以在深度上建立较小的界限,否则会导致堆栈溢出,而不是为您解答问题的好堆栈溢出。:-)


另一方面,递归作为算法概念非常有用。它是使用任何递归定义的数据格式(如HTML或XML或分层文件系统)以及在搜索、排序和(每个人都喜欢的)图形渲染等无数其他字段中实现重要算法的关键。

以下是一些没有递归几乎不可能实现的字段:

  • XML、HTML或任何其他树状文档结构
  • 编译和解析
  • 自然语言处理
  • 许多数学概念,例如阶乘
递归可以为其他复杂问题提供出色的解决方案。如果你对编程作为一门艺术感兴趣,你真的应该深入研究

哦,如果你不确定,这里有一个递归的可靠定义:

递归(名词):参见“递归”


有几种语言不支持循环(例如for和while),因此当需要重复行为时,需要使用递归(我相信J没有循环)。在许多示例中,递归需要的代码要少得多。例如,我编写了一个isPrime方法,它只需要两行代码

public静态布尔值isPrime(int n)
{
返回n!=1&&isPrime(n,2);
}

公共静态布尔值isPrime(int n,int c)
{
返回c==n | | n%c!=0&&isPrime(n,c+1);
}

迭代解决方案需要更多的代码:

public static boolean isPrime(int n)
{
    if(n==1) return false;
    int c=2;
    while(c!=n)
    {
        if(n%c==0) return false;
    }
    return true;
}
另一个很好的例子是当您使用ListNodes时,例如,如果您想检查ListNode中的所有元素是否相同,那么递归解决方案会容易得多

public static <E> boolean allSame(ListNode<E> list)
    {
        return list.getNext()==null||list.getValue().equals(list.getNext().getValue())&&allSame(list.getNext());
    }
public静态布尔allSame(列表节点列表)
{
返回list.getNext()==null | | list.getValue().equals(list.getNext().getValue())&&allSame(list.getNext());
}
迭代解决方案如下所示:

public static <E> boolean allSame(ListNode<E> list)
{
    while(list.getNext()!=null)
    {
        if(!list.getValue().equals(list)) return false;
        list=list.getNext();
    }
    return true;
}
public静态布尔allSame(列表节点列表)
{
while(list.getNext()!=null)
{
如果(!list.getValue().equals(list))返回false;
list=list.getNext();
}
返回true;
}

正如您所见,在大多数情况下,递归解比迭代解短。

试着编写一个非递归的“河内塔”解,这将向您展示递归是多么简单。@Zeke:如果我没记错的话,实际上有一个非常简单而优雅的非递归算法。我想有人在上面贴了一个关于它的问题,所以有一次试图理解它。是的,看这里:比递归简单得多。嗯,是的,谢谢你。事实上,我对递归有着非常扎实的理解,我的语句也站得住脚?你处理数据库吗?XML有一个非常递归的定义,而数据库,尤其是那些带有表的数据库,它们本身有链接,是递归解决方案的主要问题。我只是一直在计算很长时间,我花了很多时间来教育新手,让他们了解那些在学校里教得不太好的东西。事实上,正确理解“河内之塔”并不是特别的,而是有着非常广泛的用途。解决问题的一个技巧是使一个问题看起来像另一个问题——特别是你知道如何解决的问题。导航树结构(如在数据库中,或