zoukankan      html  css  js  c++  java
  • 二叉树遍历(先序、中序、后序)

    二叉树的相关概念
    二叉树的定义
    二叉树(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

  • 相关阅读:
    移动端的爬坑路
    判断设备ios或android以及判断是否是微信内置浏览器
    使用vue directive 写好的滑动删除功能
    不用ajax,使用json数据渲染商品的方法
    vue中使用swiper的一些坑
    vue的自定义指令的坑
    better-score获取滑动距离的坑
    linux命令
    关于打印
    数据可视化
  • 原文地址:https://www.cnblogs.com/hongdada/p/6476679.html
Copyright © 2011-2022 走看看