前言:
前序,中序和后序遍历都是深度优先遍历的特例
深度优先和广度优先是针对普通树的,
但是先序,中序和后序都是针对二叉树的。
使用递归和迭代(借用栈)实现二叉树先序,中序,后序遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
1.二叉树先序遍历
1.1递归
public class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
if(root != null) {
list.add(root.val);
list.addAll(preorderTraversal(root.left));
list.addAll(preorderTraversal(root.right));
}
return list;
}
}
1.2迭代
/*
维护一个栈,将根节点入栈,然后只要栈不为空,出栈并访问,
接着依次将访问节点的右节点、左节点入栈。
类似于图的深度优先遍历DFS
但是这种方式 没有良好的扩展性,在中序和后序方法中不适用
*/
public class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
if(root == null) {
return list;
}
stack.push(root);
while(!stack.isEmpty()) {
TreeNode node = stack.pop();
list.add(node.val);
if(node.right != null) {
stack.push(node.right);
}
if(node.left != null) {
stack.push(node.left);
}
}
return list;
}
}
1.3迭代-2
/*
利用栈模拟递归过程实现先序遍历二叉树
左子树点不断的压入栈,直到null,然后处理栈顶节点的右子树
但是这种方式有良好的扩展性
*/
public class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
while(root != null || !stack.isEmpty()) {
//左子树点不断的压入栈
while(root != null) {
//先访问后入栈
list.add(root.val);
stack.push(root);
root = root.left;
}
root = stack.pop();
root = root.right;
}
return list;
}
}
2.二叉树中序遍历
2.1递归
public class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
if(root != null) {
list.addAll(inorderTraversal(root.left));
list.add(root.val);
list.addAll(inorderTraversal(root.right));
}
return list;
}
}
2.2迭代
/*
利用栈模拟递归过程实现先序遍历二叉树
左子树点不断的压入栈,且入栈后访问,相当于模拟递归的先访问左子树,才是根节点,直到null,然后处理栈顶节点的右子树
但是这种方式有良好的扩展性
*/
public class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
while(root != null || !stack.isEmpty()) {
while(root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
list.add(root.val);
root = root.right;
}
return list;
}
}
3.二叉树后序遍历
3.1递归
public class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
if(root != null) {
list.addAll(postorderTraversal(root.left));
list.addAll(postorderTraversal(root.right));
list.add(root.val);
}
return list;
}
}
3.2迭代
/*后序遍历不同于先序和中序,需要先处理完左右子树,才处理根节点,
所以需要一个map来记录那些节点已经被访问*/