二叉树的遍历方法汇总
1. 二叉树的前序遍历
题解一:递归
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
recurPreorder(root, res);
return res;
}
public void recurPreorder(TreeNode root, List<Integer> res) {
if (root == null) {
return;
}
res.add(root.val);
recurPreorder(root.left, res);
recurPreorder(root.right, res);
}
}
复杂度分析
- 时间复杂度:O(n) ,其中n 是二叉树的节点数。每个节点都恰好被遍历一遍。
- 空间复杂度:O(n) ,为递归过程中栈的开销,平均情况下为O(logn),最坏情况下为O(n)。
题解二:非递归
前序遍历的遍历顺序是“根左右”,所以有以下思路。
算法思路:
- 令一个node 指向root ,开始遍历树
- 如果node 不为空,将其入栈,添加其值到列表中,并指向其左子节点。
- 如果node 为空说明左子树已经遍历到底,将node 赋值为stack 的弹栈,然后令node 指向其右节点。
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
Deque<TreeNode> stack = new LinkedList<>();
TreeNode node = root;
while (node != null || !stack.isEmpty()) {
while (node != null) {
list.add(node.val);
stack.push(node);
node = node.left;
}
node = stack.pop();
node = node.right;
}
return list;
}
}
2. 二叉树的中序遍历
题解一:递归
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
recurInorder(root, list);
return list;
}
public void recurInorder(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
recurInorder(root.left, list);
list.add(root.val);
recurInorder(root.right, list);
}
}
题解二:非递归
左根右
算法思路:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
Deque<TreeNode> stack = new LinkedList<>();
TreeNode node = root;
while (node != null || !stack.isEmpty()) {
while (node != null) {
stack.push(node);
node = node.left;
}
node = stack.pop();
list.add(node.val);
node = node.right;
}
return list;
}
}
3. 二叉树的后序遍历
题解一:递归
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
recurPostorder(root, list);
return list;
}
public void recurPostorder(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
recurPostorder(root.left, list);
recurPostorder(root.right, list);
list.add(root.val);
}
}
题解二:非递归
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if (root == null) {
return list;
}
Deque<TreeNode> stack = new LinkedList<>();
TreeNode pre = null;
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
if (root.right == null || root.right == pre) {
list.add(root.val);
pre = root;
root = null;
} else {
stack.push(root);
root = root.right;
}
}
return list;
}
}
算法思路:与前序遍历的非递归实现思路相似。后序遍历的遍历顺序是“左右根”,那么我们只需用类似前序遍历的算法,顺序是“根右左”,然后利用集合的reverse 将整个集合颠倒就变成了“左右根”,也就是后序遍历。
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
//左 右 根 <== 先访问 根 右 左 反转 (即和前序异曲同工)
while (root != null || !stack.isEmpty()) {
while (root != null) {
list.add(root.val);
stack.push(root);
root = root.right;//和前序的差异,前序是向左走
}
TreeNode node = stack.pop();
root = node.left;//和前序的差异
}
Collections.reverse(list);
return list;
}
}
Collections.reverse(list) : 翻转list 列表。
4.二叉树的层序遍历
题解
利用队列,完成二叉树的层次遍历,算法思路:
- 如果根节点不为空则入队,否则直接返回一个空数组;
- 在队列不为空的情况下,将节点出队,并将节点的值记录到List 集合中;
- 分别判断出队节点的左右儿子是否为空,不为空的入队;
- 重复2、3 直至队列为空
- 将集合遍历放到结果数组中,输出结果。
class Solution {
public int[] levelOrder(TreeNode root) {
if (root == null) return new int[0];
Deque<TreeNode> queue = new LinkedList<>();
List<Integer> list = new ArrayList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
list.add(node.val);
if (node.left != null) queue.add(node.left);
if (node.right != null) queue.add(node.right);
}
int[] res = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
res[i] = list.get(i);
}
return res;
}
}

浙公网安备 33010602011771号