遍历二叉树 非递归 JAVA 实现
Posted 顧棟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了遍历二叉树 非递归 JAVA 实现相关的知识,希望对你有一定的参考价值。
遍历二叉树 非递归
先序遍历
二叉树的先序遍历既可以直接采用递归思想实现,也可以使用栈的存储结构模拟递归的思想实现
中序遍历
中序遍历的非递归方式实现思想是:从根结点开始,遍历左孩子同时压栈,当遍历结束,说明当前遍历的结点没有左孩子,从栈中取出来调用操作函数,然后访问该结点的右孩子,继续以上重复性的操作。
除此之外,还有另一种实现思想:中序遍历过程中,只需将每个结点的左子树压栈即可,右子树不需要压栈。当结点的左子树遍历完成后,只需要以栈顶结点的右孩子为根结点,继续循环遍历即可。
后序遍历
后序遍历是在遍历完当前结点的左右孩子之后,才调用操作函数,所以需要在操作结点进栈时,为每个结点配备一个标志位。当遍历该结点的左孩子时,设置当前结点的标志位为 0,进栈;当要遍历该结点的右孩子时,设置当前结点的标志位为 1,进栈。
这样,当遍历完成,该结点弹栈时,查看该结点的标志位的值:如果是 0,表示该结点的右孩子还没有遍历;反之如果是 1,说明该结点的左右孩子都遍历完成,可以调用操作函数。
Java实现
package tree;
public class TreeNode {
/**
* 节点上的值
*/
private int value;
/**
* 左节点
*/
private TreeNode left;
/**
* 右节点
*/
private TreeNode right;
public TreeNode() {
}
public TreeNode(TreeNode left, TreeNode right, int value) {
this.left = left;
this.right = right;
this.value = value;
}
public TreeNode(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public TreeNode getLeft() {
return left;
}
public void setLeft(TreeNode left) {
this.left = left;
}
public TreeNode getRight() {
return right;
}
public void setRight(TreeNode right) {
this.right = right;
}
}
package tree;
import org.apache.commons.lang.StringUtils;
import java.util.Stack;
/**
* 遍历二叉树
*/
public class TraversalBinaryTree {
public static final StringBuilder VALUES = new StringBuilder();
public static final String SEPARATOR = "->";
public static final int SEPARATOR_LENGTH = SEPARATOR.length();
/**
* 先序遍历 非递归
*/
public static String preOrderTraverse(TreeNode treeNode) {
String result = "";
Stack<TreeNode> stack = new Stack<>();
// 树或栈不为空
while (null != treeNode || !stack.isEmpty()) {
// 对左子树进行遍历,直到最后没有做子树结点
while (null != treeNode) {
VALUES.append(treeNode.getValue()).append(SEPARATOR);
stack.push(treeNode);
treeNode = treeNode.getLeft();
}
// 栈不为空说明 还没有遍历结束
if (!stack.isEmpty()) {
treeNode = stack.pop();
treeNode = treeNode.getRight();
}
}
if (StringUtils.isNotBlank(VALUES.toString())) {
result = VALUES.substring(0, VALUES.toString().length() - SEPARATOR_LENGTH);
}
return result;
}
/**
* 中序遍历 非递归
*/
public static String inorderTraverse(TreeNode treeNode) {
String result = "";
Stack<TreeNode> stack = new Stack<>();
while (null != treeNode || !stack.isEmpty()) {
// 对左子树进行遍历,直到最后没有做子树结点
while (null != treeNode) {
stack.push(treeNode);
treeNode = treeNode.getLeft();
}
// 栈不为空说明 还没有遍历结束
if (!stack.isEmpty()) {
treeNode = stack.pop();
VALUES.append(treeNode.getValue()).append(SEPARATOR);
treeNode = treeNode.getRight();
}
}
if (StringUtils.isNotBlank(VALUES.toString())) {
result = VALUES.substring(0, VALUES.toString().length() - SEPARATOR_LENGTH);
}
return result;
}
/**
* 后序遍历 非递归
*/
public static String postorderTraverse(TreeNode treeNode) {
String result = "";
// 左右结点的标记
Integer flagLeft = 0;
Integer flagRight = 1;
Stack<TreeNode> stack = new Stack<>();
//辅助栈,用来判断子节点返回父节点时处于左节点还是右节点。
Stack<Integer> stack2 = new Stack<>();
while (null != treeNode || !stack.isEmpty()) {
while (null != treeNode) {
stack.push(treeNode);
stack2.push(flagLeft);
treeNode = treeNode.getLeft();
}
// 如果是从右子节点返回父节点,则任务完成,将两个栈的栈顶弹出
while (!stack.empty() && flagRight.equals(stack2.peek())) {
stack2.pop();
VALUES.append(stack.pop().getValue()).append(SEPARATOR);
}
// 如果是从左子节点返回父节点,则将标记改为右子节点
if (!stack.empty() && flagLeft.equals(stack2.peek())) {
stack2.pop();
stack2.push(flagRight);
treeNode = stack.peek().getRight();
}
}
if (StringUtils.isNotBlank(VALUES.toString())) {
result = VALUES.substring(0, VALUES.toString().length() - SEPARATOR_LENGTH);
}
return result;
}
}
package tree;
import java.util.Stack;
public class Client {
public static void main(String[] args) {
String result = "";
TreeNode treeNode = init();
System.out.println("===非递归方式===");
TraversalBinaryTree.VALUES.delete(0, result.length() + 2);
result = TraversalBinaryTree.preOrderTraverse(treeNode);
System.out.println("先序结果=" + result);
TraversalBinaryTree.VALUES.delete(0, result.length() + 2);
result = TraversalBinaryTree.inorderTraverse(treeNode);
System.out.println("中序结果=" + result);
TraversalBinaryTree.VALUES.delete(0, result.length() + 2);
result = TraversalBinaryTree.postorderTraverse(treeNode);
System.out.println("后序结果=" + result);
}
/**
* 构建如下的二叉树,同时是个满二叉树
* 1
* / \\
* 2 3
* / \\ / \\
* 4 5 6 7
*/
public static TreeNode init() {
TreeNode root = new TreeNode(1);
TreeNode treeNode2 = new TreeNode(2);
TreeNode treeNode3 = new TreeNode(3);
root.setLeft(treeNode2);
root.setRight(treeNode3);
TreeNode treeNode4 = new TreeNode(4);
TreeNode treeNode5 = new TreeNode(5);
TreeNode treeNode6 = new TreeNode(6);
TreeNode treeNode7 = new TreeNode(7);
treeNode2.setLeft(treeNode4);
treeNode2.setRight(treeNode5);
treeNode3.setLeft(treeNode6);
treeNode3.setRight(treeNode7);
return root;
}
}
===非递归方式===
先序结果=1->2->4->5->3->6->7
中序结果=4->2->5->1->6->3->7
后序结果=4->5->2->6->7->3->1
以上是关于遍历二叉树 非递归 JAVA 实现的主要内容,如果未能解决你的问题,请参考以下文章