zoukankan      html  css  js  c++  java
  • 二叉树

    二叉树:每个结点至多有两个子树

    满二叉树:每一层的结点个数都是最大结点数

    完全二叉树:叶子节点在最后两层;对于任一结点,左子树的深度比右子树深度大1或者相等

    性质:

    二叉树:第i层,至多有2^(i-1)个结点

    二叉树:深度为k的二叉树,至多有(2^k)-1个结点

    满二叉树:深度为k的满二叉树的结点个数为(2^k)-1 

    二叉树:任何一个二叉树,度为0的结点的个数n0,度为1的结点的个数n1,度为2的结点的个数的关系: n0 = n2+1,总的结点个数n

      原因:n0+n1+n2 = n  除了根节点之外,其它几点都有一个分支进入分支个数n-1,分支都是由度为1或者度为2的结点发出的  n1+2*n2 = n-1   根据这两个公式得到n0=n2+1

    完全二叉树:任何一个具有n个结点的完全二叉树的深度为 log以2为底n向下取整 + 1

    完全二叉树:任何一个完全二叉树按照层次为结点编号

      i=1,该结点是完全二叉树的根,无双亲

      i>1,该节点不是根,该结点的双亲的编号为i/2向下取整

      一个结点的编号是i,如果2*i大于n,表明该结点没有左孩子,否则,左孩子编号为2*i

      一个结点的编号是i,如果2*i+1大于n,表明该结点没有右孩子,否则,右孩子编号为2*i

    存储

    (1)顺序存储

    用一组地址连续的存储单元将二叉树从上到下从左到右按顺序存储,存储成对应的完全二叉树的形式(完全二叉树中编号为i的结点存储在数组下标为i-1的分量中),如果某个结点不存在,该位置存0

    数组的长度(2^k)-1   二叉树的深度为k,空间浪费

    (2)链式存储

    数据域 左孩子 右孩子

    指针域有浪费:含有n个结点的二叉树有n+1个空指针域    有n个结点,就有2*n个指针域,就有n-1个分支,所以,有n+1个指针浪费

    public class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x) {
            val = x; 
       }
        @Override
        public String toString() {
            return "TreeNode [val=" + val + ", left=" + left + ", right=" + right
                    + "]";
        }
    }

     二叉树遍历

    前序

        public static void preOrder(TreeNode node){
            //前序遍历,根左右,递归实现
            //每次调用时,参数node都是当前子树的根节点
            if(node == null){
                //如果当前节点是null,直接返回
                return;
            }else{
                //如果当前节点不是null,输出当前节点的值,然后遍历当前节点的左右子树
                System.out.print(node.val+" ");
                preOrder(node.left);
                preOrder(node.right);
            }
        }
        public static void preOrder2(TreeNode root){
            //前序遍历,根左右,借助栈,非递归实现
            //如果根节点是null,表明这是一棵空树,直接返回
            if(root == null){
                return;
            }else{
                //如果根节点不是null,遍历
                Stack<TreeNode> stack = new Stack<TreeNode>();
                //先将根节点入栈
                stack.push(root);
                while(!stack.isEmpty()){//栈空时,表明已经遍历完成
                    //弹出栈顶保存的那个节点,遍历其左右子树
                    TreeNode 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 inOrder(TreeNode node){
            //中序遍历,左根右,递归实现
            if(node == null){
                return;
            }else{
                //当前节点不是null时,先遍历当前节点的左子树,然后输出当前节点的值,最后遍历当前节点的右子树
                inOrder(node.left);
                System.out.print(node.val+" ");
                inOrder(node.right);
            }
        }
        public static void inOrder2(TreeNode root){
            //中序遍历,左根右,递归实现
            if(root == null){
                return;
            }else{
                Stack<TreeNode> stack = new Stack<TreeNode>();
                //左根右,第一个应该是该二叉树最左下的节点
                //从根节点出发,一直寻找节点的左节点,直到最左下的节点
                
                while(root!=null || !stack.isEmpty()){
                    while(root!=null){
                        stack.push(root);
                        root = root.left;
                    }
                    //while循环之后,root的值是null,只有当当前节点cur有右子树,root的值会成为右子树的根节点
                    
                    //现在栈顶元素是最左下的节点,出栈该节点,输出该节点的值,然后看该节点是否存在右节点
                    //如果存在右节点,继续从该右节点出发,一直寻找节点的左节点,直到最左下的节点
                    TreeNode cur = stack.pop();
                    System.out.print(cur.val+" ");
                    if(cur.right != null){
                        root = cur.right;
                    }
                }
            }
        }

    后序

        public static void postOrder(TreeNode node){
            //后序遍历  左右跟
            if(node == null){
                return;
            }else{
                postOrder(node.left);
                postOrder(node.right);
                System.out.print(node.val+" ");
            }
            
        }

    层序

        public static void layerOrder(TreeNode root){
            //层序遍历
            //利用队列实现
            if(root == null){
                return;
            }else{
                Queue<TreeNode> queue = new LinkedBlockingQueue<TreeNode>();
                queue.add(root);
                while(!queue.isEmpty()){
                    TreeNode node = queue.remove();
                    System.out.print(node.val+" ");
                    if(node.left != null){
                        queue.add(node.left);
                    }
                    if(node.right != null){
                        queue.add(node.right);
                    }
                    
                }
                
            }
        }

     二叉树重建

     

        public static TreeNode createBitree(List<Integer> preOrder,List<Integer> inOrder){
            int size = preOrder.size();
            if(size == inOrder.size() && size>0){
                TreeNode root = new TreeNode(preOrder.get(0));//创建当前子树的根节点
                //当前子树的根节点在中序遍历序列中的下标,找到该下标之后,该以左的子序列为当前根节点的左子树的中序遍历序列,该以右的子序列为当前根节点的右子树的中序遍历序列
                int rootIndex = inOrder.indexOf(preOrder.get(0));
                System.out.println("rootIndex:"+rootIndex);
                
                if(rootIndex==0){
                    //表明当前节点没有左子树
                    root.setLeft(null);
                    root.setRight(createBitree(preOrder.subList(rootIndex+1, size), inOrder.subList(rootIndex+1, size)));
                }else if(rootIndex == preOrder.size()-1){
                    //表明当前节点没有右子树
                    root.setLeft(createBitree(preOrder.subList(1, rootIndex+1), inOrder.subList(0, rootIndex)));
                    root.setRight(null);
                }else{
                    //当前节点既有左子树又有右子树
                    root.setLeft(createBitree(preOrder.subList(1, rootIndex+1), inOrder.subList(0, rootIndex)));
                    root.setRight(createBitree(preOrder.subList(rootIndex+1, size), inOrder.subList(rootIndex+1, size)));
                }
                return root;
                    
            }else{
                return null;
            }
            
        }

     二叉树的计数

    具有n个结点、互不相似的二叉树的数目

    相似是指二叉树的形态一样,跟结点的值没有关系

     

    参考:https://www.cnblogs.com/gxclmx/p/7485384.html

  • 相关阅读:
    Arthas线上问题排查
    如何快速增加pdf书签,解除pdf限制
    数组指针——指向数组的指针(通过指针控制数组)
    指针和数组直接对应关系之如何记忆
    C/C++语言中指针数组和数组指针比较区别
    int最大值+1为什么是-2147483648最小值-1为什么是2147483647
    电脑进行二进制加减运算方法
    C/C++语言中的函数参数传参三种对比
    Python基于VS2013 开发环境搭建 Hello World 10分钟搞定
    算法的复杂度包括时间复杂度和空间复杂度分别如何计算?
  • 原文地址:https://www.cnblogs.com/duanjiapingjy/p/9565013.html
Copyright © 2011-2022 走看看