二叉树相关

1.计算二叉树的高度,两种方式

这里给的是哪些节点连接,所以先处理一下这些节点,把它变为二叉树。

static class Node{
        int data;
        private Node lchild;
        private Node rchild;
        Node(int data){
           this.data = data;
        }
    }

    public static int  GetBTreeDepth(Node node)//递归的思路
    {
        if( node == null )
            return 0;     
        int lDepth =GetBTreeDepth(node.lchild);
        int rDepth =GetBTreeDepth(node.rchild);     
        return ((( lDepth > rDepth )? lDepth: rDepth) + 1 );        
    }
    public static int QueueDepth(Node node)    //通过队列层次遍历的思路
    {
        if(node==null) return 0;
        Queue<Node> queue = new LinkedList<Node>();
        queue.add(node);
        int num=0;
        while(!queue.isEmpty()) {
            num++;
            int size=queue.size();        
            for(int i=0;i<size;i++) {
                Node temp=queue.poll();
                if(temp.lchild!=null) queue.add(temp.lchild);
                if(temp.rchild!=null) queue.add(temp.rchild);
            }        
        }
        return num;
    }
    public static void main(String[] args){          
        Scanner in = new Scanner(System.in);
        int n=in.nextInt();
        Queue<Node> queue = new LinkedList<Node>();
        int[][] num=new int[n-1][2];
        int[] lable=new int[n-1];       
        for(int j=0;j<n-1;j++)  {       
            num[j][0]=in.nextInt();
            num[j][1]=in.nextInt();               
        }   
        Node head=new Node(1);
        queue.add(head);
        while(!queue.isEmpty()) {
            Node temp=queue.poll();
            for(int i=0;i<num.length;i++) {
                if(num[i][0]==temp.data&&lable[i]==0)
                {        
                    Node left=new Node(num[i][1]);
                    if(temp.lchild==null)
                       temp.lchild=left;
                    else
                       temp.rchild=left;
                    queue.add(left);
                    lable[i]=1;                              
                    continue;
                }
                if(num[i][1]==temp.data&&lable[i]==0) {
                    Node right=new Node(num[i][0]);
                    temp.rchild=right;
                    queue.add(right);
                    lable[i]=1;                 
                    continue;
                }               
            }       
        }    
    }

2.计算二叉树的宽度,还是通过队列计算每一层节点的个数

public static int GEtBtreeBith(Node node,int n) {
        int[] num=new int[n+1];
        if(node==null) return 0;
        Queue<Node> queue = new LinkedList<Node>();
        queue.add(node);
        int i=0;
        while(!queue.isEmpty()) {
            i++;
            int size=queue.size();
            num[i]=size;
            for(int j=0;j<size;j++) {
                Node temp=queue.poll();
                if(temp.lchild!=null) queue.add(temp.lchild);
                if(temp.rchild!=null) queue.add(temp.rchild);
            }        
        }
        int maxLen=0;
        for(int k=1;k<n+1;k++) {
            if(num[k]>maxLen)
              maxLen=num[k];
        }
        return maxLen;
    }

3.二叉树的先序中序后序的非递归形式

//先序
public
static void preOrder(TreeNode head) { Stack<TreeNode> stack=new Stack<>(); if(head!=null) { stack.push(head); while(!stack.isEmpty()) { TreeNode temp=stack.pop(); System.out.print(temp.val+"->"); if(temp.right!=null) stack.push(temp.right); if(temp.left!=null) stack.push(temp.left); } }
}

 

//中序
public
static void inOrder(TreeNode head) { Stack<TreeNode> stack=new Stack<>(); if(head!=null) { TreeNode temp=head; while(!stack.isEmpty()||temp!=null) { while(temp!=null) { stack.push(temp); temp=temp.left; } if(!stack.isEmpty()) { temp=stack.pop(); System.out.print(temp.val+"-"); temp=temp.right; } } } }
//后序
public
static void postOrder(TreeNode head) { int flag; //用来表示是否在处理栈顶标志,1就是处理栈顶 Stack<TreeNode> stack=new Stack<>(); TreeNode p; //用来判断是否前一个已经访问的节点 if(head!=null) { TreeNode temp=head; do { while(temp!=null) { stack.push(temp); temp=temp.left; } p=null; flag=1; while(!stack.isEmpty()&&flag==1) { temp=stack.peek(); if(temp.right==p) { System.out.print(temp.val+"-"); stack.pop(); p=temp; } else { temp=temp.right; flag=0; } } } while(!stack.isEmpty()); } }

给定一个数组,判断它是不是 某个二叉排序树的后序遍历的顺序

BST的后序序列的合法序列是,对于一个序列S,最后一个元素是x (也就是根),如果去掉最后一个元素的序列为T,那么T满足:T可以分成两段,前一段(左子树)小于x,后一段(右子树)大于x,且这两段(子树)都是合法的后序序列。完美的递归定义 : ) 。

public boolean VerifySquenceOfBST(int [] sequence) {
        if(sequence.length == 0){
            return false;
        }
        if(sequence.length == 1){
            return true;
        }
        return judge(sequence,0,sequence.length-1);
}         
public boolean judge(int[] a,int start,int end){
        if(start>=end) return true;
        int root=a[end];
        int i=start;
        while(a[i]<root) {
            i++;
        }
        for(int j=i;j<end;j++) {
            if(a[j]<root) 
              return false;
        }
        return judge(a,start,i-1)&&judge(a,i,end-1);
}

4.给定前序和中序,重建二叉树

public static TreeNode reConstructBinaryTree(int[] pre,int[] in) {
        if(pre.length==0||in.length==0) return null;
        TreeNode head=new TreeNode(pre[0]);
        int mid=0;
        for(int i=0;i<in.length;i++) {
            if(pre[0]==in[i]) { 
                mid=i;
                break;
            }
        }
        int[] inleft=Arrays.copyOfRange(in, 0, mid);
        int[] preleft=Arrays.copyOfRange(pre, 1, mid+1);
        
        int[] inright=Arrays.copyOfRange(in, mid+1, in.length);
        int[] preright=Arrays.copyOfRange(pre, mid+1, pre.length);
        head.left=reConstructBinaryTree(preleft, inleft);
        head.right=reConstructBinaryTree(preright, inright);
        return head;
    }

 5.输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。

深度优先搜索的方式:

    private ArrayList<ArrayList<Integer>> listAll = new ArrayList<ArrayList<Integer>>();
    private ArrayList<Integer> list = new ArrayList<Integer>();
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        if(root == null) return listAll;
        list.add(root.val);
        target -= root.val;
        if(target == 0 && root.left == null && root.right == null)
            listAll.add(new ArrayList<Integer>(list));
        FindPath(root.left, target);
        FindPath(root.right, target);
        list.remove(list.size()-1);
        return listAll;
}

用上面的方法打印从头结点到根节点的最长路径:

 

int max=0;
    ArrayList<Integer> list=new ArrayList<>();
    public void maxLength(Node head) {
        if(head==null) return;
        list.add(head.data);
        if(head.lchild==null&&head.rchild==null) {
            int temp=0;
            for(Integer i:list) {
                temp+=i;
            }
            max=Math.max(temp, max);
        }
        maxLength(head.lchild);
        maxLength(head.rchild);
        list.remove(list.size()-1);
    }

 

6.判断一棵二叉树是不是平衡二叉树

public int getDepth(TreeNode root){
        if(root==null)
            return 0;
        int left=getDepth(root.left);
        int right=getDepth(root.right);    
        if(Math.abs(left-right)>1){
            isBalanced=false;
        }
        return right>left ?right+1:left+1;
         
    }

 7.二插排序树的第k个节点

通过非递归的中序遍历,在输出的地方加一个计数

8.判断二叉树是不是完全二叉树

思想:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。

有如下算法,按层次(从上到下,从左到右)遍历二叉树,当遇到一个节点的左子树为空时,则该节点右子树必须为空,且后面遍历的节点左

右子树都必须为空,否则不是完全二叉树。

public boolean isCompleteBinaryTree(TreeNode head) {
        if (head == null)
            return true;
        boolean lable = false;//是否需要左右孩子都为空的标志
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.add(head);
        while (!queue.isEmpty()) {
            TreeNode temp = queue.poll();
            if (lable) {//需要左右孩子都为空
                if (temp.left != null || temp.right != null)
                    return false;
            } else {
                if (temp.left != null && temp.right != null) {
                    queue.add(temp.left);
                    queue.add(temp.right);
                } else if (temp.left != null) {//左孩子不为空,右孩子为空,后面的节点都不能有左右孩子了
                    queue.add(temp.left);
                    lable = true;
                } else if (temp.right != null) {//出现了左孩子为空,右孩子不为空的情况,直接返回false
                    return false;
                } else {//当前节点左右孩子节点都为空,那么后面的节点也必须是这样
                    lable = true;
                }
            }
        }
        return true;
    }

9.求二叉树中叶子节点的个数

public static int LeafNum(TreeNode head) {
        if(head==null) return 0;
        if(head.left==null&&head.right==null) return 1;
        int numLeft=LeafNum(head.left);
        int numRight=LeafNum(head.right);
        return numLeft+numRight;
    }

10.求二叉树的镜像:

public static TreeNode Mirror(TreeNode head){
       if(head==null) return null;
       TreeNode pLeft=Mirror(head.left);
       TreeNode pRight=Mirror(head.right);
       head.left=pRight;
       head.right=pLeft;
       return head;
} 

非递归解法:

 

public void Minor(Node node)    //通过队列层次遍历的思路
    {
        if(node==null) return;
        Queue<Node> queue = new LinkedList<Node>();
        queue.add(node);
        while(!queue.isEmpty()) {
            int size=queue.size();        
            for(int i=0;i<size;i++) {
                Node temp=queue.poll();
                System.out.print(temp.data+" ");
                if(temp.rchild!=null) queue.add(temp.rchild);
                if(temp.lchild!=null) queue.add(temp.lchild);
                
            }   
            System.out.println();
        }
    }

 

 

11.求二叉树的直径leetcode543

public int helper(TreeNode root) {
        if(root==null) return 0;
        int ldepth=helper(root.left);
        int rdepth=helper(root.right);
        max=Math.max(max, ldepth+rdepth);
        return 1+Math.max(ldepth, rdepth);
    }

 12.二叉查找树的查找和插入(删除太麻烦了)

public TreeNode BSTSearch(TreeNode root,int k) {       
        TreeNode cur=root;
        if(root==null) return null;        
        else if(cur.val==k) {
            return cur;
        }else if(k<cur.val) {
            return BSTSearch(root.left,k);
        }
        else
            return BSTSearch(root.right,k);
    }
    public int BSTInsert(TreeNode root,int k) {
        TreeNode cur=root;
        if(cur==null) {
            cur=new TreeNode(k);
            cur.left=null;
            cur.right=null;
            return 1;
        }
        else if(cur.val==k) {
            return 0;//存在相同的,返回0,不插入
        }
        else if(k<cur.val) {
            return BSTInsert(cur.left, k);
        }
        else
            return BSTInsert(cur.right, k);
    }

 13.两颗二叉树A,B判断B是不是A的子结构

public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root1==null||root2==null) return false;
        return isSubtree(root1, root2)||HasSubtree(root1.left, root2)||HasSubtree(root1.right, root2);
    }
public boolean isSubtree(TreeNode root1,TreeNode root2){
        if(root2==null) return true;
        if(root1==null) return false;
        if(root1.val==root2.val)
            return isSubtree(root1.left,root2.left)&&isSubtree(root1.right,root2.right);
        else
            return false;
}

 14.在一个二叉搜索树中,使得当前节点的值等于大于等于它的节点的值的和。

中序遍历中,当前节点后面的节点都是大于当前节点的,所以我们用反向中序遍历

private int mid(Node root,int exp){
     if (root == null) {
            return exp;
     }
     int right = mid(root.rchild,exp);
     root.data += right;
     int left = mid(root.lchild,root.data);
     return left;
}

非递归写法

private void mid(Node root){
          Stack<Node> stack=new Stack<>();
          int help=0;
          if(root!=null) {
                Node temp=root;
                while(!stack.isEmpty()||temp!=null) {
                    while(temp!=null) {
                        stack.push(temp);
                        temp=temp.rchild;
                    }
                    if(!stack.isEmpty()) {
                        temp=stack.pop();
                        temp.data+=help;
                        help=temp.data;                        
                        System.out.print(temp.data+"-");
                        temp=temp.lchild;
                    }
                }
            }
    }

 15.逆时针打印二叉树的最外面一圈节点

public void printleft(TreeNode root,boolean print) {
        if(root==null) return;
        if(print||(root.left==null&&root.right==null)) {
            System.out.print(root.data+"-");
        }
        printleft(root.left,print);//左边是一定要打的
        printleft(root.right,print&&root.left==null?true:false);//左边延伸为空的话打印右分支
        return;
    }
    public void printright(TreeNode root,boolean print) {
        if(root==null) return;
        printright(root.left,print&&root.right==null?true:false);//右分支为空就打印左分支
        printright(root.right,print);
        if(print||(root.left==null&&root.right==null))
            System.out.print(root.data+"-");
        return;
    }
    public void printhead(TreeNode root) {
        if(root==null) return;
        System.out.print(root.data+"-");
        if(root.left!=null&&root.right!=null) {
            printleft(root.left,true);
            printright(root.right,true);
        }
        else
        {
            printhead(root.left!=null?root.left:root.right);
        }
        return;
    }

https://www.cnblogs.com/PrimeLife/p/5460513.html

 16.找任意两个节点的最近公共祖先:

递归:

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        //如果找到 p 或者 q 那么就没有必要接着递归,因为共同祖先只可能是该节点或该节点祖先
        //如果 root 为空了,说明这条路径上不可能有 p 或 q 节点,返回空
        if(root == null || root == p || root == q) return root;
        TreeNode left = lowestCommonAncestor(root.left, p, q);  //往左分支上寻找
        TreeNode right = lowestCommonAncestor(root.right, p, q);  //往右分支上寻找
        if(left != null && right != null) return root;  //说明 p 和 q 是分布在 root 两侧,返回即可
        if(left != null) return left;  //说明在 left 分支上找到 p 或 q 节点,返回即可
        return right;  //否则返回 right
    }

非递归:

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        HashMap<TreeNode, TreeNode> parent = new HashMap<>();
        parent.put(root, null);
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while(!parent.containsKey(p) || !parent.containsKey(q)) {  //找到 p 和 q 的父节点
            root = queue.poll();
            if(root != null) {
                parent.put(root.left, root);
                parent.put(root.right, root);
                queue.add(root.left);
                queue.add(root.right);
            }
        }
        HashSet<TreeNode> set = new HashSet<>();
        while(p != null) {  //将 p 的所有父节点放入 set 中
            set.add(p);
            p = parent.get(p);
        }
        while(!set.contains(q)) {  //找到公共父节点就返回
            q = parent.get(q);
        }
        return q;
    }

 

posted @ 2019-04-13 21:26  LeeJuly  阅读(204)  评论(0)    收藏  举报