2014-01-09 75 views
0

我在理解递归时遇到了问题,我没有得到书籍和教程中的解释。下面的例子发现列表中的最大值,在这里我卡在第二行,我根本不明白发生了什么后max([H|T], Max) when H > Max ->理解递归的问题

我真的很感激,如果我能得到所有步骤的解释代码,比如为什么去-> max(T, H);-> Max.

max([H|T]) -> max(T, H). 

max([H|T], Max) when H > Max -> max(T, H); 
max([_|T], Max)    -> max(T, Max); 
max([], Max)    -> Max. 

非常感谢! E.

+0

有递归一个非常详细的岗位上,所以如果你还没有发现它已经:http://stackoverflow.com/questions/717725/understanding-recursion?rq=1 – kjw0188

回答

3

我试着一步一步解释。让我们假设你有一个清单:[2, 3, 1]

  1. max([2, 3, 1]).

  2. H=2 , T=[3, 1]
    max([H|T]) -> max(T, H).

  3. H=3, T=[1], Max=2
    max([H|T], Max) when H > Max -> max(T, H);
    这里when块说:如果H是大于Max然后调用max函数再次作为max([ 1],3)。

  4. 在这里,我们再一次,但不同的价值观:
    H=1, T=[], Max=3
    max([H|T], Max) when H > Max -> max(T, H);
    1 > 3false所以当块失败,并试图下一个最大的功能定义,这导致步骤5

  5. 我们知道H是小于最大值,因为第4步失败,所以我们忽略它。
    [] = [], Max = 3
    max([], Max) -> Max.

+0

我真的很喜欢这个解释,但如何事实证明,第三步中Max = 2? –

+0

@Eri这是因为它在第二步以'2'的形式传递(参见'H = 2'?)。 – Agis

+0

我必须是盲人或只是愚蠢的,但我没有看到在第二步马克斯是通过2还是如何。 –

0

此功能可以改写这样的:

max([H|T]) -> max(T, H). 

max([], Max) -> Max; 
max([H|T], Max) -> 
    NewMax = if H > Max -> H; 
       true -> Max 
      end, 
    %% NewMax = erlang:max(H, Max), 
    max(T, NewMax). 
T = [], Max=3
max([_|T], Max) -> max(T, Max);

  • 我们最后一个函数定义,说Max元素中找到匹配

    要理解它,你必须知道模式匹配是如何工作的。

    1. 我们将列表中的头元素视为当前最大值。我们需要查看尾部的所有其他元素,并检查它们中的任何元素是否更大。
    2. 如果列表的其余部分为空,则当前最大值为结果。
    3. 如果列表不是空的,请拍摄新头并确定新的最大值。然后继续清单的其余部分和新的最大值。这里必须注意的是,传递给下一个max/2迭代的列表总是前面传递值的尾部,所以我们不检查我们已经看到的值。
  • 0

    最后三行在你的代码是完全不同的条款相同的功能(max/2)的。这意味着只要传递了两个参数即可调用max函数,它将与这三个子句进行模式匹配。

    这个子句:

    max([_|T], Max) -> max(T, Max); 
    

    将匹配每当列表是非空的并且该列表(H)的头部是小于或等于Max。它会通过max/2通过T这是一个列表和Max这是一个数字。这个新的呼叫也将与三个条款进行模式匹配。

    这一条款:

    max([], Max) -> Max. 
    

    将匹配每当列表为空,将只返回Max这是一个数字。

    1

    了解递归的最佳方法是通过可视化来实现。让我给你一个很简单的例子:

    假设你想知道什么是资格成为美国的总理,这就是:

    您必须是美国的国家公民,为此,这里是规则:

    1. 你是一个天生的美国(或)的
    2. 你的父母是美国的全国公民现在

    ,第一选择向前伸直,使哟你的美国公民,或同样的事情适用于你的父母,这可能会再次检查他们的父母......等等。

    所以会有一个简单的答案,这是第一个选项。这就是所谓的基础案例。在第二种选择中,您可能会为您的父母申请相同的公民身份检查流程。

    这是一个非常简单的伪代码,可以解释递归:

    isEligibleForPrimeMinister checkCitizenship(You, yourParents){ 
          Base Case {returns true(That you are US citizen)} 
          checkCitizenship(yourParents, YourGrandParents) 
          } 
    

    希望这有助于。