参考了如下两篇文章:
http://zhangjunhd.blog.51cto.com/113473/82616
http://old.blog.edu.cn/user3/Newpoo/archives/2007/1683187.shtml
构造树如下:
package sherry.tyut;
import java.util.*;
//二叉树节点类
class BTNode {
private char data;
private BTNode left;
private BTNode right;
public char getData() {
return data;
}
public void setData(char data) {
this.data = data;
}
public BTNode getLeft() {
return left;
}
public void setLeft(BTNode left) {
this.left = left;
}
public BTNode getRight() {
return right;
}
public void setRight(BTNode right) {
this.right = right;
}
public BTNode(char data) {
this(data,null,null);
}
public BTNode(char data, BTNode left, BTNode right) {
this.data = data;
this.left = left;
this.right = right;
}
}
//二叉树
public class BinaryTree {
//属性
private BTNode root;
//set,get方法
public BinaryTree(BTNode root) {
this.root = root;
}
public BTNode getRoot() {
return root;
}
//访问节点
public static void visit(BTNode nood) {
System.out.print(nood.getData()+" ");
}
//初始化
public static BTNode init() {
BTNode a = new BTNode('A');
BTNode b = new BTNode('B', null, a);
BTNode c = new BTNode('C');
BTNode d = new BTNode('D', b, c);
BTNode e = new BTNode('E');
BTNode f = new BTNode('F', e, null);
BTNode g = new BTNode('G', null, f);
BTNode h = new BTNode('H', d, g);
return h;
//另外一个二叉树
// BTNode e = new BTNode('E');
// BTNode g = new BTNode('G');
// BTNode i = new BTNode('I');
// BTNode d = new BTNode('D', null, g);
// BTNode b = new BTNode('B', d, null);
// BTNode h = new BTNode('H', null, i);
// BTNode f = new BTNode('F', h, null);
// BTNode c = new BTNode('C', e, f);
// BTNode a = new BTNode('A', b, c);
// return a;
}
//递归实现前序遍历
public static void preorder(BTNode nood) {
if(nood != null) {
visit(nood);
preorder(nood.getLeft());
preorder(nood.getRight());
}
}
//递归实现中序遍历
public static void inorder(BTNode nood) {
if(nood != null) {
inorder(nood.getLeft());
visit(nood);
inorder(nood.getRight());
}
}
//递归实现后序遍历
public static void postorder(BTNode nood) {
if(nood != null) {
postorder(nood.getLeft());
postorder(nood.getRight());
visit(nood);
}
}
/*
* 非递归实现前序遍历思路:
* 1.根节点入栈
* while(栈非空) {
* (1)(根)节点出栈并访问
* (2)右子入栈,左子入栈
* }
*/
private static void nonrecuusivePreorder(BTNode nood) {
Stack<BTNode> stack = new Stack<BTNode>();
if(nood != null) {
stack.push(nood);
while(!stack.empty()) {
nood = stack.pop();
visit(nood);
if(nood.getRight() != null)
stack.push(nood.getRight());
if(nood.getLeft() != null)
stack.push(nood.getLeft());
}
}
}
/*
* 非递归实现中序遍历
* while(节点非空||栈非空) {
* 1.(根)节点及其所有左子入栈
* 2.栈顶出栈并访问,nood=nood.getRight(),无论有无右子,有则nood非空,无则nood空。
* }
* //注意:nood为空,但栈非空同样可以进入while循环
*/
private static void nonrecuusiveInorder(BTNode nood) {
Stack<BTNode> stack = new Stack<BTNode>();
while(nood != null || !stack.empty()) {
// if(nood != null)
// System.out.println("-"+nood.getData()+"-");
while(nood != null) {
// if(nood != null)
// System.out.println("--"+nood.getData()+"--");
stack.push(nood);
nood = nood.getLeft();
}
if(!stack.empty()) {
nood = stack.pop();
visit(nood);
nood = nood.getRight();
}
/*
* 当nood='A'时,nood != null进入while循环,A及A的所有左子入栈(当然A无子,不去管,至少A入栈了),
* A出栈并扫描,由于A无子,故nood返回的是一个null,再次进入while循环!stack.empty()成立,由于
* nood == null;所以while(nood != null)不会去执行,直接执行if(!stack.empty())。
* 加上判断后,保证了nood != null恒成立,则每次进入循环时,总得执行while(nood != null)里面。
*/
// if(nood.getRight() != null)//如加上这句错误。见上分析
// nood = nood.getRight();//此句加到if条件里面更好
}
}
/*
* 非递归实现后序遍历思路:
* while(节点非空||栈非空) {
* 1.(根)节点及其所有左子入栈
* 2.栈顶出栈
* (1)if(当前节点无右子 || 右子已访问)
* 当前节点出栈并访问
* (2)else
* nood = nood.getRight()
* }
* //注意:nood = null设置的重要性
* 问题:
* 1.测试本次while循环结束,nood节点的值到底是什么?
* 2.pop()的返回是当前弹出元素?还是弹出之后栈顶元素?
*/
private static void nonrecuusivePostorder(BTNode nood) {
BTNode pre = null;//上次被访问的节点
Stack<BTNode> stack = new Stack<BTNode>();
while(nood != null || !stack.empty()) {
while(nood != null) {
stack.push(nood);
nood = nood.getLeft();
// if(nood != null)//测试本次while循环结束,nood节点的值到底是?
// System.out.println(nood.getData());
// else//注意这里的nood最后为空,是因为执行了nood.getLeft()。
// System.out.println(nood);//但是栈中为H,D,B三个元素。
}
nood = stack.peek();//故在此nood节点指向当前栈顶的元素。
// System.out.println("-"+nood.getData()+"-");
//当前节点无右子或右子已经访问过
if(null == nood.getRight() || pre == nood.getRight()) {
pre = stack.pop();//记录当前要访问的节点
// System.out.println("pre="+pre.getData());//pop()返回当前弹出元素,弹之后
// System.out.println(stack.peek().getData());//再查看栈顶时,栈顶元素改变。
visit(pre);//pre值是当前弹出的元素,弹出之后,栈顶“指针”减一,指向下一个元素。
nood = null;//防止下轮while循环再次访问所有的左子
}
else {//有右子
nood = nood.getRight();//访问一个右子
}
}
}
/*
* 层次遍历思路:
* 1.根节点入队列
* 2.while(队列非空) {
* 队列头元素出队列并访问
* 左子入队列,右子入队列
* }
* //注意Queue<BTNode> queue = new Queue<BTNode>();这样会报错的。
* Queue是一个接口,接口就是一个隐式的抽象类,抽象类在Java中是不能实例化的 。
*/
private static void levelorder(BTNode nood) {
Queue<BTNode> queue = new LinkedList<BTNode>();
if(nood != null) {
queue.add(nood);
while(!queue.isEmpty()) {
nood = queue.poll();
visit(nood);
if(nood.getLeft() != null)
queue.add(nood.getLeft());
if(nood.getRight() != null)
queue.add(nood.getRight());
}
}
}
public static void main(String[] args) {
BinaryTree btree = new BinaryTree(init());
System.out.println("---recuusive method---");
System.out.print("Pre-Order:");
preorder(btree.getRoot());
System.out.println();
System.out.print("In-Order:");
inorder(btree.getRoot());
System.out.println();
System.out.print("Post-Order:");
postorder(btree.getRoot());
System.out.println();
System.out.println("---nonrecuusive method---");
System.out.print("nonrecPre-Order:");
nonrecuusivePreorder(btree.getRoot());
System.out.println();
System.out.print("nonrecIn-Order:");
nonrecuusiveInorder(btree.getRoot());
System.out.println();
System.out.print("nonrecPost-Order:");
nonrecuusivePostorder(btree.getRoot());
System.out.println();
System.out.print("levelorder:");
levelorder(btree.getRoot());
System.out.println();
}
}
输出结果:
---recuusive method---
Pre-Order:H D B A C G F E
In-Order:B A D C H G E F
Post-Order:A B C D E F G H
---nonrecuusive method---
nonrecPre-Order:H D B A C G F E
nonrecIn-Order:B A D C H G E F
nonrecPost-Order:A B C D E F G H
levelorder:H D G B C F A E