題目描述:給出一棵二叉樹,返回其節點值的前序走訪。要求不能用遞迴。
什麼是前序走訪應該已經很清楚了,範例我就省略了。
關於二叉樹的前序走訪,我之前已經詳細講過,當時是用的最簡單的遞迴解決這個問題的,詳見:點擊開啟連結,但是遞迴是有它的天然缺陷的,那就是效率低。所以,有人試圖用一種更高效的辦法替代遞迴。就這個問題來說,由於二叉樹的前序走訪用的是“深搜”的策略(中序遍曆,後序遍曆也都是“深搜”),而“深搜”其實一般情況下可以用棧來實現。
回憶一下,前序走訪就是一個“根-左-右”的過程
拿上面這幅圖來說,前序走訪的結果應該是:ABDECFG,對於到達的每一個節點都按照先掃描這個節點本身,再掃描左孩子,最後右孩子的過程。所以,我不妨建立這樣一個棧--stack
1. stack儲存當前節點,一開始,當然是根節點A,stack = [A]
2. 刪除stack的棧頂元素,將棧頂元素所儲存的值加入到最後我們要的結果清單裡面
3. 如果被刪除的元素有右孩子,將右孩子加入stack,stack = [C]
4. 如果被刪除的元素有左孩子,將左孩子加入stack,stack = [C,B]
可以看出,由於右孩子先加入,所以再把這個新的棧從第一步開始迭代時,就會先處理左孩子(圖中的B),以此類推,處理左孩子時,又會先刪除該節點(B),再加入該節點(B)的右孩子:stack = [C,E],最後加入左孩子:stack = [C,E,D]...
很明顯,我在這裡通過棧的特殊結構實現了深搜的策略
看代碼吧:
"""Definition of TreeNode:class TreeNode: def __init__(self, val): self.val = val self.left, self.right = None, None"""class Solution: """ @param root: The root of binary tree. @return: Preorder in ArrayList which contains node values. """ def preorderTraversal(self, root): result = [] stack = [] # 也可寫成 if root: if root != None: stack.append(root) while len(stack) != 0: cur = stack.pop() result.append(cur.val) if cur.right != None: stack.append(cur.right) if cur.left != None: stack.append(cur.left) return result # write your code here
需要注意的是第19行的簡潔寫法可以是if root:,24,26行也都該這樣寫,但是我現在這樣,更容易讓大家理解。