遞歸算法


 摘要:遞歸算法,結構清晰,形式簡單,符合人的思維習慣,容易被理解和閱讀,因而成為計算機程序設計中的一種重要方法,掌握它也有助於理解其他算法。該文闡述了遞歸算法的基本概念,成立的三個條件,直接和間接遞歸分類,通過實例深入分析遞歸在數據結構、函數應用和執行過程中的應用,以及將遞歸轉化為非遞歸的一般方法。
中國論文網 http://www.xzbu.com/8/view-3705319.htm
  關鍵詞:遞歸;算法;消除;程序;應用
  中圖分類號:TP311 文獻標識碼:A 文章編號:1009-3044(2012)30-7229-06
  1 遞歸概念
  1.1 概述
  本文闡述了遞歸算法的基本定義、成立的必要條件和遞歸執行的特點以及在實例中的具體應用,讓學生能理解“遞歸是一種思想”這個概念。
  在生活實際中,有些問題是不能用數學公式解決的,需要通過其他方式、其他算法才能完成,其他重要算法有分治法、回朔法和動態規划等。分治法的三個步驟為:①分解:將當前區間一分為二,求分裂點;②求解:遞歸地對兩個子區間進行歸並排序;③組合:將已排序的兩個子區間歸並為一個有序的區間。其遞歸的終結條件:子區間長度為1(一個記錄自然有序)。 回朔法的三個步驟:①搜索策略:符合遞歸算法,問題解決可以化為子問題,其子問題算法和原問題相同,只是數據增大或減少;②控制策略:避免不必要的窮舉搜索,遇到搜索失敗,從失敗點返回到上一點重新搜索;③數據結構:用數組保存搜索過程中的狀態、路徑。可見,其他算法依然以遞歸算法為基礎,利用遞歸幫助解決問題。
  1.2 概念和成立條件
  遞歸是設計和描述算法的一種有力的工具,它在復雜算法的描述中被經常采用
  1.2.1 概念
  一個函數、過程、概念或數學結構,如果在其定義或說明內部直接地或間接地出現有其本身的引用,或者是為了描述問題的某一狀態,必須用到它的上一狀態,而描述上一狀態,又必須用到它的上一狀態………這種用自己定義自己的方法,稱之為遞歸或者是遞歸定義。
  1.2.2 成立條件
  應滿足三點:①符合遞歸的描述:需要解決的問題可以化為子問題求解,而子問題求解的方法與原問題相同,只是數量增大或減少;②遞歸調用的次數是有限的;③必須有遞歸結束的條件。
  1.3 遞歸分類
  1.3.1 直接遞歸
  程序設計中,過程或函數直接或者間接調用自己,就被稱為遞歸調用。子程序直接調用自己,這稱為直接遞歸;嵌套關系的子程序A和B,內層的B調用外層的A,這是間接低歸;平級關系的子程序A和B,其中A調用了B,B調用了A,這也是間接遞歸,不過,這種間接遞歸用到了“超前引用”的規則。
  2 遞歸本質
  2.1 函數遞歸調用機制
  遞歸函數調用同樣遵守函數調用機制,當函數調用自己時也要將函數狀態、返回地址、函數參數、局部變量壓入棧中進行保存。
  實際上函數被調用時執行的代碼是函數的一個副本,與調用函數的代碼無關。當一個函數被調用兩次,則函數就會有兩個副本在內存中運行,每個副本都有自己的棧空間且與調用函數的棧空間不同,因此不會相互影響。這種調用機制決定了函數是可以遞歸調用的。
  2.2 遞歸調用優缺點
  遞歸使一些復雜的問題處理起來簡單明了,尤其在學習算法設計、數據結構時更能體會到這一點。但是,遞歸在每一次執行時都要為局部變量、返回地址分配棧空間(對方法的每次遞歸調用都會生成新的局部變量和局部參數。假如遞歸層次太多的話,就會消耗太多的stack),這就降低了運行效率,也限制了遞歸的深度。因此,在必要的時候可以只使用遞歸的思想來求解,而程序則轉用非遞歸的方式書寫。
  3 遞歸的應用
  3.1 遞歸定義的數據結構
  3.1.1 二叉樹(定義)
  二叉樹的遞歸定義 二叉樹或者是一棵空樹,或者是一棵由一個根結點和兩棵互不相交的左子樹和右子樹所組成的非空樹,左子樹和右子樹又同樣都是二叉樹。
  下面介紹二叉樹的二叉鏈式存儲結構。我們先給出二叉鏈表鏈結點類型描述:
  tnode為鏈表結點類型名,tlink為指向鏈結點的指針類型,elemtp為結點數據的類型.
  那么如何根據輸入的數據建立二叉鏈表呢?設二叉樹結點數據類型為字符型,各結點數據按照二叉樹的數組表示方式存儲在字符串str中,字符串變量為s;string、整型變量為n;integer及指針為root;tlink,它們已經在外部說明,則二叉鏈表的建立過程可表示為procedure build(str;string);其功能為根據字符串str的內容建立二叉樹的二叉鏈表,並讓root指向這個二叉鏈表。其處理過程為:以1為參數調用遞歸子函數function build0(i;integer):tilink完成二叉鏈表的建立,並讓root指向該鏈表。遞歸子函數function build0(i;integer):tilink的功能為:以字符串str的第i個元素為二叉樹的根結點遞歸的建立二叉鏈表,並返回指向該鏈表的指針。其處理過程為:
  若i小於字符串的長度,且字符串的第i個元素為非空格符,則創建一個鏈結點,在其數據域中存放字符串的第i個元素;
  以下是程序清單:
  3.2 遞歸定義函數
  3.2.1 階乘
  《例》 用遞歸計算n!
  3.3 遞歸定義過程
  3.3.1 樹的遍歷
  根據二叉樹的遞歸定義,一棵非空二叉樹由根結點、左子樹和右子樹組成,因此遍歷一棵非空二叉樹的問題可分解為三個問題,即訪問根結點、遍歷左子樹和遍歷右子樹。顯然,遍歷左、右子樹的問題仍然遍歷二叉樹的問題,所以二叉樹的這三種遍歷方式可以用遞歸算法實現。
  我們以遍歷方案DLR(因為訪問根結點的操作在遍歷左、右子樹之前,故稱之為前序遍歷或先根遍歷)為例,若二叉樹不為空,則
  訪問根結點;
  以前序遍歷方式遍歷根結點的左子樹;   以前序遍歷方式遍歷根結點的右子樹;
  設p為指向二叉樹根結點的指針,則前序遍歷過程可表示為 procedure preorder0(p:tlink),
  其功能為對p所指的二叉樹進行前序遍歷,輸出前序遍歷的結點序列,其處理過程為:
  若p非空,則
  ① 顯示p所指的結點數據;
  ② 前序遍歷p所指的左子樹;
  ③ 前序遍歷p所指的右子樹;
  以下為程序清單:
  4 遞歸消除
  為了提高算法的程序運行速度及減少占用內存空間,和透切理解遞歸遞歸機制(這種理解是熟練掌握遞歸程序技能的必要前提),我們接下來探討遞歸消除。
  遞歸消除,就是將一個遞歸算法轉化為等價的非遞歸算法。遞歸消除一般有兩種方法:
  一、基於循環的遞歸消除。不是用工作棧作為工作機制,而是利用循環算法,即采用遞推算法,這樣可避免重復計算,提高了效率,如下面所要講的斐波那契數列。
  二、基於棧的遞歸消除。大部分遞歸問題無法用遞推算法來消除,在這種情況下,引用一個工作棧作為控制機構以消除遞歸算法,其原理是:利用數組模擬工作棧,保存“返回位置”,以實現過程調用和返回控制。
  4.1 利用棧消除遞歸
  我們以Hanoi(河內/漢諾)塔問題為例,看如何利用數組建立的棧來消除遞歸的。
  例: Hanoi(河內/漢諾)塔問題
  有n個圓盤,依半徑大小(半徑都不同),自下而上套在A柱上,每次只允許移動最上面的一個盤子到另外的柱子上去(除A柱子外,還有B柱子和C柱子,開始時這兩個柱子上沒盤子),但絕不允許發生柱子上出現大盤子在上,小盤子在下的情況,現在要求設計將A柱子上n個盤子搬到C柱子上去的方法。
  問題解析:本題是典型的遞歸程序設計題。
  3) 當n=3時,需要將前2個盤子移到B柱子,再將第三個盤子移到C柱子,然后將2個在B柱子上的盤子借助A柱子移動到C柱子,因此可以得到移動盤子的一般規律:
  a.先將n-1個盤子從A 柱子移動到B柱子,C柱子為中間柱子;
  b.將第n個盤子從A柱子移動到C柱子;
  c.再將n-1個盤子從B柱子移動到C柱子,A柱子為中間柱子。
  其程序如下:
  為了保證遞歸調用正確執行,系統要建立一個遞歸調用工作棧,為各層次的調用分配數據存儲區。每一層遞歸調用所需要的信息構成一個工作記錄,其中包括所有實參指針,所有局部變量以及返回上一層的地址。每進入一層遞歸調用,就產生一個新的工作記錄壓入棧頂。每退出一層遞歸調用,就從棧頂彈出一個工作記錄。
  4.2 利用循環消除遞歸
  例:用遞歸的方法求斐波那契數列中的第n個數
  程序清單如下:
  這樣,就可以將遞歸程序轉化為非遞歸的程序了。
  斐波那契數列用非遞歸算法求解的程序如下:
  5 總結
  總的說來,遞歸是一種非常重要的,應用很廣泛的程序設計方法。遞歸的能力在於用有限的語句來定義對象的無限集合。用遞歸思想寫出的程序往往十分
  簡潔易懂,結構清晰,形式簡單,符合人們的日常思維習慣,容易被理解和閱讀。其他算法,如分治法,有許多是源於遞歸思想,或是由遞歸分解+合並處理,還有如回朔法和動態規划問題 ,動態規划的子問題重疊性質與遞歸有某種相似之處,遞歸+動態修改查表是一種不錯的建立動態規划模型的方法。可見,掌握遞歸算法、理解遞歸思想對於學習其他程序設計方法也是很有幫助的。
  遞歸使一些復雜的問題處理起來簡單明了,尤其在學習算法設計、數據結構時更能體會到這一點。但是,遞歸在每一次執行時都要為局部變量、返回地址分配棧空間,假如遞歸層次太多的話,就會消耗太多的stack,對內存要求很高,這就降低了程序運行效率,也限制了遞歸的層次和深度。因此,在必要的時候可以只使用遞歸的思想來求解,而程序則轉用非遞歸的方式書寫。
  參考文獻:
  [1] 吳再陵,高建軍.全國青少年信息學培訓教材[M].南京: 南京大學出版社,2002.
  [2] 朱振元,朱承.數據結構教程--面向對象實現方法[M].西安:西安電子科技大學出版社,2000.
  [3] 鄧毅.Delphi 4.0入門與提高[M].北京:清華大學出版社,1999.
  [4] 嚴蔚敏.數據結構[M].北京:清華大學出版社,1992.
  [5] 李大友.數據結構與算法[M].北京:機械工業出版社,1996.
  [6] 旺曉東.計算機算法設計與分析[M].北京:電子工業出版社,2004.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM