• 二叉树详解


    活动地址:CSDN21天学习挑战赛

    目录

    一、了解树型结构

    1.概念

     2.知识点

    3.树的表示形式

    二、二叉树

    1.概念

    2.二叉树的分类

    1.满二叉树

    2.完全二叉树

     3.平衡二叉树

    3.二叉树的应用场景

    4.二叉树的性质

    5.二叉树的存储

    6.二叉树的基本操作

    模拟创建二叉树

    前序遍历   

    中序遍历

    后序遍历

    获取叶子节点的个数

    获取第k层节点的个数

    获取二叉树的高度

    检查是否存在某个值

    层序遍历

    判断一棵树是不是完全二叉树


    一、了解树型结构

    1.概念

    树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

    注意:树形结构中,子树之间不能有交集,否则就不是树形结构

    例如:

     2.知识点

    结点的度:一个结点含有子树的个数称为该结点的度; 如上图:A的度为5。

    树的度:一棵树中,所有结点度的最大值称为树的度; 如上图:树的度为5。

    叶子结点或终端结点:度为0的结点称为叶结点; 如上图:B、G、H、I、O...等节点为叶结点。

    双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图:A是B、C、D、E、F的父结点。

    孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点; 如上图:B是A的孩子结点。
    根结点:一棵树中,没有双亲结点的结点;如上图:A。

    结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推。

    树的高度或深度:树中结点的最大层次; 如上图:树的高度为5。

    兄弟结点:具有相同父结点的结点互称为兄弟结点; 如上图:B、C是兄弟结点。

    结点的祖先:从根到该结点所经分支上的所有结点;如上图:A是所有结点的祖先。

    3.树的表示形式

    树的表示形式有几种,例如:双亲表示法,孩子表示法、孩子双亲表示法、孩子兄弟表示法等等。我这里用的是孩子兄弟表示法。

    二、二叉树

    1.概念

    树中节点最大的度,为2的数就叫做二叉树,也就是数的度为2的树。

    在二叉树中,一个节点最多有两颗子树,二叉树节点的度<=2。

    二叉树的有左右之分,且子树的次序不能颠倒,因此二叉树是有序树。

    所以的二叉树都是下面几种情况组合起来的:


    2.二叉树的分类

    1.满二叉树

    国际标准定义是除了叶结点外每一个结点都有左右子结点的二叉树

    而国内的定义是:除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。很显然,按照这个定义,下面的图示二叉树就不是满二叉树。

    2.完全二叉树

    • 若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
    • 一维数组可以作为完全二叉树的存储结构,堆排序使用的数据结构就是完全二叉树。

     3.平衡二叉树

     一棵空树或它的任意节点的左右两个子树的高度差的绝对值不超过1。


    3.二叉树的应用场景

    • 普通的二叉树,很难构成现实的应用场景,但因其简单,常用于学习研究,平衡二叉树则是实际应用比较多的。常见于快速匹配、搜索等方面。
    • 常用的树有:AVL树、红黑树、B+树、Trie(字典)树。
      1、AVL树: 最早的平衡二叉树之一。应用相对其他数据结构比较少。windows对进程地址空间的管理用到了AVL树。
      2、红黑树: 平衡二叉树,广泛用在C++的STL中。如map和set都是用红黑树实现的。还有Linux文件管理。
      3、B/B+树: 用在磁盘文件组织 数据索引和数据库索引。
      4、Trie树(字典树): 用在统计和排序大量字符串,如自动机、M数据库索引。
       

    4.二叉树的性质

    1. 若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有 (i>0)个结点
    2. 若规定只有根结点的二叉树的深度为1,则深度为K的二叉树的最大结点数是 (k>=0)
    3. 对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2,则有n0=n2+1
    4. 具有n个结点的完全二叉树的深度k为 上取整
    5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i的结点有:                                                                                                若i>0,双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点
      若2i+1 若2i+2

    5.二叉树的存储

    二叉树的存储分为:顺序存储类似于链表的链式存储

    6.二叉树的基本操作

    模拟创建二叉树

    前置代码

    1. static class TreeNode {
    2. public char val;
    3. public TreeNode left;
    4. public TreeNode right;
    5. public TreeNode(char val) {
    6. this.val = val;
    7. }
    8. }

    学习二叉树结构,最简单的方式就是遍历。所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问题(比如:打印节点内容、节点内容加1)。 遍历是二叉树上最重要的操作之一,是二叉树上进行其它运算之基础。
     

    在遍历二叉树时,如果没有进行某种约定,每个人都按照自己的方式遍历,得出的结果就比较混乱,如果按照某种规则进行约定,则每个人对于同一棵树的遍历结果肯定是相同的。如果N代表根节点,L代表根节点的左子树,R代表根节点的右子树,则根据遍历根节点的先后次序有以下遍历方式:前序遍历,中序遍历,后序遍历
     

    前序遍历   

       访问根结点--->根的左子树--->根的右子树。

    1. // 前序遍历
    2. void preOrder(TreeNode root) {
    3. if(root == null) return;
    4. System.out.print(root.val+" ");
    5. preOrder(root.left);
    6. preOrder(root.right);
    7. }

    中序遍历

    根的左子树--->根节点--->根的右子树。

    1. // 中序遍历
    2. void inOrder(TreeNode root) {
    3. if(root == null) return;
    4. inOrder(root.left);
    5. System.out.print(root.val+" ");
    6. inOrder(root.right);
    7. }

    后序遍历

    根的左子树--->根的右子树--->根节点。

    1. // 中序遍历
    2. void inOrder(TreeNode root) {
    3. if(root == null) return;
    4. inOrder(root.left);
    5. System.out.print(root.val+" ");
    6. inOrder(root.right);
    7. }

    获取叶子节点的个数

    子问题思路

    1. int getLeafNodeCount(TreeNode root) {
    2. if(root == null) {
    3. return 0;
    4. }
    5. if(root.left == null && root.right == null) {
    6. return 1;
    7. }
    8. return getLeafNodeCount(root.left)
    9. + getLeafNodeCount(root.right);
    10. }

    遍历思路

    1. public static int leafSize;
    2. void getLeafNodeCount2(TreeNode root) {
    3. if(root == null) return;
    4. if(root.left == null && root.right == null) {
    5. leafSize++;
    6. }
    7. getLeafNodeCount2(root.left);
    8. getLeafNodeCount2(root.right);
    9. }

    获取第k层节点的个数

    1. // 获取第K层节点的个数
    2. int getKLevelNodeCount(TreeNode root,int k) {
    3. if(root == null) return 0;
    4. if(k == 1) {
    5. return 1;
    6. }
    7. return getKLevelNodeCount(root.left, k-1) +
    8. getKLevelNodeCount(root.right,k-1);
    9. }

    获取二叉树的高度

    1. // 获取二叉树的高度 时间复杂度:O(N)
    2. int getHeight(TreeNode root) {
    3. if(root == null) return 0;
    4. int leftHeight = getHeight(root.left);
    5. int rightHeight = getHeight(root.right);
    6. return (leftHeight > rightHeight ?
    7. leftHeight+1 : rightHeight+1);
    8. }

    检查是否存在某个值

    1. // 检测值为value的元素是否存在
    2. TreeNode find(TreeNode root, char val) {
    3. if(root == null) return null;
    4. if(root.val == val) {
    5. return root;
    6. }
    7. TreeNode ret1 = find(root.left,val);
    8. if(ret1 != null) {
    9. return ret1;
    10. }
    11. TreeNode ret2 = find(root.right,val);
    12. if(ret2 != null) {
    13. return ret2;
    14. }
    15. return null;
    16. }

    层序遍历

    1. //层序遍历
    2. void levelOrder(TreeNode root) {
    3. if(root == null) return;
    4. Queue queue = new LinkedList<>();
    5. queue.offer(root);
    6. while (!queue.isEmpty()) {
    7. TreeNode cur = queue.poll();
    8. System.out.print(cur.val+" ");
    9. if(cur.left != null) {
    10. queue.offer(cur.left);
    11. }
    12. if(cur.right != null) {
    13. queue.offer(cur.right);
    14. }
    15. }
    16. System.out.println();
    17. }

    判断一棵树是不是完全二叉树

    这里运用的队列来求,有不懂队列的朋友可以去看看我写的栈和队列这篇文章,链接如下:Stack和Queue 栈和队列_即将秃头的菜鸟的博客-CSDN博客

    1. // 判断一棵树是不是完全二叉树
    2. boolean isCompleteTree(TreeNode root) {
    3. if(root == null) return true;
    4. Queue queue = new LinkedList<>();
    5. queue.offer(root);
    6. while (!queue.isEmpty()) {
    7. TreeNode cur = queue.poll();
    8. if(cur != null) {
    9. queue.offer(cur.left);
    10. queue.offer(cur.right);
    11. }else {
    12. break;
    13. }
    14. }
    15. while (!queue.isEmpty()) {
    16. TreeNode cur = queue.peek();
    17. if(cur != null) {
    18. //不是满二叉树
    19. return false;
    20. }else {
    21. queue.poll();
    22. }
    23. }
    24. return true;
    25. }

  • 相关阅读:
    使用GROUP BY分组
    【附源码】Python计算机毕业设计企业培训在线考试系统
    免费旋转视频
    买房需要了解的一些事
    Keycloak之Gerrit安装与集成-yellowcong
    分布式事务
    USB3.0 host xHCI驱动
    港科夜闻|香港科大(广州)校长倪明选教授出席江门双碳实验室第一届理事会一次会议...
    面向对象和原型/原型链学习
    Java—— 中的 Comparable、Clonable
  • 原文地址:https://blog.csdn.net/qq_52592775/article/details/126221738