二叉树的存储和遍历(java)
二叉树的概念,参考博客二叉树基础知识总结
二叉树的存储,也就是创建二叉树;
遍历可分为三种方法:
- 先序遍历
- 中序遍历
- 后序遍历
举例说明:
组成二叉树的数据{ 3, 1, 8, 5, 9, 7, 4, 2 }
以3为根节点构成二叉树:
- 先序遍历(根左右):3-1-2-8-5-4-7-9
- 中序遍历(左根右):1-2-3-4-5-7-8-9
- 后序遍历(左右根):2-1-4-7-5-9-8-3
Java代码实现:
分为递归和非递归遍历两种。
package org.algorithm.basic;
import java.util.Stack;
/**
* 树的实现和遍历
*
* @author kiki
*
*/
class TreeNode {
int val; // 节点值
TreeNode left; // 左节点
TreeNode right; // 右节点
public TreeNode(int x) {
val = x;
}
}
public class SortBinaryTree {
public static void main(String[] args) {
int a[] = { 3, 1, 8, 5, 9, 7, 4, 2 };
TreeNode root = new TreeNode(a[0]); // 以数组第一个元素为根节点
for (int i = 1; i < a.length; i++) {
// 创建/存储二叉树
SortBinaryTree.createBinaryTree(root, a[i]);
}
// 递归遍历
preOrder(root);
System.out.println("递归先序遍历");
inOrder(root);
System.out.println("递归中序遍历");
postOrder(root);
System.out.println("递归后序遍历");
System.out.println("===================");
// 非递归遍历
preOrderFi(root);
System.out.println("非递归先序遍历");
inOrderFi(root);
System.out.println("非递归中序遍历");
postOrderFi(root);
System.out.println("非递归后序遍历");
}
/**
* 构建二叉树
*
* @param node
* @param i
* @return
*/
public static TreeNode createBinaryTree(TreeNode node, int i) {
if (node == null) {
node = new TreeNode(i);
return node;
} else {
if (i <= node.val) {
node.left = createBinaryTree(node.left, i);
} else {
node.right = createBinaryTree(node.right, i);
}
return node;
}
}
/**
* 递归先序遍历(根左右)
*
* @param root
*/
public static void preOrder(TreeNode root) {
if (root != null) {
System.out.print(root.val + "-");
preOrder(root.left);
preOrder(root.right);
}
}
/**
* 递归中序遍历(左根右)
*
* @param root
*/
public static void inOrder(TreeNode root) {
if (root != null) {
inOrder(root.left);
System.out.print(root.val + "-");
inOrder(root.right);
}
}
/**
* 递归后序遍历(左右根)
*
* @param root
*/
public static void postOrder(TreeNode root) {
if (root != null) {
postOrder(root.left);
postOrder(root.right);
System.out.print(root.val + "-");
}
}
/**
* 非递归先序遍历(根左右)
*
* @param root
*/
public static void preOrderFi(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.empty()) {
// 非空节点
if (cur != null) {
stack.push(cur); // 入栈
System.out.print(cur.val + "-");
cur = cur.left; // 切换左节点
} else {
// 空节点
cur = stack.pop(); // 出栈(返回父节点)
cur = cur.right; // 切换右节点
}
}
}
/**
* 非递归中序遍历(左根右)
*
* @param root
*/
public static void inOrderFi(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.empty()) {
// 非空节点
if (cur != null) {
stack.push(cur); // 入栈
cur = cur.left; // 切换左节点
} else {
// 空节点
cur = stack.pop(); // 出栈
System.out.print(cur.val + "-");
cur = cur.right; // 切换右节点
}
}
}
/**
* 非递归后序遍历(左右根)
*
* @param root
*/
public static void postOrderFi(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
TreeNode last = null; // 访问过的节点
while (cur != null || !stack.empty()) {
// 非空节点
if (cur != null) {
stack.push(cur); // 入栈
cur = cur.left; // 切换到左节点
} else {
// 空节点
// 返回栈顶,不删除栈顶
cur = stack.peek();
// 右节点不为空或者没有访问过
if (cur.right != null && cur.right != last) {
cur = cur.right; // 切换右节点
} else {
// 右节点为空或已经访问过
System.out.print(cur.val + "-");
cur = stack.pop(); // 出栈
last = cur; // 记录节点
cur = null; // 设置当前为空值,让其出栈
}
}
}
}
}
执行结果如下:
3-1-2-8-5-4-7-9-递归先序遍历
1-2-3-4-5-7-8-9-递归中序遍历
2-1-4-7-5-9-8-3-递归后序遍历
===================
3-1-2-8-5-4-7-9-非递归先序遍历
1-2-3-4-5-7-8-9-非递归中序遍历
2-1-4-7-5-9-8-3-非递归后序遍历