JAVA实现二叉树(二叉树的存储、二叉树的遍历)

参考了如下两篇文章:

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循环,AA的所有左子入栈(当然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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值