有两种通用的遍历树的策略:
- 深度优先搜索(DFS)
在这个策略中,我们采用深度作为优先级,以便从根开始一直到达某个确定的叶子,然后再返回根到达另外一个分支。深度优先又细分为- 后序遍历: 访问根节点的操作在左右孩子之后
- 前序遍历: 访问根节点的操作在左右孩子之前
- 中序遍历: 访问根节点的操作在左右孩子之中
- 广度优先搜索(BFS)
按照高度顺序一层层的访问整棵树,高层次的结点将会比低层次的结点先被访问到。
下面是一张示意图,树上的结点按照访问顺序来编号。
后序遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
// 反过来的前序遍历
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
LinkedList<Integer> output = new LinkedList<Integer>();
if(root == null){
return output;
}
stack.add(root);
while(!stack.isEmpty()){
TreeNode node = stack.pollLast();
output.addFirst(node.val);
if(node.left != null){
stack.add(node.left);
}
if(node.right != null){
stack.add(node.right);
}
}
return output;
}
}
// 记录结点是否被访问过的后序遍历
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
Deque<TreeNode> stack = new LinkedList<>();
Deque<Integer> flag = new LinkedList<>();
TreeNode p = root;
List<Integer> res = new ArrayList<>();
while (p != null || !stack.isEmpty()) {
while (p != null) {
flag.push(0);
stack.push(p);
p = p.left;
}
while (!stack.isEmpty() && flag.peek() == 1) {
flag.pop();
res.add(stack.pop().val);
}
if (!stack.isEmpty()) {
flag.pop();
flag.push(1);
p = stack.peek().right;
}
}
return res;
}
}
前序遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
LinkedList<Integer> output = new LinkedList<Integer>();
if(root == null){
return output;
}
stack.add(root);
while(!stack.isEmpty()){
TreeNode node = stack.pollLast();
output.add(node.val);
if(node.right!=null){
stack.add(node.right);
}
if(node.left!=null){
stack.add(node.left);
}
}
return output;
}
}
中序遍历
中序遍历递归解法
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if(root == null){
return res;
}
helper(root, res);
return res;
}
public void helper(TreeNode root, List<Integer> res){
if(root.left != null){
helper(root.left, res);
}
res.add(root.val);
if(root.right != null){
helper(root.right, res);
}
}
}基于栈的遍历
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
LinkedList<TreeNode> stack = new LinkedList<>();
List<Integer> res = new ArrayList<>();
TreeNode curr = root;
while(curr != null || !stack.isEmpty()){
while(curr != null){
stack.push(curr);
curr = curr.left;
}
curr = stack.pop();
res.add(curr.val);
curr = curr.right;
}
return res;
}
}
层次遍历
层次遍历递归解法
class Solution {
List<List<Integer>> levels = new ArrayList<List<Integer>>();
public void helper(TreeNode node, Integer level){
if(levels.size() == level){
levels.add(new ArrayList<Integer>());
}
levels.get(level).add(node.val);
if(node.left != null){
helper(node.left, level+1);
}
if(node.right != null){
helper(node.right, level+1);
}
}
public List<List<Integer>> levelOrder(TreeNode root) {
if(root == null){
return levels;
}
helper(root, 0);
return levels;
}
}层次遍历迭代解法
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> levels = new ArrayList<List<Integer>>();
if(root == null) return levels;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
int level = 0;
while( !queue.isEmpty() ){
// 开始当前层次
levels.add(new ArrayList<Integer>());
// 当前层次的元素数量
int level_length = queue.size();
for(int i=0; i<level_length; ++i){
TreeNode node = queue.remove();
// 把当前层次的元素都放入返回数组中
levels.get(level).add(node.val);
// 添加当前层次的孩子结点到队列中为下一层次做准备
if(node.left != null){
queue.add(node.left);
}
if(node.right != null){
queue.add(node.right);
}
}
// 进行下一层次
level++;
}
return levels;
}
}