前、中、后序遍历
题目描述
分别按照二叉树先序,中序和后序打印所有的节点。
示例1
输入
{1,2,3}
返回值
[[1,2,3],[2,1,3],[2,3,1]]
备注:
n \leq 10^6n≤106
解题思路
新建栈并将数根进栈
前序遍历:
- while(栈不空):1.弹栈顶并输出 2.有右子树右子树进栈 3.有左子树左子树进栈
中序遍历:
- 新建visited集合,记录已经从栈中弹出并打印的节点
- while(栈不空):1. 取栈顶元素(不弹出)。2.如果栈顶元素有没被访问过的左子树就将左子树压栈,否则弹栈并输出并将右子树压栈(如果有)
后续遍历:
- 新建visited集合,记录已经从栈中弹出并打印的节点
- while(栈不空):1. 取栈顶元素(不弹出)。2.尝试将栈顶节点的左、右子树压栈【压栈条件,存在且没被访问过】3.尝试弹栈【弹栈条件,栈顶元素的左右子树要么不存在要么被访问过】
import java.util.*;
/**
* @author SJ
* @date 2021/4/4
*/
public class TraversingBinaryTree {
public static class TreeNode {
public int val = 0;
public TreeNode left = null;
public TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
/**
*
* @param root TreeNode类 the root of binary tree
* @return int整型二维数组
*/
public int[][] threeOrders (TreeNode root) {
List<Integer> listPre = preOrder(root);
List<Integer> listIn = inOrder(root);
List<Integer> listPost = postOrder(root);
int size = listIn.size();
int[][] ints = new int[3][size];
for (int i = 0; i < size; i++) {
ints[0][i]=listPre.get(i);
ints[1][i]=listIn.get(i);
ints[2][i]=listPost.get(i);
}
return ints;
}
//先根遍历
public List<Integer> preOrder(TreeNode node){
List<Integer> ans=new ArrayList<>();
Deque<TreeNode> stack=new ArrayDeque<>();
stack.push(node);
while (!stack.isEmpty()){
//弹出栈顶元素并输出
TreeNode pop = stack.pop();
ans.add(pop.val);
//先进右子树,后进左子树,时为了到时候左子树先出
if (pop.right!=null)
stack.push(pop.right);
if (pop.left!=null)
stack.push(pop.left);
}
return ans;
}
//中根遍历
public List<Integer> inOrder(TreeNode node){
List<Integer> ans=new ArrayList<>();
Deque<TreeNode> stack=new ArrayDeque<>();
Set<TreeNode> visited=new HashSet<>();
stack.push(node);
while (!stack.isEmpty()){
TreeNode peek = stack.peek();
//如果有左子树就进左子树
if (peek.left!=null&&!visited.contains(peek.left))
stack.push(peek.left);
else {//没有左子树就输出并弹出栈顶元素,并将栈顶元素的右子树压栈
TreeNode pop = stack.pop();
visited.add(pop);
ans.add(pop.val);
if (pop.right!=null)
stack.push(pop.right);
}
}
return ans;
}
//后根遍历
public List<Integer> postOrder(TreeNode node){
List<Integer> ans=new ArrayList<>();
Deque<TreeNode> stack=new ArrayDeque<>();
Set<TreeNode> visited=new HashSet<>();
stack.push(node);
while (!stack.isEmpty()){
//每次取栈顶元素,尝试将右子树和左子树压入栈
TreeNode peek = stack.peek();
TreeNode right = peek.right;
TreeNode left = peek.left;
if (right!=null&&!visited.contains(right))
stack.push(right);
if (left!=null&&!visited.contains(left))
stack.push(left);
//一个节点能输出,当且仅当这个节点的子树都无法被输出
if ((right==null||visited.contains(right))&&(left==null||visited.contains(left))){
TreeNode pop = stack.pop();
ans.add(pop.val);
visited.add(pop);
}
}
return ans;
}
public static void main(String[] args) {
TreeNode n1 = new TreeNode(1);
TreeNode n2 = new TreeNode(2);
TreeNode n3 = new TreeNode(3);
n1.left=n2;
n1.right=n3;
TraversingBinaryTree traversingBinaryTree = new TraversingBinaryTree();
traversingBinaryTree.threeOrders(n1);
}
}
层次遍历
题目描述
给定一个二叉树,返回该二叉树层序遍历的结果,(从左到右,一层一层地遍历)
例如:
给定的二叉树是{3,9,20,#,#,15,7},
该二叉树层序遍历的结果是
[
[3],
[9,20],
[15,7]
]
解题思路
其实普通的层次遍历很简单,一个队列就可以完成。这个有点特殊,需要每层输出一个结果数组,此时就要区分这个节点时哪一层的了。
新建两个队列:队列1和队列2
- 1.将根节点加入队列1
- 2.遍历队列1,同时将遍历到节点的左右子树加入队列2
- 3.遍历完之后,队列1已空,将队列1和队列2交换名称
- 重复2,3 直至队列1空
import java.util.*;
/**
* @author SJ
* @date 2021/4/4
*/
public class LevelOrder {
public static class TreeNode {
public int val = 0;
public TreeNode left = null;
public TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
/**
* @param root TreeNode类
* @return int整型ArrayList<ArrayList <>>
*/
public ArrayList<ArrayList<Integer>> levelOrder(TreeNode root) {
ArrayList<ArrayList<Integer>> ans = new ArrayList<>();
if (root == null)
return ans;
Deque<TreeNode> queue1 = new ArrayDeque<>();
Deque<TreeNode> queue2 = new ArrayDeque<>();
queue1.add(root);
int layer = 0;
//两个队列来回倒,每次队列里装一层,另一个队列里装这一层的子节点
while (!queue1.isEmpty()) {
ans.add(new ArrayList<>());
while (!queue1.isEmpty()) {
TreeNode poll = queue1.poll();
ans.get(layer).add(poll.val);
if (poll.left != null)
queue2.add(poll.left);
if (poll.right != null)
queue2.add(poll.right);
}
Deque<TreeNode> temp;
temp = queue1;
queue1 = queue2;
queue2 = temp;
layer++;
}
return ans;
}
public static void main(String[] args) {
TreeNode n1 = new TreeNode(1);
TreeNode n2 = new TreeNode(2);
TreeNode n3 = new TreeNode(3);
n1.left = n2;
n1.right = n3;
LevelOrder levelOrder = new LevelOrder();
ArrayList<ArrayList<Integer>> arrayLists = levelOrder.levelOrder(n1);
for (ArrayList<Integer> arrayList : arrayLists) {
System.out.println(arrayList.toString());
}
}
}
之字形遍历
题目描述
给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替)
例如:
给定的二叉树是{3,9,20,#,#,15,7},
该二叉树之字形层序遍历的结果是
[
[3],
[20,9],
[15,7]
]
解题思路
之字形遍历,层次遍历结果集里奇数层倒着插就行,哪有那么复杂。
if (layer%2 == 0)
ans.get(layer).add(poll.val);
else
ans.get(layer).add(0, poll.val);