紧接上一篇,网上搜索了Java实现二叉树的方法及二叉树的遍历方法,参考:http://blog.csdn.net/skylinesky/article/details/6611442
学习和调试后代码如下:
测试数据(#表示节点为空):
所建立二叉树如下:
代码如下:
// 树的节点 public class TreeNode { private TreeNode left; private TreeNode right; private String val; public TreeNode(){ } public TreeNode(String val) { super(); this.val = val; } public TreeNode(TreeNode left, TreeNode right, String val) { super(); this.left = left; this.right = right; this.val = val; } 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; } public String getVal() { return val; } public void setVal(String val) { this.val = val; } }
import java.io.File; import java.io.FileNotFoundException; import java.util.Queue; import java.util.Scanner; import java.util.Stack; import java.util.concurrent.LinkedBlockingQueue; public class Tree { private TreeNode root; public Tree() { } public Tree(TreeNode root) { this.root = root; } // 创建二叉树 public void buildTree() { Scanner scn = null; try { scn = new Scanner(new File("D:\\test\\input.txt")); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } root = createTree(root, scn); } // 先序遍历创建二叉树 private TreeNode createTree(TreeNode root, Scanner scn) { String temp = scn.next(); if (temp.trim().equals("#")) { return null; } else { root = new TreeNode(temp); root.setLeft(createTree(root.getLeft(), scn)); root.setRight(createTree(root.getRight(), scn)); return root; } } // 中序遍历(递归) —— 左、根、右 public void inOrderTraverse() { inOrderTraverse(root); } public void inOrderTraverse(TreeNode root) { if (root != null) { inOrderTraverse(root.getLeft()); System.out.print(root.getVal() + " "); inOrderTraverse(root.getRight()); } } // 中序遍历(非递归) public void nrInorderTraverse() { Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode node = root; while (node != null || !stack.isEmpty()) { // 右子树不为空,或者栈不为空 while (node != null) { // 从根或右子树开始,把所有的左孩子的左孩子全部入栈,直到找到最里面的左孩子 stack.push(node); node = node.getLeft(); } node = stack.pop(); // 出栈左孩子或者根节点 System.out.print(node.getVal() + " "); node = node.getRight(); // 遍历之后,处理右子树内容。循环遍历右子树的左孩子等等 } } // 先序遍历(递归) —— 根、左、右 public void preOrderTraverse() { preOrderTraverse(root); } public void preOrderTraverse(TreeNode root) { if (root != null) { System.out.print(root.getVal() + " "); preOrderTraverse(root.getLeft()); preOrderTraverse(root.getRight()); } } // 先序遍历(非递归) public void nrPreOrderTraverse() { Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode node = root; while (node != null || !stack.isEmpty()) { // 右子树不为空,或者栈不为空 while (node != null) { System.out.print(node.getVal() + " "); // 遍历根节点和左子树的一系列的“根”,并将它们全部入栈 stack.push(node); node = node.getLeft(); } node = stack.pop(); // 弹出此时最里面的左子树根节点,判断其右子树情况 node = node.getRight(); // 处理右子树情况 } } // 后序遍历(递归) —— 左、右、根 public void postOrderTraverse() { postOrderTraverse(root); } public void postOrderTraverse(TreeNode root) { if (root != null) { postOrderTraverse(root.getLeft()); postOrderTraverse(root.getRight()); System.out.print(root.getVal() + " "); } } // 后序遍历(非递归) public void nrPostOrderTraverse() { Stack<TreeNode> stack = new Stack<TreeNode>(); TreeNode node = root; TreeNode preNode = null; // 表示最近一次访问的节点 while (node != null || !stack.isEmpty()) { // 右子树不为空,或者栈不为空(其子树已经处理过) while (node != null) { // 将根节点和左子树的根节点入栈,直到左子树为空 stack.push(node); node = node.getLeft(); } node = stack.peek(); // stack.peek()查找栈顶对象,但不移除它 查看栈顶元素 if (node.getRight() == null || node.getRight() == preNode) { // 该节点的右子树为空,或者其右子树已经被访问过 System.out.print(node.getVal() + " "); // 访问该节点 node = stack.pop(); preNode = node; node = null; // 将node置为空,用于判断栈中的下一元素 } else { node = node.getRight(); } } } // 按层次遍历 public void levelTraverse() { levelTraverse(root); } public void levelTraverse(TreeNode root) { Queue<TreeNode> queue = new LinkedBlockingQueue<TreeNode>(); // Queue为接口 queue.add(root); while (!queue.isEmpty()) { TreeNode temp = queue.poll(); // queue.poll()获取并移除队头元素 if (temp != null) { System.out.print(temp.getVal() + " "); if (temp.getLeft() != null) { queue.add(temp.getLeft()); } if (temp.getRight() != null) { queue.add(temp.getRight()); } } } } }
注意:各种非递归方式的实现是借助栈或者队列来实现的,利用了它们的进出的特点,关于非递归的实现,可以从分析具体的遍历来得到思路。
中序遍历和先序遍历的非递归方式有点类似,不同的地方在于,什么时候打印“根节点”。
后序遍历,需要好好理解遍历节点操作(使用stack.peek方法,还有参数preNode)
测试代码:
public class BinaryTreeTest { public static void main(String[] args) { Tree tree = new Tree(); tree.buildTree(); System.out.println("中序遍历"); tree.inOrderTraverse(); System.out.println("\n中序遍历(非递归)"); tree.nrInorderTraverse(); System.out.println("\n先序遍历"); tree.preOrderTraverse(); System.out.println("\n先序遍历(非递归)"); tree.nrPreOrderTraverse(); System.out.println("\n后序遍历"); tree.postOrderTraverse(); System.out.println("\n后序遍历(非递归)"); tree.nrPostOrderTraverse(); System.out.println("\n层次遍历"); tree.levelTraverse(); } }