2014-01-09 113 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) 
          } 
    

    希望這有助於。