1. 程式人生 > >遞迴原理解析

遞迴原理解析

大部分的人對遞迴的理解可能停留在遞迴程式設計:遞迴(recursion)就是子程式(或函式)直接呼叫自己或通過一系列呼叫語句間接呼叫自己。這篇文章會從遞迴程式設計出發一步步瞭解遞迴原理。

一、遞迴程式設計:遞迴(recursion)就是子程式(或函式)直接呼叫自己或通過一系列呼叫語句間接呼叫自己,是一種描述問題和解決問題的基本方法。

1,採用遞迴方法的原因:

遞迴通常用來解決結構自相似的問題。所謂結構自相似,是指構成原問題的子問題與原問題在結構上相似,可以用類似的方法解決。具體地,整個問題的解決,可以分為兩部分:第一部分是一些特殊情況,有直接的解法;第二部分與原問題相似,但比原問題的規模小。實際上,遞迴是把一個不能或不好解決的大問題轉化為一個或幾個小問題,再把這些小問題進一步分解成更小的問題,直至每個小問題都可以直接解決。

2,遞迴的兩個基本要素:
邊界條件:確定遞迴到何時終止,也稱為遞迴出口。
遞迴模式:大問題是如何分解為小問題的,也稱為遞迴體。遞迴函式只有具備了這兩個要素,才能在有限次計算後得出結果

二、遞迴原理:

1,遞迴函式的內部執行過程:
一個遞迴函式的呼叫過程類似於多個函式的巢狀的呼叫,只不過呼叫函式和被呼叫函式是同一個函式。為了保證遞迴函式的正確執行,系統需設立一個工作棧。具體地說,遞迴呼叫的內部執行過程如下:

(1)運動開始時,首先為遞迴呼叫建立一個工作棧,其結構包括值參、區域性變數和返回地址;
(2)每次執行遞迴呼叫之前,把遞迴函式的值參和區域性變數的當前值以及呼叫後的返回地址壓棧;
(3)每次遞迴呼叫結束後,將棧頂元素出棧,使相應的值參和區域性變數恢復為呼叫前的值,
然後轉向返回地址指定的位置繼續執行。 

2,遞迴呼叫有層級關係:如果把呼叫遞迴函式的主函式稱為第0層,進入函式後,首次遞迴呼叫自身稱為第1層呼叫;從第i層遞迴呼叫自身稱為第i+1層。反之,退出第i+1層呼叫應該返回第i層。

  • 每一級的函式呼叫都有它自己的變數。
  • 每一次函式呼叫都會有一次返回,並且是某一級遞迴返回到呼叫它的那一級,而不是直接返回到main()函式中的初始呼叫部分。
  • 遞迴函式中,位於遞迴呼叫前的語句和各級被調函式具有相同的執行順序。位於遞迴呼叫語句之前,它按照遞迴呼叫的順序被執行,即依次為第一級、第二級、第三級、第四級……。
  • 遞迴函式中,位於遞迴呼叫後的語句的執行順序和各個被調函式的順序相反。位於遞迴呼叫語句之後,其執行順序依次是:….第四級、第三級、第二級、第一級。
  • 雖然每一級遞迴都有自己的變數,但是函式程式碼不會複製。
  • 遞迴函式中必須包含終止遞迴的語句。通常遞迴函式會使用一個if條件語句或其他類似語句一邊當函式引數達到某個特定值時結束遞迴呼叫。

三、例項解釋遞迴的原理:(python)

def ff(n):
    print('layer is {};address is :{}'.format(n,id(n)))
    if n < 4:
        ff(n+1)
    print('layer is {};address is :{}'.format(n, id(n)))
ff(1)
**輸出:**
layer is 1;address is :1548465216
layer is 2;address is :1548465248
layer is 3;address is :1548465280
layer is 4;address is :1548465312

layer is 4;address is :1548465312
layer is 3;address is :1548465280
layer is 2;address is :1548465248
layer is 1;address is :1548465216

遞迴的具體工作過程:

輸出一共八句,前四句很好理解,後四句的理解體現了遞迴的根本:當某一級遞迴結束,則該級函式馬上將程式的控制權交給該函式的呼叫函式。 比如說第四級呼叫,輸出了語句#1之後,判斷n < 4時是不成立的,所以不再繼續遞迴呼叫,而是輸出語句#2,輸完語句#2之後,第四級呼叫就結束了,此時它就會將控制權交給第三級呼叫,第三級呼叫函式中前一個執行過的語句是在if語句中進行第四級呼叫,因此,當第三級呼叫獲得第四級給它的控制權時,它繼續執行後面的程式碼,即執行列印語句#2,這就輸出了第6句話。當第三級呼叫結束後,第二級呼叫函式開始繼續執行,即輸出了第7句話。以此類推。