二叉树的学习笔记

树型结构(非线性),递归定义,子树之间不能有交集

结点的度:一个结点含有子树的个数称为该结点的度

树的度:一棵树中,所有结点度的最大值称为树的度

叶子结点:度为0的结点

一、概念

要么为空,要么一个根节点加两棵树(左子树和右子树),每个节点的度不能超过2

二、特殊二叉树

1.满二叉树

每层的结点数都达到最大值

总共的结点个数(k层):2ᴷ-1

2.完全二叉树

(深度为k,n个结点)

从0到n-1结点一 一对应,满二叉树是特殊的完全二叉树

三、二叉树的性质

  1. 第i层最多有2的(i-1)次方个结点(i>0)
  2. 深度为k的最大结点数是2ᴷ-1(k≥0)
  3. 叶结点个数为n0,度为2的非叶结点个数为n2,则有n0=n2+1(每生两个孩子就多一个叶子)
  4. n个节点的完全二叉数深度k为㏒(n+1)(以2为底)取整
  5. n个结点的完全二叉树,从上至下从左至右编号,已知父亲节点下标是i,则左孩子节点的下表是2i+1,右孩子节点的下表是2i+2(就是根节点编号从0开始)
  6. 总边数=总结点数-1(除了根,每个节点都有一条边,总边数等于度数之和,你把节点的度想象成向下的手)

例题:在具有2n个结点的完全二叉数中,叶子结点个数为_。

答案:n(提示:要考虑到结点数的奇偶,偶数结点就多一个,所以n=n0+1+n2,奇数结点就是n=n0+0+n2)

四、二叉树的存储与遍历

1.存储结构

  • 顺序存储
  • 链式存储

2.遍历方式

  • 前序遍历(根左右)
  • 顺序遍历(左根右)
  • 后序遍历(左右根)
  • 层序遍历

例题:

  • 前序:ABDEHCFG
  • 中序:DBEHAFCG
  • 后序:DHEBFGCA

五、代码实现

1.构建二叉树

重点是那种思想,其他方法差不多可以类比

获取节点个数:

思路一:遍历思路,不为空,计数加一

思路二:子问题思路,整棵树的结点个数=左子树的结点个数+右子树的结点个数

获取叶子节点的个数:

遍历思路:root.left == null && root.right == null count++

子问题思路:整棵树的叶子节点个数等于左子树叶子节点的个数加右子树叶子节点的个数

java 复制代码
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;

public class BinaryTree {

    static class TreeNode {
        public char val;
        public TreeNode left;//左孩子的引用
        public TreeNode right;//右孩子的引用

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


    /**
     * 创建一棵二叉树 返回这棵树的根节点
     *
     * @return
     */
    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');
        A.left = B;
        A.right = C;
        B.left = D;
        B.right = E;
        C.right = F;
        return A;
    }

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

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

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

    }

    public static int nodeSize;

    /**
     * 获取树中节点的个数:遍历思路
     */
    void size(TreeNode root) {
        if (root == null){
            return;
        }
        nodeSize++;
        size(root.left);
        size(root.right);
    }

    /**
     * 获取节点的个数:子问题的思路
     *
     * @param root
     * @return
     */
    int size2(TreeNode root) {
        if (root == null){
            return 0;
        }
        return size2(root.left) + size2(root.right) + 1;
    }


    /*
     获取叶子节点的个数:遍历思路
     */
    public static int leafSize = 0;

    void getLeafNodeCount1(TreeNode root) {
        if (root == null){
            return;
        }
        if (root.left == null && root.right == null){
            leafSize++;
        }
        getLeafNodeCount1(root.left);
        getLeafNodeCount1(root.right);
    }

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

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

    /*
     获取二叉树的高度
     时间复杂度:O(N)
     */
    int getHeight(TreeNode root) {
        if (root == null){
            return 0;
        }
        int leftroot = getHeight(root.left);
        int rightroot = getHeight(root.right);
        return Math.max(leftroot,rightroot)+1;
    }


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

    //层序遍历
    void levelOrder(TreeNode root) {
        if (root == null){
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        while (!queue.isEmpty()){
            TreeNode qul = queue.poll();
            System.out.println(qul.val);
            if (qul.left != null){
                queue.offer(qul.left);
            }
            if (qul.right != null){
                queue.offer(qul.right);
            }
        }


    }


    // 判断一棵树是不是完全二叉树
    boolean isCompleteTree(TreeNode root) {
        if (root == null){
            return false;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        while (!queue.isEmpty()){
            TreeNode qul = queue.poll();
            if (qul != null){
                queue.offer(qul.left);
                queue.offer(qul.right);
            }
            else {
                break;
            }
        }
        while (!queue.isEmpty()){
            TreeNode qul1 = queue.poll();
            if (qul1 != null){
                return false;
            }
        }
        return true;
    }
}

2.判断平衡二叉树

平衡二叉树是指该树所有节点的左右子树的高度相差不超过 1

java 复制代码
class Solution {

    public boolean isBalanced(TreeNode root) {

        if(root == null){

            return true;

        }

        return getHeight(root) >= 0;

    }

    public int getHeight(TreeNode root){

        if(root == null){

            return 0;

        }

            int leftH = getHeight(root.left);

            if(leftH < 0){

                return -1;

            }

            int rightH = getHeight(root.right);

            if(leftH >= 0 && rightH >= 0 && Math.abs(leftH-rightH)<=1){

                return leftH > rightH ? leftH + 1 : rightH + 1;

            }

        else{

            return -1;

        }

    }

}

3.层序遍历

这是一个力扣题,我觉得值得反复看

题目:给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

java 复制代码
class Solution {

    public List<List<Integer>> levelOrderBottom(TreeNode root) {

        List<List<Integer>> ret = new ArrayList<>();

        Queue<TreeNode> queue = new LinkedList<>();

        if(root == null){

            return ret;

        }

        queue.offer(root);

        while(!queue.isEmpty()){

            int size = queue.size();

            List<Integer> crow = new ArrayList<>();

            while(size != 0){

            TreeNode cur = queue.poll();

            crow.add(cur.val);

            if(cur.left != null){

                queue.offer(cur.left);

            }

            if(cur.right != null){

                queue.offer(cur.right);

            }

            size--;

            }

           ret.add(crow);

        }

        Collections.reverse(ret);

        return ret;

    }

}

最后祝大家每天都能坚持学代码,我也会坚持学习,尽量持续更新学习进度,加油

相关推荐
sakiko_1 小时前
Swift/UIkit学习笔记27-模块管理,发送位置信息
前端·笔记·学习·ios·swift·uikit
happymaker06261 小时前
Spring学习日记——DAY07(SpringMVC)
java·学习·spring
weixin_428005301 小时前
C#调用 AI学习从0开始-第1阶段(基础与工具)-第4天CoT思维链学习
开发语言·学习·ai·c#·cot
神秘剑客_CN1 小时前
Ubuntu 26.04使用笔记
linux·笔记·ubuntu
会编程的土豆1 小时前
Gin POST 请求完整流程笔记
chrome·笔记·gin
吃好睡好便好1 小时前
在Matlab中绘制变半径柱面图
开发语言·人工智能·学习·算法·matlab
IT英语写作研习社2 小时前
英语写作中“内容”Content的使用注意点
笔记
拂拉氏2 小时前
【知识讲解-题目讲解】:二叉树的前、中、后序遍历的三种实现(递归,非递归,Morris遍历)与二叉树oj题讲解(二叉树最近公共祖先,二叉树展开为链表)
数据结构·算法·leetcode·二叉树·遍历
凌晨7点2 小时前
控制的滤波器01:一阶RC低通滤波器
学习·mathcad