二叉樹(shù)的遍歷

相信只要了解過(guò)二叉樹(shù),都知道二叉樹(shù)的3種遍歷方式:前序遍歷、中序遍歷、后序遍歷。
甚至不夸張的說(shuō),其遞歸的遍歷方法閉著眼睛也能寫(xiě)出來(lái)。所以本篇意不在記錄其遞歸的寫(xiě)法,而是探尋其迭代的方法。

0、定義二叉樹(shù)

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

1. 前序遍歷

想要理解或者實(shí)現(xiàn)前序遍歷方法,我們可以從其遞歸方法入手,了解其實(shí)現(xiàn)過(guò)程。

class Solution:
    def preorderTraversal(self, root: TreeNode):
        res = []
        
        def dfs(root):
            nonlocal res
            if not root:
                return 
            res.append(root.val)
            dfs(root.left)
            dfs(root.right)
        
        dfs(root)
        return res

將其遞歸的過(guò)程展開(kāi),就如同其下的方式:訪問(wèn)當(dāng)前節(jié)點(diǎn),進(jìn)入左子節(jié)點(diǎn),然后訪問(wèn)當(dāng)前節(jié)點(diǎn)的左子節(jié)點(diǎn)……,遇到null則返回,然后訪問(wèn)節(jié)點(diǎn)的右子節(jié)點(diǎn),由于節(jié)點(diǎn)不能反向找到其父節(jié)點(diǎn),我們需要保存其右子節(jié)點(diǎn)。同時(shí),我們需要從最近的右子節(jié)點(diǎn)開(kāi)始訪問(wèn),也即利用棧來(lái)代替遞歸算法中的調(diào)用棧。

dfs(root)
    print(root.val)
    dfs(root.left)
        print(root.left.val)
        dfs(root.left)
            null return
        dfs(root.right)
            print(root.right.val)
            dfs(root.left)
            ...

下面是其迭代方法的實(shí)現(xiàn)

class Solution:
    def preorderTraversal(self, root):
        res = []
        stack = []
        
        while stack or root:
            while root:
                res.append(root.val)
                stack.append(root.right)
                root = root.left
            root = stack.pop()
        
        return res

2. 中序遍歷

中序遍歷的遞歸調(diào)用過(guò)程如下,深入左子節(jié)點(diǎn),當(dāng)其為空則返回,訪問(wèn)節(jié)點(diǎn),然后進(jìn)入其右子節(jié)點(diǎn)。重復(fù)該過(guò)程。

dfs(root)
    dfs(root.left)
        dfs(root.left)
            null return
        print(root.val)
        dfs(root.right)
            dfs(root.left)
                dfs(root.left)
                ...

可以看到,我們需要先將左子節(jié)點(diǎn)保存,待其為空后,當(dāng)問(wèn)節(jié)點(diǎn),進(jìn)入右子樹(shù),繼續(xù)……

class Solution:
    def inorderTraversal(self, root: TreeNode):
        res = []
        stack = []
        while stack or root:
            while root:
                stack.append(root)
                root = root.left
            root = stack.pop()
            res.append(root.val)
            root = root.right
        return res

3. 后序遍歷

后序遍歷可以看著是前序遍歷的鏡像,所以可以套用前序遍歷的方法,但是需要將最后結(jié)果進(jìn)行反轉(zhuǎn)。

class Solution:
    def postorderTraversal(self, root):
        res = []
        stack = []
        
        while stack or root:
            while root:
                res.append(root.val)
                stack.append(root.left)
                root = root.right
            root = stack.pop()
        
        return res[::-1]

4. 顏色標(biāo)記法

這個(gè)方法是leetcode解題中,針對(duì)前中后序遍歷均適用,而且容易理解。
以后序遍歷為例,其代碼如下。需要注意的是,因?yàn)闂5暮筮M(jìn)先出結(jié)構(gòu),所以我們的入棧順序?yàn)橄喾捶较颉?br> 同理,如果是前序遍歷,則入棧順序?yàn)椋河?、左、中?br> 中序遍歷的入棧順序?yàn)椋河?、中、左?/p>

class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        res = []
        white, gray = 1, 0
        stack = [(white, root)]
        while stack:
            color, node = stack.pop()
            if not node:
                continue
            if color == white:
                stack.append((gray, node))
                stack.append((white, node.right))
                stack.append((white, node.left))
            else:
                res.append(node.val)
        return res

5. leetcode

94. 二叉樹(shù)的中序遍歷

145. 二叉樹(shù)的后序遍歷

6. 參考

1、https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/yan-se-biao-ji-fa-yi-chong-tong-yong-qie-jian-ming/
2、https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/die-dai-fa-by-jason-2/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容