算法整理-二叉树

参考Java实现二叉树算法
自己重写了部分代码,便于巩固和复习,其中最后几个题目没有测试,后两个题目没有实现,有点难度,以后有机会再去探索。

package com.xpn.tree;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

import javax.naming.LinkLoopException;
import javax.swing.RootPaneContainer;

/** 
 * http://blog.csdn.net/luckyxiaoqiang/article/details/7518888  轻松搞定面试中的二叉树题目 
 * http://www.cnblogs.com/Jax/archive/2009/12/28/1633691.html  算法大全(3) 二叉树 
 *  
 * TODO: 一定要能熟练地写出所有问题的递归和非递归做法! 
 * 
 * 1. 求二叉树中的节点个数: getNodeNumRec(递归),getNodeNum(迭代) 
 * 2. 求二叉树的深度: getDepthRec(递归),getDepth  
 * 3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec 
 * (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2) 
 * 4.分层遍历二叉树(按层次从上往下,从左往右): levelTraversal, levelTraversalRec(递归解法!) 
 * 5. 将二叉查找树变为有序的双向链表: convertBST2DLLRec, convertBST2DLL 
 * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel 
 * 7. 求二叉树中叶子节点的个数:getNodeNumLeafRec, getNodeNumLeaf 
 * 8. 判断两棵二叉树是否相同的树:isSameRec, isSame 
 * 9. 判断二叉树是不是平衡二叉树:isAVLRec 
 * 10. 求二叉树的镜像(破坏和不破坏原来的树两种情况):mirrorRec, mirrorCopyRec 
 * 10.1 判断两个树是否互相镜像:isMirrorRec 
 * 11. 求二叉树中两个节点的最低公共祖先节点:getLastCommonParent, getLastCommonParentRec, getLastCommonParentRec2 
 * 12. 求二叉树中节点的最大距离:getMaxDistanceRec 
 * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec 
 * 14.判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec 
 *  
 */ 
public class Main {

    /**
     * @param args
     * 
                 1  
                / \  
               2   3  
              / \   \  
             4  5   6  
     */  
    private static class TreeNode {  
        int val;  
        TreeNode left;  
        TreeNode right;  

        public TreeNode(int val) {  
            this.val = val;  
        }  
    }  
    public static void main(String[] args) {
        TreeNode r1 = new TreeNode(1);  
        TreeNode r2 = new TreeNode(2);  
        TreeNode r3 = new TreeNode(3);  
        TreeNode r4 = new TreeNode(4);  
        TreeNode r5 = new TreeNode(5);  
        TreeNode r6 = new TreeNode(6);  

        r1.left = r2;  
        r1.right = r3;  
        r2.left = r4;  
        r2.right = r5;  
        r3.right = r6;  
        System.out.println(getNodeNumLeaf(r1));

    }
    //1. 求二叉树中的节点个数: getNodeNumRec(递归),getNodeNum(迭代) 
    private static int getNodeNumRec(TreeNode root){
        if(root==null)
            return 0;

        return getNodeNumRec(root.left)+getNodeNumRec(root.right)+1;

    }
    private static int getNodeNum(TreeNode root){
        if(root==null)
            return 0;
        Stack<TreeNode> stacks=new Stack<TreeNode>();
        stacks.push(root);
        int len=0;
        while(!stacks.empty()){//层次遍历
            TreeNode cur=stacks.pop();
            len++;
            if(cur.left!=null){
                stacks.push(cur.left);
            }
            if(cur.right!=null){
                stacks.push(cur.right);
            }
        }
        return len;
    }
    //2. 求二叉树的深度: getDepthRec(递归),getDepth 
    private static int getDepthRec(TreeNode root){
        if(root==null){
            return 0;
        }
        return getDepthRec(root.left)>getDepthRec(root.right)
                ?getDepthRec(root.left)+1:getDepthRec(root.right)+1;
    }
    private static int getDepth(TreeNode root){
        if(root==null){
            return 0;
        }
        int depth=0;
        int curNodes=1;//当前层的节点数
        int nextNodes=0;//下一层的节点数
        LinkedList<TreeNode> queue=new LinkedList<TreeNode>() ;
        queue.add(root);
        while(!queue.isEmpty()){
            curNodes--;
            TreeNode cur=queue.remove();
            if(cur.left!=null){
                nextNodes++;
                queue.add(cur.left);
            }
            if(cur.right!=null){
                queue.add(cur.right);
                nextNodes++;
            }
            if(curNodes==0){//当前层遍历完毕
                depth++;
                curNodes=nextNodes;
                nextNodes=0;
            }
        }
        return depth;
    }
    //3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec 
     //* (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2) 
    private static void preorderTraversalRec(TreeNode root){
        if(root==null)
            return;
        System.out.print(root.val+" ");
        if(root.left!=null){
            preorderTraversalRec(root.left);
        }
        if(root.right!=null){
            preorderTraversalRec(root.right);
        }
    }
    private static void preorderTraversal(TreeNode root){
        if(root==null)
            return;
        Stack<TreeNode> stacks=new Stack<TreeNode>();
        stacks.push(root);
        while(!stacks.empty()){
            TreeNode cur=stacks.pop();
            System.out.print(cur.val + " ");
            if(cur.right!=null){
                stacks.push(cur.right);
            }
            if(cur.left!=null){
                stacks.push(cur.left);
            }
        }
    }

    private static void inorderTraversalRec(TreeNode root){
        if(root==null)
            return;
        inorderTraversalRec(root.left);
        System.out.print(root.val+" ");
        inorderTraversalRec(root.right);
    }
    private static void inorderTraversal(TreeNode root){
        if(root==null)
            return;
        Stack<TreeNode> stacks=new Stack<TreeNode>();
        TreeNode cur=root;
        while(true){
            while(cur!=null){
                stacks.push(cur);
                cur=cur.left;
            }//查找最左边的
            if(stacks.empty()){
                break;
            }
            cur=stacks.pop();
            System.out.print(cur.val+" ");
            cur=cur.right;
        }
    }
    private static void postorderTraversalRec(TreeNode root){
        if(root==null){
            return;
        }
        postorderTraversalRec(root.left);
        postorderTraversalRec(root.right);
        System.out.print(root.val+" ");
    }
    private static void postorderTraversal(TreeNode root){
        if(root==null){
            return;
        }
        //两个stack进行维护
        Stack<TreeNode> stacks=new Stack<TreeNode>();
        Stack<TreeNode> result=new Stack<TreeNode>();//存放结果的栈
        stacks.push(root);
        TreeNode cur=null;
        while(!stacks.empty()){
            cur=stacks.pop();
            result.push(cur);
            if(cur.left!=null){
                stacks.push(cur.left);
            }
            if(cur.right!=null){
                stacks.push(cur.right);
            }
        }
        while(!result.empty()){
            System.out.print(result.pop().val+" ");
        }

    }

    //4.分层遍历二叉树(按层次从上往下,从左往右): levelTraversal, levelTraversalRec(递归解法!)
    private static void levelTraversal(TreeNode root){
        if(root==null)
            return;
        LinkedList<TreeNode> queue=new LinkedList<TreeNode>();
        queue.add(root);
        TreeNode cur=null;//队列实现层次遍历
        while(!queue.isEmpty()){
            cur=queue.pop();
            System.out.print(cur.val+" ");
            if(cur.left!=null){
                queue.add(cur.left);
            }
            if(cur.right!=null){
                queue.add(cur.right);
            }
        }
    }
    //比较难,使用列表嵌套列表,将每一层的元素作为一个列表进行存储

    private static void levelTraversalRec(TreeNode root){
        if(root==null)
            return;
        List<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
        dfs(root, 0, res);
        System.out.println(res);


    }
    private static void dfs(TreeNode root,int level,List<ArrayList<Integer>> res){
        if(root==null)
            return;
        if(level>=res.size()){//添加新的层
            res.add(new ArrayList<Integer>());
        }
        res.get(level).add(root.val);
        dfs(root.left, level+1, res);
        dfs(root.right, level+1, res);

    }
    //5. 将二叉查找树变为有序的双向链表: convertBST2DLLRec, convertBST2DLL 
    private static void convertBST2DLLRec(TreeNode root) {
        if(root==null)
            return;
        root=convertBST2DLLsubRec(root);
        while(root.left!=null){
            root=root.left;
        }
    }
    private static TreeNode convertBST2DLLsubRec(TreeNode root) {
        if(root==null||root.left==null&&root.right==null)
            return root;
        TreeNode tmp=null;
        if(root.left!=null){
            tmp=convertBST2DLLsubRec(root.left);//处理左子节点
            while(tmp.right!=null){//找最右节点
                tmp=tmp.right;
            }
            tmp.right=root;
            root.left=tmp;
        }
        if(root.right!=null){
            tmp=convertBST2DLLsubRec(root.right);//处理右子节点
            while(tmp.left!=null){//找最左节点
                tmp=tmp.left;
            }
            tmp.left=root;
            root.right=tmp;
        }
        return root;
    }
    //中序遍历进行修改
    private static TreeNode convertBST2DLL(TreeNode root) {
        TreeNode head=null;
        TreeNode cur=root;
        Stack<TreeNode> stacks=new Stack<TreeNode>();
        TreeNode old = null;            // 指向前一个处理的节点  
        while(true){
            while(cur!=null){
                stacks.push(cur);
                cur=cur.left;
            }
            if(stacks.empty()){
                break;
            }
            // 因为此时已经没有左孩子了,所以输出栈顶元素
            cur=stacks.pop();
            if(old!=null)
                old.right=cur;
            if(head == null){       // /第一个节点为双向链表头节点  
                head = cur;  
            } 
            old=cur;
            cur=cur.right;

        }
        return head;
    }
    //6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel 
    private static int getNodeNumKthLevelRec(TreeNode root,int k) {
        if(root==null||k<=0)
            return 0;
        if(k==1)
            return 1;
        return getNodeNumKthLevelRec(root.left, k-1)+getNodeNumKthLevelRec(root.right, k-1);

    }
    //队列 层次遍历
    private static int getNodeNumKthLevel(TreeNode root,int k) {
        if(root==null||k<=0)
            return 0;
        if(k==1)
            return 1;
        int curNodes=1;
        int nextNodes=0;
        TreeNode cur=root;
        LinkedList<TreeNode> queue=new LinkedList<TreeNode>();
        queue.push(cur);
        int i=1;
        while (!queue.isEmpty()&& i<k) {
            cur=queue.remove();
            curNodes--;
            if(cur.left!=null){
                queue.add(cur.left);
                nextNodes++;
            }
            if(cur.right!=null){
                queue.add(cur.right);
                nextNodes++;
            }
            if(curNodes==0){
                curNodes=nextNodes;
                nextNodes=0;
                i++;
            }

        }
        return curNodes;
    }
    //7. 求二叉树中叶子节点的个数:getNodeNumLeafRec, getNodeNumLeaf 
    private 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);
    }
    private static int getNodeNumLeaf(TreeNode root){
        if(root==null){
            return 0;
        }
        int counts=0;
        Stack<TreeNode> stacks=new Stack<TreeNode>();
        stacks.push(root);
        TreeNode cur=null;
        while(!stacks.empty()){
            cur=stacks.pop();
            if(cur.right!=null){
                stacks.push(cur.right);
            }
            if(cur.left!=null){
                stacks.push(cur.left);
            }
            if(cur.left==null&&cur.right==null){
                counts++;
            }
        }
        return counts;
    }
    //8. 判断两棵二叉树是否相同的树:isSameRec, isSame 
    private static boolean isSameRec(TreeNode t1,TreeNode t2){
        if(t1==null&&t2==null)
            return true;
        if(t1==null||t2==null)
            return false;
        if(t1.val==t2.val)
            return true;
        return isSameRec(t1.left, t2.left)&&isSameRec(t1.right, t2.right);
    }
    private static boolean isSame(TreeNode t1,TreeNode t2){
        if(t1==null&&t2==null)
            return true;
        if(t1==null||t2==null)
            return false;
        Stack<TreeNode> s1=new Stack<TreeNode>();
        Stack<TreeNode> s2=new Stack<TreeNode>();
        s1.push(t1);
        s2.push(t2);
        TreeNode cur1=null;
        TreeNode cur2=null;
        while(!s1.empty()&&!s2.empty()){
            cur1=s1.pop();
            cur2=s2.pop();
            if(cur1.left!=null)
                s1.push(cur1.left);
            if(cur1.right!=null)
                s1.push(cur1.right);
            if(cur2.left!=null)
                s2.push(cur2.left);
            if(cur2.right!=null)
                s2.push(cur2.left);
            if(cur1.val!=cur2.val)
                return false;
        }
        if(!s1.empty()||!s2.empty())
            return false;
        return true;


    }
    //9. 判断二叉树是不是平衡二叉树:isAVLRec
    private static boolean isAVLRec(TreeNode root){
        if(root==null)
            return true;
        if(Math.abs(getDepth(root.left)-getDepth(root.right))>1)
            return false;
        return isAVLRec(root.left)&&isAVLRec(root.right);
    }
    //10. 求二叉树的镜像(破坏和不破坏原来的树两种情况):mirrorRec, mirrorCopyRec 
    // 10.1 判断两个树是否互相镜像:isMirrorRec 
    private static TreeNode mirrorRec(TreeNode root){
        if(root==null)
            return null;
        TreeNode tmp=mirrorRec(root.left);
        root.left=mirrorRec(root.right);
        root.right=tmp;
        return root;
    }
    //11. 求二叉树中两个节点的最低公共祖先节点:getLastCommonParent, getLastCommonParentRec, getLastCommonParentRec2 
    private static TreeNode getLastCommonParentRec(TreeNode root,TreeNode t1,TreeNode t2){
        if(findNodeRec(root.left,t1)){//t1在左子树
            if(findNodeRec(root.right, t2))//t2在右子树
                return root;
            else {
                return getLastCommonParentRec(root.left, t1, t2);
            }
        }else {
            if(findNodeRec(root.left, t2))//t2在左子树
            {
                return root;
            }else {
                return getLastCommonParentRec(root.right, t1, t2);
            }

        }
    }
     // 帮助方法,递归判断一个点是否在树里  
    private static boolean findNodeRec(TreeNode root, TreeNode node) { 
        if(root==null||node==null)
            return false;
        if(root==node){
            return true;
        }
        boolean isfound=findNodeRec(root.left, node);
        if(!isfound)
            isfound=findNodeRec(root.right, node);
        return isfound;

    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值