目录
前言
在刷剑指offer树的题,还挺吃力的。
先把这几种遍历写一遍!
注意单词:preorder 是先序, postorder是后续, 中序是inorder
我的测试树:
测试代码:
// 构造二叉树,返回根节点
public static TreeNode treeSet() {
TreeNode root = new TreeNode(1);
TreeNode a = new TreeNode(2);
TreeNode b = new TreeNode(3);
TreeNode c = new TreeNode(4);
TreeNode d = new TreeNode(5);
TreeNode e = new TreeNode(6);
TreeNode f = new TreeNode(7);
TreeNode g = new TreeNode(8);
root.left = a;
root.right = b;
a.left = c;
c.right = f;
b.left = d;
b.right = e;
e.left = g;
return root;
}
/**
* @author :pmdream
* @description : TreeNode
* @create : 2020/06/15
*/
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
递归
先序(preorder)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
// 递归实现
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
preorder(root, res);
return res;
}
public void preorder(TreeNode root, List<Integer> res) {
if (root == null) {
return;
}
res.add(root.val);
preorder(root.left, res);
preorder(root.right, res);
}
}
其实会写一个,剩下的都一样,树的简单遍历还是递归简单~
中序(inorder)
class Solution {
// 输出一个list
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);
}
}
后序(postorder)
class Solution {
// 输出一个list
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);
}
}
迭代
先序
/**
* 迭代,先序遍历
* 官方使用了: Deque 队列
* */
public List<Integer> preorderTraversal_1(TreeNode root) {
// 结果集
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
// 使用一个stack, 利用栈的特性,先进后出
Deque<TreeNode> stack = new LinkedList<TreeNode>();
TreeNode node = root;
while (!stack.isEmpty() || node != null) {
while (node != null) {
// 放中间节点
res.add(node.val);
stack.push(node);
// 放入左边的节点
node = node.left;
}
node = stack.pop();
// 放入右边的节点
node = node.right;
}
return res;
}
中序
/**
* 中序遍历,主要利用栈的特性,挺巧妙的
* */
public List<Integer> inorderTraversal_1(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
Deque<TreeNode> stk = new LinkedList<TreeNode>();
while (root != null || !stk.isEmpty()) {
while (root != null) {
stk.push(root);
root = root.left;
}
root = stk.pop();
res.add(root.val);
root = root.right;
}
return res;
}
后序
/**
* 后续遍历
* */
public List<Integer> postorderTraversal_1(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
// 维护这个栈
Deque<TreeNode> stack = new LinkedList<TreeNode>();
TreeNode prev = null;
while (root != null || !stack.isEmpty()) {
while (root != null) {
// 先放到站里面,遍历左边的节点
stack.push(root);
root = root.left;
}
// 到头了,然后pop一个,处理右边的节点
root = stack.pop();
// if可能这个是一个单个的节点
// root.right == prev, root.right == prev 说明回溯到上一个根节点了。
if (root.right == null || root.right == prev) {
res.add(root.val);
// pre 是上一个节点,因为这个比较的是root.right ,所以prev就是上一次的root
prev = root;
// 让root为0 ,因为右子树也没东西了,需要往上面回溯
root = null;
} else {
//有右节点,就push到stack中,然后循环操作就好
stack.push(root);
root = root.right;
}
}
return res;
}
层级遍历
需要注意一道题,就是把二叉树的某一个层级翻转,然后返回头节点;
/**
* 树的层级遍历
* 这个树是什么样的
* 结合队列就很好截出来这道题
*
* */
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;
}
public static void main(String[] args) {
LevelOrder102 levelOrder = new LevelOrder102();
TreeNode root = treeSet();
List<List<Integer>> result = levelOrder.levelOrder(root);
System.out.println();
}
// 构造二叉树,返回根节点
public static TreeNode treeSet() {
TreeNode root = new TreeNode(1);
TreeNode a = new TreeNode(2);
TreeNode b = new TreeNode(3);
TreeNode c = new TreeNode(4);
TreeNode d = new TreeNode(5);
TreeNode e = new TreeNode(6);
TreeNode f = new TreeNode(7);
TreeNode g = new TreeNode(8);
root.left = a;
root.right = b;
a.left = c;
c.right = f;
b.left = d;
b.right = e;
e.left = g;
return root;
}