所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题。遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。
遍历方式分别为:先序遍历、中序遍历、后序遍历。
遍历之前,我们先来创建一棵树。
首先要声明结点TreeNode类,代码如下:
public class TreeNode {
private int val;
private TreeNode left;
private TreeNode right;
public TreeNode() {
}
public TreeNode(int val) {
this.val = val;
}
public TreeNode(int val,TreeNode left,TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
// 省略get、set
}
随机创建一个tree
public class TreeBuilder {
/**
* 1
* / \
* 2 3
* / \ / \
* 4 5 6 7
* / \
* 8 9
* @return
*/
public static TreeNode randomBuild() {
TreeNode node8 = new TreeNode(8);
TreeNode node9 = new TreeNode(9);
TreeNode node7 = new TreeNode(7);
TreeNode node6 = new TreeNode(6,null,node9);
TreeNode node5 = new TreeNode(5);
TreeNode node4 = new TreeNode(4,node8,null);
TreeNode node3 = new TreeNode(3,node6,node7);
TreeNode node2 = new TreeNode(2,node4,node5);
TreeNode node1 = new TreeNode(1,node2,node3);
return node1;
}
}
使用递归的方式进行遍历
public class TreePrint1 {
public static void main(String[] args) {
TreeNode head = TreeBuilder.randomBuild();
System.out.println("preorderTraversal");
preorderTraversal(head);
System.out.println("\n\ninorderTraversal");
inorderTraversal(head);
System.out.println("\n\npostorderTraversal");
postorderTraversal(head);
}
/**
* 二叉树前序遍历 根-> 左-> 右
*/
private static void preorderTraversal(TreeNode head) {
if (head == null) {
return;
}
System.out.print(head.getVal() + " ");
preorderTraversal(head.getLeft());
preorderTraversal(head.getRight());
}
/**
* 二叉树中序遍历 左-> 根-> 右
*/
private static void inorderTraversal(TreeNode head) {
if (head == null) {
return;
}
inorderTraversal(head.getLeft());
System.out.print(head.getVal() + " ");
inorderTraversal(head.getRight());
}
/**
* 二叉树后序遍历 左-> 右-> 根
*/
private static void postorderTraversal(TreeNode head) {
if (head == null) {
return;
}
postorderTraversal(head.getLeft());
postorderTraversal(head.getRight());
System.out.print(head.getVal() + " ");
}
}
使用非递归的方式进行遍历
public class TreePrint2 {
public static void main(String[] args) {
TreeNode head = TreeBuilder.randomBuild();
System.out.println("preorderTraversal");
preorderTraversal(head);
System.out.println("\n\ninorderTraversal");
inorderTraversal(head);
System.out.println("\n\npostorderTraversal");
postorderTraversal(head);
}
/**
* 二叉树前序遍历 根-> 左-> 右
*/
private static void preorderTraversal(TreeNode head) {
if (head == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode node = head;
while (node != null || !stack.isEmpty()) {
while (node != null) {
System.out.print(node.getVal() + " ");
stack.push(node);
node = node.getLeft();
}
if (!stack.isEmpty()) {
node = stack.pop().getRight();
}
}
}
/**
* 二叉树中序遍历 左-> 根-> 右
*/
private static void inorderTraversal(TreeNode head) {
if (head == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode node = head;
while (node != null || !stack.isEmpty()) {
while (node != null) {
stack.push(node);
node = node.getLeft();
}
if (!stack.isEmpty()) {
node = stack.pop();
System.out.print(node.getVal() + " ");
node = node.getRight();
}
}
}
/**
* 二叉树后序遍历 左-> 右-> 根
*/
private static void postorderTraversal(TreeNode head) {
if (head == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode node = head; // 当前根节点
TreeNode last = null; // 上一次打印的节点
while (node != null || !stack.isEmpty()) {
while (node != null) {
stack.push(node);
node = node.getLeft();
}
if (!stack.isEmpty()) {
node = stack.pop();
/*
没有右节点,当前节点可以打印了
当前节点的右节点就是上一次打印的节点,当前节点可以打印了
“node = null”表示当前节点的这个分支不能再处理了,因为外层循环是“node = node.getLeft()”
*/
if (node.getRight() == null || node.getRight() == last) {
System.out.print(node.getVal() + " ");
last = node;
node = null;
}else {
stack.add(node);
node = node.getRight();
}
}
}
}
}