二叉树遍历(先序、中序、后序)

二叉树的相关概念
二叉树的定义
二叉树(Binary Tree)是n(n>=0)个有限元素的集合,该集合或者为空,或者由一个称为根(root)的元素及两个不相交的,被称为左子树和右子树的二叉树组成。当集合为空时,称该二叉树为空二叉树,在二叉树中,一个元素也称为一个结点。
二叉树是有序的,即若将其左右子树颠倒,就称为另一颗不同的二叉树。
结点的度:结点所拥有的子树的个数称为该结点的度。
叶结点:度为0的结点称为叶结点,或者称为终端结点。
树的深度:树中所有结点的最大层数称为树的深度。
树的度:树中个结点度的最大值称为该树的度。
2.二叉树的三种遍历方式
二叉树有三种遍历方式:前序(父节点,左节点,右节点),中序(左节点,父节点,右节点),后序(左节点,右节点,父节点)。

如上图所示的一颗二叉树,按照三种遍历方式所打印的结果应该是:
前序:1 2 4 8 9 5 10 11 3 6 7
中序:8 4 9 2 10 5 11 1 6 3 7
后序:8 9 4 10 11 5 2 6 7 3 1

 

遍历方式的代码:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

public class Main {
    public static void main(String[] args)   {

        TreeNode root =new TreeNode(0);
        TreeNode left=new TreeNode(1);
        TreeNode right=new TreeNode(2);
        TreeNode left2=new TreeNode(3);
        TreeNode right2=new TreeNode(4);
        TreeNode left3=new TreeNode(5);
        TreeNode right3=new TreeNode(6);
        TreeNode left4=new TreeNode(7);
        TreeNode right4=new TreeNode(8);
        left.left=left2;
        left.right=right2;
        right.left=left3;
        right.right=right3;
        root.left=left;
        root.right=right;
        left2.left=left4;
        left2.right=right4;
        Print.PrintTreeNode(root);

        System.out.println("先序遍历:");
        PreOrderTraverse(root);
        System.out.println();
        System.out.println("中序遍历:");
        MidOrderTraverse(root);
        System.out.println();
        System.out.println("后序遍历:");
        LastOrderTraverse(root);
        System.out.println();
    }

    public static void PreOrderTraverse(TreeNode root){
        TreeNode node=root;
        if(node!=null){
            System.out.print(node.val+"   ");
            PreOrderTraverse(node.left);
            PreOrderTraverse(node.right);
        }
    }

    public static void MidOrderTraverse(TreeNode root){
        TreeNode node=root;
        if(node!=null){
            MidOrderTraverse(node.left);
            System.out.print(node.val+"   ");
            MidOrderTraverse(node.right);
        }
    }

    public static void LastOrderTraverse(TreeNode root){
        TreeNode node=root;
        if(node!=null){
            LastOrderTraverse(node.left);
            LastOrderTraverse(node.right);
            System.out.print(node.val+"   ");
        }
    }
}

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int x) {
        val = x;
    }
}



class Print{
    //打印TreeNode
    public static void PrintTreeNode(TreeNode root){
        ArrayList arrayList=PrintFromTopToBottom(root);
        printTree(arrayList,arrayList.size());
    }
    //转换TreeNode为ArrayList
    private static ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {

        ArrayList<Integer> list = new ArrayList();
        if(root == null)
            return list;

        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);

        while(!queue.isEmpty()){
            TreeNode treeNode = queue.poll();
            list.add(treeNode.val);
            if(treeNode.left != null)
                queue.offer(treeNode.left);
            if(treeNode.right != null)
                queue.offer(treeNode.right);
        }

        return list;
    }

    //以树形打印ArrayList
    private static void printTree(ArrayList array,int len){

        int layers = (int)Math.floor(Math.log((double)len)/Math.log((double)2))+1;  //树的层数
        int maxWidth = (int)Math.pow(2,layers)-1;  //树的最大宽度
        int endSpacing = maxWidth;
        int spacing;
        int numberOfThisLayer;
        for(int i=1;i<=layers;i++){  //从第一层开始,逐层打印
            endSpacing = endSpacing/2;  //每层打印之前需要打印的空格数
            spacing = 2*endSpacing+1;  //元素之间应该打印的空格数
            numberOfThisLayer = (int)Math.pow(2, i-1);  //该层要打印的元素总数

            int j;
            for(j=0;j<endSpacing;j++){
                System.out.print("  ");
            }

            int beginIndex = (int)Math.pow(2,i-1)-1;  //该层第一个元素对应的数组下标
            for(j=1;j<=numberOfThisLayer;j++){
                System.out.print(array.get(beginIndex++)+"");
                for(int k=0;k<spacing;k++){  //打印元素之间的空格
                    System.out.print("  ");
                }
                if(beginIndex == len){  //已打印到最后一个元素
                    break;
                }
            }

            System.out.println();
        }
        System.out.println();
    }

}
              0                              
      1              2              
  3      4      5      6      
7  8  

先序遍历:
0   1   3   7   8   4   2   5   6   
中序遍历:
7   3   8   1   4   0   5   2   6   
后序遍历:
7   8   3   4   1   5   6   2   0   

Process finished with exit code 0

非遍历方式的代码:

先序遍历:

   public static void PreOrderTraverse(TreeNode root) {
        TreeNode node = root;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        while(node!=null||!stack.isEmpty()){
            while(node!=null){
                System.out.print(node.val+"   ");
                stack.push(node);
                node=node.left;
            }
            if(!stack.isEmpty()){
                node=stack.pop();
                node=node.right;
            }
        }
    }

    public static void PreOrderTraverse2(TreeNode root){
        Stack<TreeNode> stack=new Stack<TreeNode>();
        TreeNode node=root;
        stack.push(node);
        while(!stack.isEmpty()){
            node=stack.pop();
            System.out.print(node.val+"   ");
            if(node.right!=null) {
             stack.push(node.right);
            }
            if(node.left!=null){
                stack.push(node.left);
            }
        }
    }

第二种方式比较容易,效率也应该高一些。

中序遍历:

    public static void MidOrderTraverse(TreeNode root){
        TreeNode node = root;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        while(node!=null||!stack.isEmpty()){
            while(node!=null){

                stack.push(node);
                node=node.left;
            }
            if(!stack.isEmpty()){
                node=stack.pop();
                System.out.print(node.val+"   ");
                node=node.right;
            }
        }
    }

后序遍历:

    // 非递归后序遍历
    public static void LastOrderTraverse(TreeNode root) {
        Stack<TreeNode> treeNodeStack = new Stack<TreeNode>();
        TreeNode node = root;
        TreeNode lastVisit = root;
        while (node != null || !treeNodeStack.isEmpty()) {
            while (node != null) {
                treeNodeStack.push(node);
                node = node.left;
            }
            //查看当前栈顶元素
            node = treeNodeStack.peek();
            //如果其右子树也为空,或者右子树已经访问
            //则可以直接输出当前节点的值
            if (node.right == null || node.right == lastVisit) {
                System.out.print(node.val + "   ");
                treeNodeStack.pop();
                lastVisit = node;
                node = null;
            } else {
                //否则,继续遍历右子树
                node = node.right;
            }
        }
    }

 

https://segmentfault.com/a/1190000004853442

http://www.jianshu.com/p/456af5480cee

https://segmentfault.com/a/1190000002606302

http://www.voidcn.com/blog/u013344815/article/p-4677425.html

https://my.oschina.net/u/225373/blog/491589

posted @ 2017-02-27 22:24  hongdada  阅读(985)  评论(0编辑  收藏  举报