给定一个二叉树,返回它的前序、中序 和后序遍历。
示例:
输入: [1,null,2,3]
1
\
2
/
3
输出:
前序:[1,2,3]
中序:[1,3,2]
后序:[3,2,1]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
本文使用三种方法来实现。
一、方法一 递归
首先使用递归算法,就像上面所说,非常简单,几行代码搞定。
前序遍历:
class Solution:
def preorderTraversal(self, root):
self.res = []
self.dec(root)
return self.res
def dec(self,root):
if root:
self.res.append(root.val)
self.dec(root.left)
self.dec(root.right)
中序遍历:
class Solution:
def inorderTraversal(self, root):
self.res = []
self.dec(root)
return self.res
def dec(self,root):
if root:
self.dec(root.left)
self.res.append(root.val)
self.dec(root.right)
后序遍历:
class Solution:
def postorderTraversal(self, root):
self.res = []
self.dec(root)
return self.res
def dec(self,root):
if root:
self.dec(root.left)
self.dec(root.right)
self.res.append(root.val)
二、方法二 借助栈的迭代
对比上面三种遍历的递归算法代码,只是改变了遍历的顺序,很好理解。
下面是迭代算法。巧妙利用栈的特点,便能很好实现目的。
前序遍历:
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
"""
搜索到最左边,节点依次放进栈,搜索的同时将遍历的节点值放入结果数组
"""
stack = []
res = []
while root or stack:
if root:
res.append(root.val)
stack.append(root)
root = root.left
else:
root = stack.pop()
root = root.right
return res
中序遍历:
class Solution:
def inorderTravelsal(self, root: TreeNode) -> List[int]:
"""
搜索到最左边,节点依次放进栈,
"""
stack, res = [], []
while root or stack:
if root:
stack.append(root)
root = root.left
else:
root = stack.pop()
res.append(root.val)
root = root.right
return res
后序遍历:
class Solution:
def postorderTravelsal(self, root: TreeNode) -> List[int]:
"""
对前序遍历进行稍微改造,变成"根-右-左"的顺序进行遍历,将得到的列表进行反转,便得到了后序遍历
"""
stack, res = [], []
while root or stack:
if root:
res.append(root.val)
stack.append(root)
root = root.right
else:
root = stack.pop()
root = root.left
return res[::-1]
三、方法三 Morris遍历算法
对于x节点,如果有左子树
找到左子树的最右节点,为x的前驱节点 predecessor,根据 predecessor 的右节点是否存在,
1 右节点为空,则右指向x,并访问x的左节点,x = x.left
2 右节点不为空,则说明左子树已经访问完了,结果集中添加x,断开链接,并访问x的右子树,x = x.right
否则
将x添加到结果集中,在访问x的右孩子,即 x = x.left
前序遍历:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
TreeNode predecessor;
while (root != null) {
if (root.left != null) {
predecessor = root.left;
while (predecessor.right != null && predecessor.right != root) {
predecessor = predecessor.right;
}
if (predecessor.right == null) {
res.add(root.val);
predecessor.right = root;
root = root.left;
} else {
predecessor.right = null;
root = root.right;
}
} else {
res.add(root.val);
root = root.right;
}
}
return res;
}
}
中序遍历
public class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
TreeNode predecessor = null;
while (root != null) {
if (root.left != null) {
predecessor = root.left;
// predecessor不为null,并且前驱的右不是root
while (predecessor.right != null && predecessor.right != root) {
predecessor = predecessor.right;
}
// 让 predecessor 的右指针指向root,继续遍历子树
if (predecessor.right == null) {
predecessor.right = root;
root = root.left;
} // 说明左子树已经访问完了,需要断开链接
else {
res.add(root.val);
predecessor.right = null;
root = root.right;
}
}
// 没有左孩子,则直接访问右孩子
else {
res.add(root.val);
root = root.right;
}
}
return res;
}
}
后序遍历:
public class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
TreeNode predecessor;
while (root != null) {
predecessor = root.right;
if (root.right != null) {
while (predecessor.left != null && predecessor.left != root) {
predecessor = predecessor.left;
}
if (predecessor.left == null) {
res.add(root.val);
predecessor.left = root;
root = root.right;
} else {
predecessor.left = null;
root = root.left;
}
} else {
res.add(root.val);
root = root.left;
}
}
Collections.reverse(res);
return res;
}
}
-------------------------------------------------------------------------------------------------------------------------------------
更多题目包括leetcode、牛客网、各种排序算法解法参见个人GitHub,持续更新中,欢迎star ~~
https://github.com/PemLer/Journey_of_leetcode
-------------------------------------------------------------------------------------------------------------------------------------