二叉树 BinaryTree

二叉树

二叉树有左子树,右子树之分,因此是一个有序树

二叉树分为  满二叉树 和 完全二叉树

满二叉树是一种特殊的完全二叉树。

 二叉树的性质:

结论3的推导过程:

通过性质  做两道题:

自己简单实现一个二叉树

二叉树的遍历(通过递归实现)

前序遍历,中序遍历,后序遍历

package dataStructBinaryTree;

public class MyBinaryTree {

    static class TreeNode{
        public char val;  // 数据域
        public TreeNode left;  //左孩子引用
        public TreeNode right; // 有孩子引用

        public TreeNode(char val) {
            this.val = val;
        }
    }

    public TreeNode root; // 根节点

    public TreeNode createTree(){
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        TreeNode H = new TreeNode('H');
        A.left = B;
        A.right = C;
        B.left = D;
        B.right = E;
        C.left = F;
        C.right = G;
        E.right = H;
        this.root = A;
        return root;
    }

    // 前序遍历
    public void preOrder(TreeNode root){
        if(root == null){
            return;
        }
        System.out.print(root.val+" ");
        preOrder(root.left);
        preOrder(root.right);
    }


    // 中序遍历
    void inOrder(TreeNode root){
        if (root == null){
            return;
        }
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }


    // 后序遍历
    void postOrder(TreeNode root){
        if(root == null){
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val+" ");
    }


}

二叉树的层序遍历 (*

102. 二叉树的层序遍历 - 力扣(LeetCode)

思路:

如图,可以建立一个队列 来按顺序输出 从上到下,从左到右的二叉树

定义一个中间变量 cur

从队列弹出pop一个元素赋值给cur,打印这个元素,然后将cur的左子树,右子树 入队列

然后再弹出队列的下一个元素

依次循环下去,直到队列为空。

class Solution {
    public void levelOrder(TreeNode root) {
        if (root == null){
            return null;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()){
                TreeNode cur = queue.poll();
                System.out.println(cur.val +" ");
                if (cur.left != null){
                    queue.offer(cur.left);
                }
                if (cur.right != null){
                    queue.offer(cur.right);
                }
            }
    }

}

而在本题中,要求输出的是一个二维List , 因此要多一次循环生成二维顺序表

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> list = new ArrayList<>();
        if (root == null){
            return list;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()){
            int size = queue.size();
            List<Integer> tmp = new ArrayList<>();
            while (size>0){
                TreeNode cur = queue.poll();
                tmp.add(cur.val);
                size--;
                if (cur.left != null){
                    queue.offer(cur.left);
                }
                if (cur.right != null){
                    queue.offer(cur.right);
                }
            }
            list.add(tmp);
        }
        return list;
    }

}

思考:

如何输出二叉树的左视图?                 

假设为下图:

则此图 的左视图 就为 A B E H

使用层序遍历方法,即为 求每一层 的第一个元素

右视图 同理。。。。

二叉树的常用方法


//    子问题法 (递归)  求 节点个数    
// 获取树中节点的个数
    public int size(TreeNode root){
        if(root == null){
            return 0;
        }
        int count = 1;
        int leftCount = size(root.left);
        int rightCount = size(root.right);
        count = count + leftCount + rightCount;
        return count;
    }

//    遍历法求 节点个数
//    public int usedSize;
//    public void size2(TreeNode root){
//        if(root == null){
//            return;
//        }
//        usedSize++;
//        preOrder(root.left);
//        preOrder(root.right);
//    }


    // 获取叶子节点的个数
    public int getLeafNodeCount(TreeNode root){
        if(root == null){
            return 0;
        }
        if(root.left == null && root.right== null){
            return 1;
        }
        int left = getLeafNodeCount(root.left);
        int right = getLeafNodeCount(root.right);
        return left+right;
    }


    // 获取第K层节点的个数
    public int getKLevelNodeCount(TreeNode root,int k){
        if (root == null){
            return 0;
        }
        if (k == 1){
            return 1;
        }
        int left = getKLevelNodeCount(root.left,k-1);
        int right = getKLevelNodeCount(root.right,k-1);
        return left+right;
    }

    // 获取二叉树的高度
    // 求左树的高度和右树的高度 然后取最大值 然后加一  就是树的高度
    int getHeight(TreeNode root){
        if (root == null){
            return 0;
        }
        int left = getHeight(root.left);
        int right = getHeight(root.right);
        return left>right ? left+1 : right+1;
    }


    // 检测值为value的元素是否存在
    TreeNode find(TreeNode root, int val){
        if(root == null){
            return null;
        }
        if(root.val == val){
            return root;
        }
        TreeNode left = find(root.left,val);
        if (left != null){
            return left;
        }
        TreeNode right = find(root.right,val);
        if (right != null){
            return right;
        }
        return null;
    }

二叉树的算法题

 数据结构11节

1. 检查两颗树是否相同。

OJ链接100. 相同的树 - 力扣(LeetCode)

 思路:

从root 开始判断:

结构是否相同,如果一个为空一个非空 则一定不相等

结构相同: 判断是否都是空

结构相同且都不为空:判断值是否相等  如果值也相等 则证明 root 相同

然后再进去左右子树 判断子树的 root 是否相同(如上流程)依次不断递归,直到值都为空返回

class Solution {

        public boolean isSameTree(TreeNode p, TreeNode q) {
        if (p == null && q != null || p != null && q == null){
            return false;
        }
        if(p == null && q == null){
            return true;
        }
        if(p.val != q.val){
            return false;
        }
        boolean left = isSameTree(p.left,q.left);
        boolean right = isSameTree(p.right,q.right);
        return left && right;
        }
}

2. 另一颗树的子树。

OJ链接572. 另一棵树的子树 - 力扣(LeetCode)

思路:

如果发现 有相同的树 就直接返回true

判断是否有相同树的方法 如上题

class Solution {

            public boolean isSubtree(TreeNode root, TreeNode subRoot) {
            if (root == null || subRoot == null){
                return false;
            }
            if (isSameTree(root,subRoot)) return true;

            if (isSubtree(root.left,subRoot)) return true;

            if (isSubtree(root.right,subRoot)) return true;

            return false;
    }

        public boolean isSameTree(TreeNode p, TreeNode q) {
        if (p == null && q != null || p != null && q == null){
            return false;
        }
        if(p == null && q == null){
            return true;
        }
        if(p.val != q.val){
            return false;
        }
        return isSameTree(p.left,q.left) && isSameTree(p.right,q.right) ;
        }
}

3. 翻转二叉树。

Oj链接226. 翻转二叉树 - 力扣(LeetCode)

    

思路:

定义一个中间变量

再交换左右子树即可

不断递归下去

class Solution {
    public TreeNode invertTree(TreeNode root) {
                if (root == null){
            return null;
        }
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;

        invertTree(root.left);
        invertTree(root.right);

        return root;
    }
}

4. 判断一颗二叉树是否是平衡二叉树。 (重点 !!)

OJ链接110. 平衡二叉树 - 力扣(LeetCode)

                   

思路:

 求两数的绝对值     

要使高度差不超过1,所以首先要定义一个方法求出左右子树的高度(参考上文的二叉树常用方法实现 )

得到左右子树的高度差小于2才返回true ,

同时要满足 当前根 的左子树 &&  当前根 的右子树  也符合这个条件 ( 相当于此处要递归判断是否成立 )

class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root == null){
            return true;
        }
        int left = getHight(root.left);
        int right = getHight(root.right);
        return Math.abs(left-right)<2 && isBalanced(root.left) && isBalanced(root.right);
    
    }

    public int getHight(TreeNode root){
        if(root == null){
            return 0;
        }
        int left = getHight(root.left);
        int right = getHight(root.right);
        return left>right ? left+1 : right+1;
    }

}

当前代码的时间复杂度是O(n2) , 为什么 ?

如果要变为O(n) 要怎么写 ?

数据结构11节 2:00:00 ~2:10:00

思路:

在求高度的时候就判断是否 左右子树 的高度差值<2 

如果不满足平衡,返回一个 负数

class Solution {
    public boolean isBalanced(TreeNode root) {
        return getHight(root)>=0;
    }

    public int getHight(TreeNode root){
        if(root == null){
            return 0;
        }
        int left = getHight(root.left);
        if(left < 0) return -1;

        int right = getHight(root.right);
        if(right < 0) return -1;
        
        if(Math.abs(left-right)<2){
            return Math.max(left,right)+1;
        }else {
            return -1;
        }
    }


}

5. 对称二叉树。

OJ链接101. 对称二叉树 - 力扣(LeetCode)

思路一

常规解法: 

      

观察可以发现,

对于root, root.left 和 root.right 的值要相同,

左树的左子树 要等于右树的右子树,

左树的右子树,要等于右树的左子树

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if (root == null){
            return false;
        }
        //  存在root,开始判断下一层
        return isSymmetricChild(root.left,root.right);
    }

    public boolean isSymmetricChild(TreeNode rootLeft,TreeNode rootRight){

            //  左为空,右不为空 或 左不为空,右为空  则结构不相等,false
            if(rootLeft == null && rootRight != null || rootLeft != null && rootRight == null ){
                return false;
            }

            //  左右子树的跟都为空时,结构相等 true
            if (rootLeft == null && rootRight == null){
                return true;
            }

            //  此时 左右子树的跟结构相等,且都不为空,判断值是否相同, 不同 false
            if(rootLeft.val != rootRight.val){
                return false;
            }

            //  左右子树的root都相同,判断下一层是否符合
            //  左的左 == 右的右 , 左的右 == 右的左
            return isSymmetricChild(rootLeft.left,rootRight.right) &&                 
                      isSymmetricChild(rootLeft.right,rootRight.left);

    }

}

思路二:

灵活运用前面写的代码

先翻转二叉树的右(左)子树,再判断两个二叉树是否相等

调用翻转二叉树方法,和判断二叉树是否相等方法

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root == null){
            return false;
        }
        if (root.left == null && root.right == null){
            return true;
        }
        invertTree(root.right);
        boolean ret = isSameTree(root.left,root.right);
        return ret;
    }

    //  翻转 二叉树
        public TreeNode invertTree(TreeNode root) {
                if (root == null){
            return null;
        }
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;

        invertTree(root.left);
        invertTree(root.right);

        return root;
    }

    //  判断 二叉树是否相等
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if (p == null && q != null || p != null && q == null){
            return false;
        }
        if(p == null && q == null){
            return true;
        }
        if(p.val != q.val){
            return false;
        }
        boolean left = isSameTree(p.left,q.left);
        boolean right = isSameTree(p.right,q.right);
        return left && right ;
        }


}

6. 二叉树的构建及遍历。

OJ链接102. 二叉树的层序遍历 - 力扣(LeetCode)

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> list = new ArrayList<>();
        if (root == null){
            return list;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()){
            int size = queue.size();
            List<Integer> tmp = new ArrayList<>();
            while (size>0){
                TreeNode cur = queue.poll();
                tmp.add(cur.val);
                size--;
                if (cur.left != null){
                    queue.offer(cur.left);
                }
                if (cur.right != null){
                    queue.offer(cur.right);
                }
            }
            list.add(tmp);
        }
        return list;
    }

}

7. 二叉树的分层遍历 。

OJ链接

8. 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先 。

236. 二叉树的最近公共祖先 - 力扣(LeetCode)

有三种情况:

 用递归的方法实现: 常规方法

    class Solution {
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
            if(root == null){
                return null;
            }
            if( root == p || root == q ){
                return root;
            }
            TreeNode leftRet = lowestCommonAncestor(root.left,p,q);
            TreeNode rightRet = lowestCommonAncestor(root.right,p,q);
            if( leftRet != null && rightRet != null ){
                return root;
            } else if (leftRet != null) {
                return leftRet;
            } else if ( rightRet != null ) {
                return rightRet;
            }
            return null;
        }
    }

用栈实现: 讲解:二叉树04 - 1:10:00

9. 根据一棵树的前序遍历与中序遍历构造二叉树。

105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

10. 根据一棵树的中序遍历与后序遍历构造二叉树([课堂不讲解,课后完成作业])。OJ链接

11. 二叉树创建字符串。

606. 根据二叉树创建字符串 - 力扣(LeetCode)

12. 二叉树前序非递归遍历实现 。

OJ链接

13. 二叉树中序非递归遍历实现。

OJ链接

14. 二叉树后序非递归遍历实现。

OJ链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值