二叉树

天大地大妈咪最大 提交于 2020-04-01 08:27:44

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

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

完全二叉树:叶子节点在最后两层;对于任一结点,左子树的深度比右子树深度大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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!