二叉树前序、中序、后序,递归、非递归遍历
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class BinaryTree {
static class Node {
public Node left;
public Node right;
public char value;
}
private static void processNode(Node node) {
System.out.println("(" + node.value + ")");
}
/**
* 递归前序遍历
*/
private static void preOrder(Node node) {
if (node != null) {
processNode(node);
preOrder(node.left);
preOrder(node.right);
}
}
/**
* 非递归前序遍历
* @param root
*/
private static void preOrderNonRecursive(Node root) {
Stack<Node> nodeStack = new Stack<>();
Node currentNode = root;
while (currentNode != null || !nodeStack.empty()) {
while (currentNode != null) {
processNode(currentNode);
nodeStack.push(currentNode);
currentNode = currentNode.left;
}
if (!nodeStack.empty()) {
currentNode = nodeStack.pop().right;
}
}
}
/**
* 递归中序遍历
* @param node
*/
private static void inOrder(Node node) {
if (node != null) {
inOrder(node.left);
processNode(node);
inOrder(node.right);
}
}
/**
* 非递归中序遍历
* @param root
*/
private static void inOrderNonRecursive(Node root) {
Stack<Node> nodeStack = new Stack<>();
Node currentNode = root;
while (currentNode != null || !nodeStack.empty()) {
while (currentNode != null) {
nodeStack.push(currentNode);
currentNode = currentNode.left;
}
if (!nodeStack.empty()) {
currentNode = nodeStack.pop();
processNode(currentNode);
currentNode = currentNode.right;
}
}
}
/**
* 递归后序遍历
* @param node
*/
private static void postOrder(Node node) {
if (node != null) {
postOrder(node.left);
postOrder(node.right);
processNode(node);
}
}
/**
* 非递归后续遍历
* 要访问一个节点的条件上一个访问的节点是右儿子,因此保存上一个访问节点与当前节点的子节点做比较
*
* @param root
*/
private static void postOrderNonRecursive(Node root) {
Node preNode, currentNode;
currentNode = root;
Stack<Node> nodeStack = new Stack<>();
// 当前节点的左子节点已经被访问了
boolean isLeftBeVisited;
while (currentNode != null || !nodeStack.empty()) {
// 当前节点的所有左子节点入栈
while (currentNode != null) {
nodeStack.push(currentNode);
currentNode = currentNode.left;
}
isLeftBeVisited = true;
preNode = null;
// 栈非空,且左子节点被访问过了
while (!nodeStack.empty() && isLeftBeVisited) {
currentNode = nodeStack.peek();
// 如果上一个访问的节点与当前节点的右子节点相同,那么当前节点就可以处理了;如果不是,说明当前节点的右子节点还没被处理过
if (currentNode.right == preNode) {
processNode(currentNode);
nodeStack.pop();
preNode = currentNode;
currentNode = null;
} else {
currentNode = currentNode.right;
isLeftBeVisited = false;
}
}
}
}
private static Node generateTree() {
List<Node> list = new ArrayList<>();
char c = 'a';
int count = 10;
for (int i = 0; i < count; i++) {
Node node = new Node();
node.value = (char) (c + i);
list.add(node);
}
for (int i = count / 2; i >= 0; i--) {
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < count) {
list.get(i).left = list.get(left);
}
if (right < count) {
list.get(i).right = list.get(right);
}
}
return list.get(0);
}
public static void main(String[] args) {
Node root = generateTree();
// preOrder(root);
// preOrderNonRecursive(root);
// inOrder(root);
// inOrderNonRecursive(root);
postOrder(root);
postOrderNonRecursive(root);
}
}
简单说明
这里需要说明的是,后序非递归遍历,主要思路在于,访问节点之前,需要确定节点左右子节点都已经被访问过了,通过标志(isLeftBeVisited)确定左子节点已经被访问过了,通过preNode保存上一个访问过节点,判断preNode是否为当前节点的右子节点,确定右子节点已经被访问过了。