前序遍历:中-左-右
中序遍历:左-中-右
后序遍历:左-右-中
树中的结点定义:
static class Node{
Node leftChild;
Node rightChild;
int rvisited;
char data;
Node(char newData){
leftChild=null;
rightChild=null;
data=newData;
}
public Node(char data,Node leftChild, Node rightChild) {
super();
this.leftChild = leftChild;
this.rightChild = rightChild;
this.data = data;
}
}
树的建立:
public static Node init() {
Node a = new Node(‘A’);
Node b = new Node(‘B’, null, a);
Node c = new Node(‘C’);
Node d = new Node(‘D’, b, c);
Node e = new Node(‘E’);
Node f = new Node(‘F’, e, null);
Node g = new Node(‘G’, null, f);
Node h = new Node(‘H’, d, g);
return h;// root
}
前序遍历递归代码实现:
public static void preOrderTraverse(Node node){
if(node!=null){
System.out.print(node.data+” “);
preOrderTraverse(node.leftChild);
preOrderTraverse(node.rightChild);
}
}
前序遍历非递归代码实现:
public static void iterativePreorder(Node p) {
Stack<Node> stack=new Stack<Node>();
stack.push(p);
while(!stack.empty()){
Node temp=stack.pop();
System.out.print(temp.data+” “);
if(temp.rightChild!=null) stack.push(temp.rightChild);
if(temp.leftChild!=null) stack.push(temp.leftChild);
}
}
中序遍历递归代码实现:
public static void inOrderTraverse(Node node){
if(node!=null){
inOrderTraverse(node.leftChild);
System.out.print(node.data+” “);
inOrderTraverse(node.rightChild);
}
}
中序遍历非递归代码实现:
public static void iterativeInorder(Node p) {
Stack<Node> stack=new Stack<Node>();
while(p!=null){
stack.push(p);
p=p.leftChild;
}
while(!stack.isEmpty()){
Node node=stack.pop();
System.out.print(node.data+” “);
if(node.rightChild!=null){
node=node.rightChild;
while(node!=null){
stack.push(node);
node=node.leftChild;
}
}
}
}
后序遍历递归代码实现:
public static void postOrderTraverse(Node node){
if(node!=null){
postOrderTraverse(node.leftChild);
postOrderTraverse(node.rightChild);
System.out.print(node.data+” “);
}
}
后序遍历非递归代码实现:
public static void iterativePostorder(Node p){
Stack<Node> stack=new Stack<Node>();
//首先,从根节点开始,往左下方走,一直走到头,将路径上的每一个结点入栈。
while(p!=null){
stack.push(p);
//
push到栈中两个信息,一是结点指针,一是其右结点是否被访问过
p=p.leftChild;
}
//然后进入循环体
while(!stack.isEmpty()){
//
只要栈非空
Node node=stack.peek();
//
sn是栈顶结点
//注意,任意一个结点N,只要他有左孩子,则在N入栈之后,N的左孩子必然也跟着入栈了(这个体现在算法的后半部分),所以当我们拿到栈顶元素的时候,可以确信这个元素要么没有左孩子,要么其左孩子已经被访问过,所以此时我们就不关心它的左孩子了,我们只关心其右孩子。 //若其右孩子已经被访问过,或是该元素没有右孩子,则由后序遍历的定义,此时可以visit这个结点了。
if(node.rightChild==null||node.rvisited==1){
System.out.print(node.data+” “);
stack.pop();
}else{
//若它的右孩子存在且rvisited为0,说明以前还没有动过它的右孩子,于是就去处理一下其右孩子。 { //此时我们要从其右孩子结点开始一直往左下方走,直至走到尽头,将这条路径上的所有结点都入栈。 //当然,入栈之前要先将该结点的rvisited设成1,因为其右孩子的入栈意味着它的右孩子必将先于它被访问(这很好理解,因为我们总是从栈顶取出元素来进行visit)。由此可知,下一次该元素再处于栈顶时,其右孩子必然已被visit过了,所以此处可以将rvisited设置为1。
if(node.rightChild!=null){
node.rvisited=1;
//往左下方走到尽头,将路径上所有元素入栈
node=node.rightChild;
while(node!=null){
stack.push(node);
node=node.leftChild;
}
}
//这一轮循环已结束,刚刚入栈的那些结点我们不必管它了,下一轮循环会将这些结点照顾的很好。
}
}
}