树是一种非线性的结构,叫做树是它的结构看起来像一颗倒挂的树。一个结点由一个根节点加上左右子树便成为了二叉树。二叉树在树的有着很重要的位置。大多数题目都是基于二叉树的。
本文主要分享二叉树的几个遍历方式,概念只做简单介绍。二叉树的几个遍历方式如下:
// 前序遍历(递归)
void preOrder(TreeNode root);
// 中序遍历(递归)
void inOrder(TreeNode root);
// 后序遍历(递归)
void postOrde(TreeNode root);
//前序遍历(非递归)
public List<Integer> preorderTraversal(TreeNode root);
//中序遍历(非递归)
public List<Integer> inorderTraversal(TreeNode root);
//后序遍历(非递归)
public List<Integer> postorderTraversal(TreeNode root);
//层序遍历
public List<List<Integer>> levelOrder(TreeNode root);
前置说明
二叉树的表示方法很多,我们在做题的时候,常常使用孩子表示法。
class TreeNode {
int val;//数值域
TreeNode left;//左孩子(结点)的引用
TreeNode right;//右孩子(结点)的引用
public TreeNode(int val) {
this.val = val;
}
}
自己来创建一颗二叉树,比如下面的一个二叉树:
这里手动创建一个二叉树。
public void createTree() {
TreeNode A = new TreeNode(1);
TreeNode B = new TreeNode(2);
TreeNode C = new TreeNode(3);
TreeNode D = new TreeNode(4);
TreeNode E = new TreeNode(5);
TreeNode F = new TreeNode(6);
TreeNode G = new TreeNode(7);
A.left = B;
A.right = C;
B.left = D;
B.right = E;
C.left = F;
C.right = G;
}
1、前序遍历(递归)
前序遍历是一种根左右的遍历方式,在操作的时候,先对根进行操作,在遍历根的左,根的右。如果整个树是一颗空的树,直接返回,不需要操作。
public void preOrder(TreeNode root) {
//如果是空的结点,就返回
if (root == null) return;
//你的操作
System.out.print(root.val + " ");
//走树的左边
preOrder(root.left);
//走树的右边
preOrder(root.right);
}
2、中序遍历(递归)
中序遍历是一种左根右的遍历方式,在操作的时候,先遍历根的左,在对根进行操作,最后就是根的右。如果整个树是一颗空的树,直接返回,不需要操作。
void inOrder(TreeNode root) {
//如果是空的结点,就返回
if (root == null) return;
//先走树的左边
inOrder(root.left);
//你的操作
System.out.print(root.val + " ");
//走树的右边
inOrder(root.right);
}
3、后序遍历(递归)
后序遍历是一种左右根的遍历方式,在操作的时候,先遍历根的左,再就是根的右,最后对根进行操作。如果整个树是一颗空的树,直接返回,不需要操作。
void postOrder(TreeNode root) {
//如果是空的结点,就返回
if (root == null) return;
//先走树的左边
postOrder(root.left);
//走树的右边
postOrder(root.right);
//你的操作
System.out.print(root.val + " ");
}
下面的非递归的方式,是在模拟整个递归的过程。这个过程中使用了队列这个数据结构。在这里使用链表作为返回值,也可以不返回。
4、前序遍历(非递归)
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
Deque<TreeNode> stack = new LinkedList<>();
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;
}
5、中序遍历(非递归)
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if (root == null) return list;
Stack<TreeNode> queue = new Stack<>();
while (!queue.isEmpty() || root != null) {
while (root != null) {
queue.push(root);
root = root.left;
}
root = queue.pop();
list.add(root.val);
root = root.right;
}
return list;
}
6、后序遍历(非递归)
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode prev = null;
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
if (root.right == null || root.right == prev) {
res.add(root.val);
prev = root;
root = null;
} else {
stack.push(root);
root = root.right;
}
}
return res;
}
7、层序遍历
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ret = new ArrayList<>();
if (root == null) return ret;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
List<Integer> list = new ArrayList<>();
while (size > 0) {
TreeNode cur = queue.poll();
if (cur.left != null) {
queue.offer(cur.left);
}
if (cur.right != null) {
queue.offer(cur.right);
}
list.add(cur.val);
--size;
}
ret.add(list);
}
return ret;
}