二叉树的遍历
参考链接:https://segmentfault.com/a/1190000016674584
前言
二叉树的前中后序遍历是面试考察中一个重要的点。而递归方法是最简单实现的,所以要信手拈来。非递归方法更要加以掌握。前序就是根-左-右,中序是左-根-右,后序是左-右-根。
有两种通用的遍历树的策略:
深度优先搜索(DFS)
在这个策略中,我们采用深度作为优先级,以便从跟开始一直到达某个确定的叶子,然后再返回根到达另一个分支。
深度优先搜索策略又可以根据根节点、左孩子和右孩子的相对顺序被细分为前序遍历,中序遍历和后序遍历。
宽度优先搜索(BFS)
我们按照高度顺序一层一层的访问整棵树,高层次的节点将会比低层次的节点先被访问到。
层次遍历
非递归,用队列实现(其实自己想了会能不能用递归结果自己不会。。。
看了下题解,它的递归实现其实用了深度优先。
class Solution: def levelOrder(self, root: TreeNode) -> List[List[int]]: if root==None: return [] result = [[root.val]] quene = [(root,1)] while(quene): root,count = quene.pop(0) if root.left: quene.append((root.left,count+1)) if count+1>len(result): result.append([root.left.val]) else: result[count].append(root.left.val) if root.right: quene.append((root.right,count+1)) if count+1>len(result): result.append([root.right.val]) else: result[count].append(root.right.val) return result
前序遍历
然鹅,很简单的递归算法我自己实现的时候都会出错。。。还是太太菜
class Solution: def preorderTraversal(self, root: TreeNode) -> List[int]: list = [] self.preorderHelp(list,root) return list def preorderHelp(self,list,root): if root==None: return None else: list.append(root.val) self.preorderHelp(list,root.left) self.preorderHelp(list,root.right)
非递归,使用栈。先压右子树再压左子树
class Solution: def preorderTraversal(self, root: TreeNode) -> List[int]: result = [] stack = [root,] if root==None: return result while(stack): root = stack.pop() result.append(root.val) if root.right!=None: stack.append(root.right) if root.left!=None: stack.append(root.left) return result
中序遍历
链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
递归方法:
class Solution: def inorderTraversal(self, root: TreeNode) -> List[int]: result = [] self.inordefHelper(result,root) return result def inordefHelper(self,result,root): if root==None: return self.inordefHelper(result,root.left) result.append(root.val) self.inordefHelper(result,root.right)
非递归采用两层循环:按照根节点左子树顺序压栈,然后再改变指针,对右子树采用同样的方法
class Solution: def inorderTraversal(self, root: TreeNode) -> List[int]: result = [] stack = [] if root==None: return [] while(stack or root!=None): while(root!=None): stack.append(root) root = root.left root = stack.pop() result.append(root.val) root = root.right return result
后序遍历:
链接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal/submissions/
递归写法
class Solution: def postorderTraversal(self, root: TreeNode) -> List[int]: result = [] if root==None: return result self.postHelper(result,root) return result def postHelper(self,result,root): if root==None: return self.postHelper(result,root.left) self.postHelper(result,root.right) result.append(root.val)
非递归写法:(对已经访问过的右子树做标记,根据后续的特点,若访问过右子树肯定根节点的右节点是刚被访问过的,用指针添加新的节点),不明白的话看参考链接哦
class Solution: def postorderTraversal(self, root: TreeNode) -> List[int]: result = [] stack = [] pre = None if root==None: return result while(stack or root!=None): while(root!=None): stack.append(root) root = root.left root = stack[-1] if root.right==None or root.right==pre: root = stack.pop() result.append(root.val) pre = root root = None else: root = root.right return result
针对后序遍历还有个简化方法
双栈法
前序遍历比较简单,因为是先访问根
1.用一个栈实现 根->右->左 的遍历
2.用另一个栈将遍历顺序反过来,使之变成 左->右->根
实现代码:
class Solution: def postorderTraversal(self, root: TreeNode) -> List[int]: result = [] stack1 = [root,] stack2 = [] if root == None: return [] while(stack1): root = stack1.pop() stack2.append(root) if root.left!=None: stack1.append(root.left) if root.right!=None: stack1.append(root.right) while(stack2): root = stack2.pop() result.append(root.val) return result
双栈简化:直接每次插入时将元素插入到头部class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
result = []
stack1 = [root,]
stack2 = []
if root == None:
return []
while(stack1):
root = stack1.pop()
result.insert(0,root.val)
if root.left!=None:
stack1.append(root.left)
if root.right!=None:
stack1.append(root.right)
return result