首頁>技術>

二叉樹遍歷的概念

二叉樹遍歷是指按照一定次序訪問二叉樹中所有結點,並且每個結點僅被訪問一次的過程。

設N為根結點,L、R分別為左、右子樹,這6種遍歷方法是NLR、LNR、LRN、NRL、RNL、RLN),若再規定先遍歷左子樹,後遍歷右子樹,則對於非空二叉樹,可得到如下3種遞迴的遍歷方法(即NLR、LNR和LRN)。

1)先序遍歷

① 訪問根結點。

② 先序遍歷左子樹。

2)中序遍歷

① 中序遍歷左子樹。

② 訪問根結點。

3)後序遍歷

① 後序遍歷左子樹。

② 後序遍歷右子樹。

先序、中序和後序遍歷遞迴演算法

1)先序遍歷的遞迴演算法

2)中序遍歷的遞迴演算法

3)後序遍歷的遞迴演算法

遞迴遍歷演算法的應用

假設二叉樹採用二叉鏈儲存結構儲存,設計一個演算法求一棵給定二叉樹中的結點個數。

解:求一棵二叉樹中的結點個數是以遍歷演算法為基礎的,任何一種遍歷演算法都可以出一棵二叉樹中的結點個數。

也可以從遞迴演算法設計的角度來求解。設f(b)求二叉樹b中所有結點個數,它是"大問題",f(b.lchild)和f(b.rchild)分別求左、右子樹的結點個數。

假設二叉樹採用二叉鏈儲存結構儲存,設計一個演算法按從左到右輸出一棵二叉樹中所有葉子結點值。

解:由於先序、中序和後序遞迴遍歷演算法都是按從左到右的順序訪問葉子結點的,所以本題可以基於這三種遞迴遍歷演算法求解。

也可以直接採用遞迴演算法設計方法求解。

設f(b)的功能是從左到右輸出以b為根結點的二叉樹的所有葉子結點值,為"大問題",顯然f(b.lchild)和f(b.rchild)是兩個"小問題"。

當b不是葉子結點時,先呼叫f(b.lchild)再呼叫f(b.rchild)。

對應的遞迴模型f(b)如下:

從上述兩例看出,基於遞迴遍歷思路和直接採用遞迴演算法設計方法完全相同。實際上,當求解問題較複雜時,直接採用遞迴演算法設計方法更加簡單方便。

僅從遞迴遍歷角度看,上述兩例基於3種遞迴遍歷思路中任意一種都是可行的,但有些情況並非如此。

一般地,二叉樹由根、左右子樹3部分構成,但可以看成兩類,即根和子樹。

如果需要先處理根再處理子樹,可以採用先序遍歷思路。

如果需要先處理子樹,再處理根,可以採用後序遍歷思路。

假設二叉樹採用二叉鏈儲存結構儲存,設計一個演算法將二叉樹bt1複製到二叉樹bt2。

解:採用直接遞迴演算法設計方法。設f(t1,t2)是由二叉鏈t1複製產生t2,這是"大問題"。

也可以採用基於後序遍歷思路

假設一棵二叉樹採用二叉鏈儲存結構,且所有結點值均不相同,設計一個演算法求二叉樹中指定結點值的結點所在的層次(根結點的層次計為1)

解:

二叉樹中每個結點都有一個相對於根結點的層次,根結點的層次為1,那麼如何指定這種情況呢?

可以採用遞迴演算法引數賦初值的方法,即設f(b,x,h)為"大問題",增加第3個引數h表示第一個引數b指向結點的層次,在初始呼叫時b指向根結點,h對應的實參為1,從而指定了根結點的層次為1的情況。

遞迴演算法引數賦初值問題

假設二叉樹採用二叉鏈儲存結構,且所有結點值均不相同,設計一個演算法輸出值為x的結點的所有祖先。

解法1

根據二叉樹中祖先的定義可知,若一個結點的左孩子或右孩子值為x時,則該結點是x結點的祖先結點;若一個結點的左孩子或右孩子為x結點的祖先結點時,則該結點也為x結點的祖先結點。

設f(t,x)表示t結點是否為x結點的祖先結點。

解法2

二叉樹中x結點的祖先恰好是根結點到x結點的路徑上除了x結點外的所有結點,用全域性變數res列表表示。

改進演算法2:

改為用path[0..d]存放根到x結點的路徑

9
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 資料結構二叉樹(四)