import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;
/** * 定义节点类 * 为了简单就不定义getter/setter方法了 */
class Node {
public int value;
public Node left;
public Node right;
public Node() {
this(0);
}
public Node(int v) {
this.value = v;
this.left = null;
this.right = null;
}
}
/** * 对二叉树进行操作的工具类 */
class PrintBinaryTree {
private PrintBinaryTree(){
throw new RuntimeException("该工具类不应该被实例化");
}
/** * 层序遍历二叉树(每一行从左到右,整体上从上到下) * 主要思路:利用队列先进先出的性质保存顺序 * @param root 要遍历的二叉树的根节点 */
public static void levelTraversal(Node root) {
Queue<Node> q = new LinkedList<>();
q.add(root);
while (!q.isEmpty()) {
Node temp = q.poll();
if (temp != null) {
System.out.print(temp.value + " ");
q.add(temp.left);
q.add(temp.right);
}
}
}
/** * 前序遍历二叉树(递归) root->left->right * @param root 要遍历的二叉树的根节点 */
public static void preOrderRec(Node root) {
if (root == null) {
return;
}
System.out.print(root.value + " ");
preOrderRec(root.left);
preOrderRec(root.right);
}
/** * 前序遍历二叉树(非递归) root->left->right * 主要思路:利用栈保存未打印的节点,然后逐个出栈处理,在此过程中更新栈 * @param root 要遍历的二叉树的根节点 */
public static void preOrderUnRec(Node root) {
Stack<Node> stack = new Stack<>();
stack.push(root);
Node temp;
while (!stack.empty()) {
temp = stack.pop();
if (temp != null) {
System.out.print(temp.value + " ");
stack.push(temp.right);
stack.push(temp.left);
}
}
}
/** * 后序遍历二叉树(递归) * @param root 要遍历的二叉树的根节点 */
public static void postOrderRec(Node root) {
if (root == null) {
return;
}
postOrderRec(root.left);
postOrderRec(root.right);
System.out.print(root.value + " ");
}
/** * 后序遍历二叉树(非递归) left->right->root * 主要思路:利用栈保存未打印的节点,然后逐个出栈,进行判断,并根据需要更新栈 * 因为是处理完左右子树后,再处理根(回溯),所以需要一个记录上一个被打印的节点的引用 * @param root 要遍历的二叉树的根节点 */
public static void postOrderUnRec(Node root) {
if (root == null) {
return;
}
Stack<Node> stack = new Stack<>();
stack.push(root);
Node cur, pre = null;
while (!stack.empty()) {
cur = stack.peek();
if ((cur.left == null && cur.right == null) ||
(pre != null && (pre == cur.left || pre == cur.right))) {
System.out.print(cur.value + " ");
stack.pop();
pre = cur;
} else {
if (cur.right != null)
stack.push(cur.right);
if (cur.left != null)
stack.push(cur.left);
}
}
}
/** * 中序遍历二叉树(递归) * @param root 要遍历的二叉树的根节点 */
public static void inOrderRec(Node root) {
if (root == null) {
return;
}
inOrderRec(root.left);
System.out.print(root.value + " ");
inOrderRec(root.right);
}
/** * 中序遍历二叉树(非递归) left->root->right * 主要思路:模拟递归的过程,将左子树节点不断的压入栈,直到左叶子,然后处理栈顶节点的右子树 * @param root 要遍历的二叉树的根节点 */
public static void inOrderUnRec(Node root) {
Stack<Node> stack = new Stack<>();
Node cur = root;
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
cur = stack.pop();
System.out.print(cur.value + " ");
cur = cur.right;
}
}
/** * 前序递归构造二叉树 root->left->right * @param scanner 输入流,用于读取节点值 * @return 构造完成的二叉树的根节点 */
public static Node createTreeNode(Scanner scanner) {
assert scanner!=null;
Node root = null;
int data = scanner.nextInt();
if (data > 0) {
root = new Node(data);
root.left = createTreeNode(scanner);
root.right = createTreeNode(scanner);
}
return root;
}
}
/** * 测试类 */
public class BinaryTree{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Node root = PrintBinaryTree.createTreeNode(sc);
sc.close();
System.out.print("层序遍历:");
PrintBinaryTree.levelTraversal(root);
System.out.print("\n中序递归遍历:");
PrintBinaryTree.inOrderRec(root);
System.out.print("\n中序非递归遍历:");
PrintBinaryTree.inOrderUnRec(root);
System.out.print("\n前序递归遍历:");
PrintBinaryTree.preOrderRec(root);
System.out.print("\n前序非递归遍历:");
PrintBinaryTree.preOrderUnRec(root);
System.out.print("\n后序递归遍历:");
PrintBinaryTree.postOrderRec(root);
System.out.print("\n后序非递归遍历:");
PrintBinaryTree.postOrderUnRec(root);
}
}