二叉树相关算法

    /* 
     *  判断两棵二叉树是否相同的树。  
     * 递归解法:   
     * (1)如果两棵二叉树都为空,返回真  
     * (2)如果两棵二叉树一棵为空,另一棵不为空,返回假   
     * (3)如果两棵二叉树都不为空,如果对应的左子树和右子树都同构返回真,其他返回假  
     * */  
    public static boolean isSameRec(TreeNode r1, TreeNode r2) {  
        // both are null.  
        if (r1 == null && r2 == null) {  
            return true;  
        }  
          
        // one is null.  
        if (r1 == null || r2 == null) {  
            return false;  
        }  
          
        // 1. the value of the root should be the same;  
        // 2. the left tree should be the same.  
        // 3. the right tree should be the same.  
        return r1.val == r2.val &&   
                isSameRec(r1.left, r2.left) && isSameRec(r1.right, r2.right);  
    }  
      
    /* 
     * 判断两棵二叉树是否相同的树。 
     * 迭代解法  
     * 我们直接用中序遍历来比较就好啦  
     * */  
    public static boolean isSame(TreeNode r1, TreeNode r2) {  
        // both are null.  
        if (r1 == null && r2 == null) {  
            return true;  
        }  
          
        // one is null.  
        if (r1 == null || r2 == null) {  
            return false;  
        }  
          
        Stack<TreeNode> s1 = new Stack<TreeNode>();  
        Stack<TreeNode> s2 = new Stack<TreeNode>();  
          
        TreeNode cur1 = r1;  
        TreeNode cur2 = r2;  
          
        while (true) {  
            while (cur1 != null && cur2 != null) {  
                s1.push(cur1);  
                s2.push(cur2);  
                cur1 = cur1.left;  
                cur2 = cur2.left;  
            }  
              
            if (cur1 != null || cur2 != null) {  
                return false;  
            }  
              
            if (s1.isEmpty() && s2.isEmpty()) {  
                break;  
            }  
              
            cur1 = s1.pop();  
            cur2 = s2.pop();  
            if (cur1.val != cur2.val) {  
                return false;  
            }  
              
            cur1 = cur1.right;  
            cur2 = cur2.right;  
        }  
          
        return true;  
    }  
/*
.


 public static int getDepthRec(TreeNode root) {//求树高
        if (root == null) {  
            return -1;  
        }  
          
        return Math.max(getDepthRec(root.left), getDepthRec(root.right)) + 1;  
    }  
      
    /* 
     * 可以用 level LevelOrderTraversal 来实现,我们用一个dummyNode来分隔不同的层,这样即可计算出实际的depth. 
     *      1   
           / \   
          2   3   
         / \   \   
        4   5   6 
     *  
     * 在队列中如此排列: 1, dummy, 2, 3, dummy, 4, 5, 5, dummy   
     *  
    */    
    public static int getDepth(TreeNode root) {  
        if (root == null) {  
            return 0;  
        }  
          
        TreeNode dummy = new TreeNode(0);  
        Queue<TreeNode> q = new LinkedList<TreeNode>();  
        q.offer(root);  
        q.offer(dummy);  
          
        int depth = -1;  
        while (!q.isEmpty()) {  
            TreeNode curr = q.poll();  
            if (curr == dummy) {  
                depth++;  
                if (!q.isEmpty()) {  // 使用DummyNode来区分不同的层, 如果下一层不是为空,则应该在尾部加DummyNode.  
                    q.offer(dummy);  
                }  
            }  
              
            if (curr.left != null) {  
                q.offer(curr.left);  
            }  
            if (curr.right != null) {  
                q.offer(curr.right);  
            }  
        }  
          
        return depth;  
    }  




/* 
 *  
 *  判断二叉树是不是平衡二叉树:isAVLRec 
 *     1. 左子树,右子树的高度差不能超过1 
 *     2. 左子树,右子树都是平衡二叉树。  
 *       
 */  
    public static boolean isAVLRec(TreeNode root) {  
        if (root == null) {  
            return true;  
        }  
          
        // 左子树,右子树都必须是平衡二叉树。   
        if (!isAVLRec(root.left) || !isAVLRec(root.right)) {  
            return false;  
        }  
          
        int dif = Math.abs(getDepthRec(root.left) - getDepthRec(root.right));  
        if (dif > 1) {  
            return false;  
        }  
          
        return true;  
    } 




 /* 
     * . 求二叉树中两个节点的最低公共祖先节点:  
     * */  
    public static TreeNode LACRec(TreeNode root, TreeNode node1, TreeNode node2) {  
        if (root == null || node1 == null || node2 == null) {  
            return null;  
        }  
          
        // If any of the node is the root, just return the root.  
        if (root == node1 || root == node2) {  
            return root;  
        }  
          
        // if no node is in the node, just recursively find it in LEFT and RIGHT tree.  
        TreeNode left = LACRec(root.left, node1, node2);  
        TreeNode right = LACRec(root.right, node1, node2);  
          
        if (left == null) {  // If didn't found in the left tree, then just return it from right.  
            return right;  
        } else if (right == null) { // Or if didn't found in the right tree, then just return it from the left side.  
            return left;  
        }   
          
        // if both right and right found a node, just return the root as the Common Ancestor.  
        return root;  
    }  
/* 
     *  求BST中两个节点的最低公共祖先节点: 
     * Recursive version: 
     * LCABst  
     *  
     * 1. If found in the left tree, return the Ancestor. 
     * 2. If found in the right tree, return the Ancestor. 
     * 3. If Didn't find any of the node, return null. 
     * 4. If found both in the left and the right tree, return the root. 
     * */  
    public static TreeNode LCABstRec(TreeNode root, TreeNode node1, TreeNode node2) {  
        if (root == null || node1 == null || node2 == null) {  
            return null;  
        }  
          
        // If any of the node is the root, just return the root.  
        if (root == node1 || root == node2) {  
            return root;  
        }  
          
        int min = Math.min(node1.val, node2.val);  
        int max = Math.max(node1.val, node2.val);  
          
        // if the values are smaller than the root value, just search them in the left tree.  
        if (root.val > max) {  
            return LCABstRec(root.left, node1, node2);  
        } else if (root.val < min) {  
        // if the values are larger than the root value, just search them in the right tree.      
            return LCABstRec(root.right, node1, node2);  
        }  
          
        // if root is in the middle, just return the root.  
        return root;  
    }  


 /* 
     * 算法. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec  
     *  We assume that there is no duplicate in the trees. 
     *  For example: 
     *          1 
     *         / \ 
     *        2   3 
     *       /\    \ 
     *      4  5    6 
     *              /\ 
     *             7  8   
     *              
     *  PreOrder should be: 1   2 4 5   3 6 7 8 
     *                      根   左子树    右子树   
     *  InOrder should be:  4 2 5   1   3 7 6 8 
     *                       左子树  根  右子树 
     * */                     
    public static TreeNode rebuildBinaryTreeRec(List<Integer> preOrder, List<Integer> inOrder) {  
        if (preOrder == null || inOrder == null) {  
            return null;  
        }  
          
        // If the traversal is empty, just return a NULL.  
        if (preOrder.size() == 0 || inOrder.size() == 0) {  
            return null;  
        }  
          
        // we can get the root from the preOrder.   
        // Because the first one is the root.  
        // So we just create the root node here.  
        TreeNode root = new TreeNode(preOrder.get(0));  
          
        List<Integer> preOrderLeft;  
        List<Integer> preOrderRight;  
        List<Integer> inOrderLeft;  
        List<Integer> inOrderRight;  
          
        // 获得在 inOrder中,根的位置  
        int rootInIndex = inOrder.indexOf(preOrder.get(0));  
        preOrderLeft = preOrder.subList(1, rootInIndex + 1);  
        preOrderRight = preOrder.subList(rootInIndex + 1, preOrder.size());  
          
        // 得到inOrder左边的左子树  
        inOrderLeft = inOrder.subList(0, rootInIndex);  
        inOrderRight = inOrder.subList(rootInIndex + 1, inOrder.size());  
  
        // 通过 Rec 来调用生成左右子树。  
        root.left = rebuildBinaryTreeRec(preOrderLeft, inOrderLeft);  
        root.right = rebuildBinaryTreeRec(preOrderRight, inOrderRight);  
          
        return root;          
    }  

/* 
 *  *  求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel  
 * */  
    public static int getNodeNumKthLevel(TreeNode root, int k) {  
        if (root == null || k <= 0) {  
            return 0;  
        }  
          
        int level = 0;  
          
        Queue<TreeNode> q = new LinkedList<TreeNode>();  
        q.offer(root);  
          
        TreeNode dummy = new TreeNode(0);  
        int cnt = 0; // record the size of the level.  
          
        q.offer(dummy);  
        while (!q.isEmpty()) {  
            TreeNode node = q.poll();  
              
            if (node == dummy) {  
                level++;  
                if (level == k) {  
                    return cnt;  
                }  
                cnt = 0; // reset the cnt;  
                if (q.isEmpty()) {  
                    break;  
                }  
                q.offer(dummy);  
                continue;  
            }  
              
            cnt++;  
            if (node.left != null) {  
                q.offer(node.left);  
            }  
              
            if (node.right != null) {  
                q.offer(node.right);  
            }  
        }  
          
        return 0;  
    }  
 /* 
     *  *  求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel  
     * */  
    public static int getNodeNumKthLevelRec(TreeNode root, int k) {  
        if (root == null || k <= 0) {  
            return 0;  
        }  
          
        if (k == 1) {  
            return 1;  
        }  
          
        // 将左子树及右子树在K层的节点个数相加.  
        return getNodeNumKthLevelRec(root.left, k - 1) + getNodeNumKthLevelRec(root.right, k - 1);  
    }  



/* 
     *  * 12. 求二叉树中节点的最大距离:getMaxDistanceRec 
     *   
     *  首先我们来定义这个距离: 
     *  距离定义为:两个节点间边的数目. 
     *  如: 
     *     1 
     *    / \ 
     *   2   3 
     *        \ 
     *         4 
     *   这里最大距离定义为2,4的距离,为3.       
     * 求二叉树中节点的最大距离 即二叉树中相距最远的两个节点之间的距离。 (distance / diameter)  
     * 递归解法: 
     * 返回值设计: 
     * 返回1. 深度, 2. 当前树的最长距离   
     * (1) 计算左子树的深度,右子树深度,左子树独立的链条长度,右子树独立的链条长度 
     * (2) 最大长度为三者之最: 
     *    a. 通过根节点的链,为左右深度+2 
     *    b. 左子树独立链 
     *    c. 右子树独立链。 
     *  
     * (3)递归初始条件: 
     *   当root == null, depth = -1.maxDistance = -1; 
     *    
     */    
    public static int getMaxDistanceRec(TreeNode root) {  
        return getMaxDistanceRecHelp(root).maxDistance;  
    }  
      
    public static Result getMaxDistanceRecHelp(TreeNode root) {  
        Result ret = new Result(-1, -1);  
          
        if (root == null) {  
            return ret;  
        }  
          
        Result left = getMaxDistanceRecHelp(root.left);  
        Result right = getMaxDistanceRecHelp(root.right);  
          
        // 深度应加1, the depth from the subtree to the root.  
        ret.depth = Math.max(left.depth, right.depth) + 1;  
          
        // 左子树,右子树与根的距离都要加1,所以通过根节点的路径为两边深度+2  
        int crossLen = left.depth + right.depth + 2;  
          
        // 求出cross根的路径,及左右子树的独立路径,这三者路径的最大值。  
        ret.maxDistance = Math.max(left.maxDistance, right.maxDistance);  
        ret.maxDistance = Math.max(ret.maxDistance, crossLen);  
          
        return ret;  
    }  
  
      
    private static class Result {  
        int depth;  
        int maxDistance;  
        public Result(int depth, int maxDistance) {  
            this.depth = depth;  
            this.maxDistance = maxDistance;  
        }  
    }  



 /* 
     * .求叶子节点个数 getNodeNumLeafRec  把左子树和右子树的叶子节点加在一起即可 
     * */  
    public static int getNodeNumLeafRec(TreeNode root) {  
        if (root == null) {  
            return 0;  
        }  
          
        if (root.left == null && root.right == null) {  
            return 1;  
        }  
          
        return getNodeNumLeafRec(root.left) + getNodeNumLeafRec(root.right);  
    }  
      
  

 /* 7. getNodeNumLeaf 
     * 随便使用一种遍历方法都可以,比如,中序遍历。 
     * inorderTraversal,判断是不是叶子节点。 
     * */  
    public static int getNodeNumLeaf(TreeNode root) {  
        if (root == null) {  
            return 0;  
        }  
          
        int cnt = 0;  
          
        // we can use inorderTraversal travesal to do it.  
        Stack<TreeNode> s = new Stack<TreeNode>();  
        TreeNode cur = root;  
          
        while (true) {  
            while (cur != null) {  
                s.push(cur);  
                cur = cur.left;  
            }  
              
            if (s.isEmpty()) {  
                break;  
            }  
              
            // all the left child has been put into the stack, let's deal with the   
            // current node.  
            cur = s.pop();  
            if (cur.left == null && cur.right == null) {  
                cnt++;  
            }  
            cur = cur.right;  
        }  
          
        return cnt;  
    }  


转自:http://blog.csdn.net/yangcs2009/article/details/40146967


/** 
     * 求二叉树中两个节点的最低公共祖先节点  
     * 递归解法:  
     * (1)如果两个节点分别在根节点的左子树和右子树,则返回根节点 
     * (2)如果两个节点都在左子树,则递归处理左子树;如果两个节点都在右子树,则递归处理右子树 
     */  
    public static TreeNode getLastCommonParentRec(TreeNode root, TreeNode n1, TreeNode n2) {  
        if (findNodeRec(root.left, n1)) {               // 如果n1在树的左子树  
            if (findNodeRec(root.right, n2)) {      // 如果n2在树的右子树  
                return root;                                // 返回根节点  
            } else {            // 如果n2也在树的左子树  
                return getLastCommonParentRec(root.left, n1, n2); // 递归处理  
            }  
        } else {                // 如果n1在树的右子树  
            if (findNodeRec(root.left, n2)) {           // 如果n2在左子树  
                return root;  
            } else {                 // 如果n2在右子树  
                return getLastCommonParentRec(root.right, n1, n2); // 递归处理  
            }  
        }  
    }  
  
    // 帮助方法,递归判断一个点是否在树里  
    private static boolean findNodeRec(TreeNode root, TreeNode node) {  
        if (root == null || node == null) {  
            return false;  
        }  
        if (root == node) {  
            return true;  
        }  
  
        // 先尝试在左子树中查找  
        boolean found = findNodeRec(root.left, node);  
        if (!found) {       // 如果查找不到,再在右子树中查找  
            found = findNodeRec(root.right, node);  
        }  
        return found;  
    }  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值