二叉樹漫遊——編程技術與技巧總結(上):遞迴技術

來源:互聯網
上載者:User

                          
二叉樹漫遊——編程技術與技巧總結(上):遞迴技術

 

            本系列分三篇文章,分別對二叉樹編程中的常用技術和技巧進行了總結。第一篇是關於二叉樹編程的遞迴技術的;第二篇討論如何將遞迴程式轉化為非遞迴程式;第三篇討論二叉樹編程的其它方法和技術。

 

             一、 二叉樹編程概述

            程式 =資料結構+演算法。更精確地說,任何程式的功能實現,從技術角度來說,通過選取合適的資料結構和高效的演算法即可做到。二叉樹是一種非線性資料結構,即每一個元素都可能有0個,1個,或2個後繼結點;這使得二叉樹編程比線性表編程增加了一些難度;另一方面,由於二叉樹具有天然的遞迴特性,要掌握二叉樹編程技術,必須懂得如何用遞迴來思考問題以及熟練掌握遞迴程式的編寫,這對初學者來說,無疑是一道必須跨越的門檻。

 

             二、遞迴技術概述

            遞迴技術並不神秘。從方法層面上看,遞迴技術通過使用相同的方法求解比原問題規模更小的子問題,併合並子問題的解而實現;遞迴與分治是緊密關聯的;從技術手段上看,遞迴通過相同的函數調用來實現。即有P(n)=
P(P(i),P(j), …,
P(s),G(1))。

要寫出遞迴程式,其實也並不困難,有三點技巧:A.分析和找出遞迴的部分;
B.確定遞迴調用的參數形式;
C.確定遞迴結束條件。掌握這些技巧,甚至不用對遞迴機製作過多瞭解,就能寫出優雅的遞迴代碼。在後面的樣本中,會逐漸給出一些相關的方法和技巧。

 

          三、二叉樹的遞迴求解技術

二叉樹的遞迴求解通常可以歸納為以下步驟:

S1: 對根結點求解;

S2: 遞迴求解左子樹;

S3: 遞迴求解右子樹;

S4 :
合并根結點、左子樹、右子樹的解,進而得到原問題的解。

         
聰明的讀者馬上意識到,上述步驟與二叉樹的先序遍曆非常類似。針對具體的問題,S1,S2, S3
的順序可能有所變化。

 

A.分析和找出遞迴的部分:

         
很顯然,二叉樹根結點的左子樹和右子樹都是一棵二叉樹,因此,可以用相同的策略求解左右子樹;這就是可以遞迴的部分;

B.
確定遞迴調用的參數形式:

         
這一點也比較明顯,即將二叉樹的根結點作為調用參數。根據問題需要,可能會增加一些其它的參數,用於標示當前遍曆的深度,要返回的列表等。

C.確定遞迴條件。通常,根據應用將根結點需要滿足的條件作為遞迴結束條件。

         
這裡有一個小技巧:你可以先對A/A(B,)/A(,B)/A(B,C)這幾種基本的二叉樹結構進行分析,以掌握遞迴程式的行為和機制。

 

四、樣本

(1)二叉樹的先序、中序、後序遞迴遍曆。這個是最基本的,請讀者自行查閱相關書籍弄懂;

(2)求二叉樹的總結點數目。

A.分析和找出遞迴的部分:很顯然,二叉樹的總結點數目
=1 +
左子樹的總結點數目 +右子樹的總結點數目。
1表示根結點。

B.遞迴調用的參數: 二叉樹的根結點。

C.遞迴結束條件: 根結點為空白。

 

         
現在,就可以開始寫遞迴程式了。先寫遞迴結束時的情況,再寫繼續遞迴的情況。熟練掌握遞迴程式的編寫不是一蹴而就的,多練習就習慣了。

 

Publicint size(TreeNode root) {

if(root == null) { return 0; }

else{

return1 + size(root.getLChild()) + size(root.getRChild()) ;

}

}

 

(3)將二叉樹所有結點的左右子樹交換

         
初看起來,像是很困難;然而運用遞迴的思維,很容易就能想到:如果根結點不為空白,則交換根結點的左右子樹;遞迴求解左子樹;遞迴求解右子樹。於是,可以寫出遞迴程式:

publicvoid swapTree(TreeNode root)

{

if(root != null) {

TreeNodetmp = root.getLChild();

root.setLChild(root.getRChild());

root.setRChild(tmp);

swapTree(root.getLChild());

swapTree(root.getRChild());

}

}

 

(4)
求二叉樹的最長路徑(如果有多條,輸出其中一條)

         
這個問題咋看起來,沒發現明顯可以遞迴的地方。這時,就需要仔細地分析。首先,二叉樹的最長路徑必定包括非空根結點;其次,最長路徑必定在葉子結點處到達;那麼,二叉樹的最長路徑與其左右子樹的最長路徑有什麼關聯呢?可以很容易想到:二叉樹的最長路徑
=非空根結點
+Max(左子樹的最長路徑,右子樹的最長路徑)。這樣,就可以整理出思路:

LongestPath(root):

if(root != null) { //
若根結點不為空白,則儲存在最長路徑中

longestPath.add(root);

if(root.getLChild() == null && root.getRChild() == null) {

//到達葉子結點,可以輸出路徑

returnpath;

}

else{

//遞迴求解左子樹最長路徑

leftLongestPath= LongestPath(root.getLChild());

//遞迴求解右子樹最長路徑

rightLongestPath= LongestPath(root.getRChild());

if(leftLongestPath.size() >= rightLongestPath.size())

{

      //
左子樹最長路徑大於或等於右子樹最長路徑,則取左子樹最長路徑

path.addAll(leftLongestPath);

}

else{

       //
否則,取右子樹最長路徑

       
path.addAll(rightLongestPath);

}

}

 

         
由於二叉樹的遞迴求解通常非常簡潔,且運行效率也在可接受範圍內,因此,有人甚至建議:二叉樹的問題求解,首選遞迴技術。本文從方法層面上討論了如何編寫二叉樹的遞迴程式,這些方法和技巧使得,即使對遞迴的機制不甚瞭解,也可以寫出非常優雅的遞迴代碼。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.