前序遍历
- 前序遍历顺序为:依次遍历根节点、左子节点、右子节点。在访问子节点的时候,依旧是这个顺序,不断的重复此过程,就可以用递归实现。
递归遍历
- 树的递归遍历,其实就添加节点值的语句的位置不同,其他都相同。所以前中后序递归遍历都是一个模板,只需要知道添加节点值的语句在哪就行。
- 前序:先遍历根节点,自然先添加根节点的值。所以添加节点值的语句放在遍历子节点前边。
- 中序:同理,放在遍历左子节点之后。
- 后序:同理,放在遍历右子节点之后。
class Solution {
List<Integer> list = new ArrayList<>(); //直接在类成员变量的位置声明list
public List<Integer> preorderTraversal(TreeNode root) {
if(root == null) return list;
list.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
return list;
}
}
或:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>(); //在方法中声明list;
preTraversal(root, list);
return list;
}
public void preTraversal(TreeNode node, List<Integer> list){
if(node == null) return;
list.add(node.val);
preTraversal(node.left, list);
preTraversal(node.right, list);
}
}
迭代遍历
- 迭代遍历需要注意的一个点就是,当我们遍历到叶子节点,如何返回父节点,继续遍历父节点的右侧节点。这里我们用栈来解决这个问题。
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>(); //栈用来存储父节点,当父节点无子节点时,出栈返回父节点
List<Integer> list = new ArrayList<>();
TreeNode cur = root;
while(cur != null || !stack.empty() )
{
if(cur != null){
list.add(cur.val); // root
stack.push(cur);
cur = cur.left; // left
}else{
cur = stack.pop();
cur = cur.right; //right
}
}
return list;
}
}
中序遍历
- 中序遍历顺序为:依次遍历左子节点,根节点,右子节点。在访问子节点的时候,依旧是这个顺序,不断的重复此过程,就可以用递归实现。
递归代码
class Solution {
List<Integer> list = new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
if(root == null) return list;
inorderTraversal(root.left);
list.add(root.val);
inorderTraversal(root.right);
return list;
}
}
或:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
inorder(root, res);
return res;
}
public void inorder(TreeNode root, List<Integer> res) {
if (root == null) {
return;
}
inorder(root.left, res);
res.add(root.val);
inorder(root.right, res);
}
}
迭代遍历
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while(cur != null || !stack.empty()){
if(cur != null){
stack.push(cur);
cur = cur.left;
}
else{
cur = stack.pop();
list.add(cur.val);
cur = cur.right;
}
}
return list;
}
}
后序遍历
- 后续遍历:依次遍历左子节点,右子节点,根节点。
- 后续遍历迭代法:
- 前序遍历:根 - > 左 - > 右
- 后序遍历:左 - > 右 - > 根
- 后续遍历可以根据前序遍历稍作修改,根 - > 右 - > 左,之后结果放到栈中,进行倒序,之后再遍历结果栈就可以输出后序遍历了。
递归代码
class Solution {
List<Integer> list = new ArrayList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if(root == null) return list;
postorderTraversal(root.left);
postorderTraversal(root.right);
list.add(root.val);
return list;
}
}
或:
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
postorder(root, res);
return res;
}
public void postorder(TreeNode root, List<Integer> res) {
if (root == null) {
return;
}
postorder(root.left, res);
postorder(root.right, res);
res.add(root.val);
}
}
迭代遍历
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
Stack<TreeNode> resStack = new Stack<>();
List<Integer> list = new ArrayList<>();
TreeNode cur = root;
while(cur != null || !stack.empty()){
if(cur != null){
stack.push(cur);
resStack.push(cur);
cur = cur.right;
}else{
cur = stack.pop();
cur = cur.left;
}
}
while(!resStack.empty()){
list.add(resStack.pop().val);
}
return list;
}
}
层次遍历
- 其实层次遍历就是对BFS(广度优先遍历)的修改,BFS每次只取一个元素进行扩展,而层次遍历每次是取S(S为一层节点的个数)个元素进行扩展。
- 这里使用队列来存储层次遍历的节点。
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ret = new ArrayList<List<Integer>>();
if (root == null) {
return ret;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
while (!queue.isEmpty()) {
List<Integer> level = new ArrayList<Integer>();
int currentLevelSize = queue.size();
for (int i = 1; i <= currentLevelSize; ++i) {
TreeNode node = queue.poll();
level.add(node.val);
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
ret.add(level);
}
return ret;
}
}