Java创建二叉树及其遍历的递归和非递归实现

    紧接上一篇,网上搜索了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();
	}
}

    代码运行结果:

   

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值