Collection与数据结构 二叉树(一):二叉树的性质与基本操作

1. 树形结构

1.1 概念1 (了解)

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

  • 有一个特殊的结点,称为根结点,根结点没有前驱结点
  • 除根结点外,其余结点被分成M(M > 0)个互不相交的集合T1、T2、…、Tm,其中每一个集合Ti (1 <= i <= m) 又是一棵与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
  • 树是递归定义的。
    在这里插入图片描述
    在这里插入图片描述
    注意:在子树之间不可以有交集,否者就不是树形结构.
    在这里插入图片描述

1.2 概念2 (重点)

在这里插入图片描述

  • 结点的度:一个结点含有子树的个数称为该结点的度,如b的度为2.
  • 树的度:一棵树中,所有结点度的最大值称为树的度,如上面这棵树的度为2.
  • 叶子结点或终端结点:度为0的结点称为叶结点,如上图中d,g,h,i都是叶子结点.
  • 双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点,如g的父结点是e.
  • 孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点,如b的子节点是d,e.
  • 根结点:一棵树中,没有双亲结点的结点,如上面这棵树的根节点是a.
  • 结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推.
  • 树的高度或深度:树中结点的最大层次,如上面这棵树的深度是4.
  • 兄弟结点:具有相同父结点的结点互称为兄弟结点,如g的兄弟结点是h
  • 堂兄弟结点:双亲在同一层的结点互为堂兄弟,如e是f的堂兄弟结点.

1.3 树的表示形式

树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,实际中树有很多种表示方式,如:双亲表示法,孩子表示法、孩子双亲表示法、孩子兄弟表示法等等。我们这里就简单的了解其中最常用的孩子兄弟表示法。下图中,c代表child,b代表brother.
在这里插入图片描述

1.4 树的应用

  1. 文件管理系统,如Linux操作系统的目录
    在这里插入图片描述

2. 二叉树(重点)

2.1 概念

一棵二叉树是结点的一个有限集合,该集合:

  1. 或者为空
  2. 或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成
    在这里插入图片描述
    从上图可以看出:
  3. 二叉树不存在度大于2的结点.
  4. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树.

注意:对于任意的二叉树都是由以下几种情况复合而成的:
在这里插入图片描述

2.2 两种特殊的二叉树

  1. 满二叉树:
    一棵二叉树,如果每层的结点数都达到最大值,则这棵二叉树就是满二叉树。也就是说,如果一棵二叉树的层数为K,且结点总数是2k-1,则它就是满二叉树。
  2. 完全二叉树:
    通过层序遍历的方法,==从上到下,从左到右,依次存储结点,==中间不可以有断开.
    [注] 满二叉树是一棵特殊的完全二叉树.
    在这里插入图片描述
    在这里插入图片描述

2.3 二叉树的性质

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

2.4 二叉树的存储

在这里,我们使用类似与链表的链式存储.
二叉树的链式存储是通过一个一个的节点引用起来的,常见的表示方式有**二叉(找不到父节点,类似与单向列表)和三叉(可以找到父节点,类似与双向链表)**表示方式,具体如下:

// 孩子表示法
class Node {int val; // 数据域Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
}// 孩子双亲表示法
class Node {int val; // 数据域Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树Node parent;    // 当前节点的父节点
}

2.5 二叉树的基本操作

前置说明:我们这里使用非常简单的方法来创建一棵二叉树,此二叉树是孩子表示法,其实真正创建二叉树的方法不是这样的,我们后边介绍.我们创建下面这棵二叉树:
在这里插入图片描述

2.5.1 二叉树的遍历

  • NLR:前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点—>根的左子树—>根的右子树
  • LNR:中序遍历(Inorder Traversal)——根的左子树—>根节点—>根的右子树
  • LRN:后序遍历(Postorder Traversal)——根的左子树—>根的右子树—>根节点
  • 层序遍历: 从上到下,从左到右,依次遍历.
public class BinaryTree  {static class Node{public int value;public Node left;public Node right;public Node(int value) {this.value = value;}}public int treeSize;/*** 创建一棵默认的树* @return*/public Node createTree(){//注意:真正创建二叉树的方法不是这这样的,我们后面介绍Node a = new Node(1);Node b = new Node(2);Node c = new Node(3);Node d = new Node(4);Node e = new Node(5);Node f = new Node(6);Node g = new Node(7);a.left = b;a.right = c;b.left = d;c.left = e;c.right = f;d.left = g;return a;}/*** 前序遍历* @param root*/public void preOrder(Node root){if (root == null){return;}System.out.print(root.value+" ");preOrder(root.left);preOrder(root.right);}/*** 中序遍历* @param root*/public void inOrder(Node root){if (root == null){return;}preOrder(root.left);System.out.print(root.value+" ");preOrder(root.right);}/*** 后序遍历* @param root*/public void postOrder(Node root){if (root == null){return;}preOrder(root.left);preOrder(root.right);System.out.print(root.value+" ");}/*** 计算树的大小* @param root* @return*/public int size(Node root) {if (root == null){return 0;}treeSize++;size(root.left);size(root.right);return treeSize;}/*** 获取树叶子结点的个数* @param root* @return*/public int getLeafNodeCount(Node root) {if (root == null){return 0;}if (root.left == null && root.right == null){return 1;}return getLeafNodeCount(root.left)+getLeafNodeCount(root.right);}/*** 获取该树的第k层有几个结点* @param root* @param k* @return*/public int getKLevelNodeCount(Node root, int k) {if (root == null){return 0;}if (k == 1){return 1;}return getKLevelNodeCount(root.left,k-1)+getKLevelNodeCount(root.right,k-1);//每递归一层,k-1//相对与根节点,第三层就是第三层,相对第二层,第三层是第二层,以此类推...}/*** 获取树的高度,取左子树和右子树的最大值+1(加上根节点所在的层)* @param root* @return*/public int getHeight(Node root) {if (root == null){return 0;}return Math.max(getHeight(root.left),getHeight(root.right))+1;}/*** 在树中寻找val值是否存在* @param root* @param val* @return*/public Node find(Node root, int val) {if (root == null){return null;}if (root.value == val){return root;}Node leftNode = find(root.left,val);if (leftNode != null){//写成判断地址的形,如果写成值的形式,可能会报空指针异常return leftNode;//如果从左树中找到,直接返回,就不用遍历右树,以此来减小时间复杂度}Node rightNode = find(root.right,val);if (rightNode != null){return rightNode;}return null;//递归到底了,说明没找到,返回null}
/*
层序遍历和判断是否为完全二叉树比较复杂,我们后续介绍*/
}

开始测试:

public class Test {public static void main(String[] args) {BinaryTree binaryTree = new BinaryTree();BinaryTree.Node root = binaryTree.createTree();binaryTree.preOrder(root);System.out.println();binaryTree.inOrder(root);System.out.println();binaryTree.postOrder(root);System.out.println();System.out.println(binaryTree.size(root));System.out.println(binaryTree.getLeafNodeCount(root));System.out.println(binaryTree.getKLevelNodeCount(root,4));System.out.println(binaryTree.getHeight(root));System.out.println(binaryTree.find(root,7));System.out.println(binaryTree.find(root,8));}
}

测试结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/603982.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTTPS,不可或缺的数据安全锁

互联网时代的发展&#xff0c;让我们足不出户就能办理很多生活和工作上的事情&#xff0c;便利了我们的工作和生活。随着网络技术的不断升级&#xff0c;网络安全已经成为当下的焦点&#xff0c;如何让互联网为我们提供服务的同时也能保护好用户的隐私&#xff0c;已经成为行业…

Spring 之 IoC概述

目录 1. IoC概述 1.1 控制反转 1.2 依赖注入 2. IoC容器在Spring中的实现 2.1 BeanFactory 2.2 ApplicationContext 2.2.1 ApplicationContext的主要实现类 1. IoC概述 全称&#xff1a;Inversion of Control&#xff0c;译为 “控制反转” Spring通过IoC容器来管理所有…

运筹学基础(六)列生成算法(Column generation)

文章目录 前言从Cutting stock problem说起常规建模Column generation reformulation 列生成法核心思想相关概念Master Problem (MP)Linear Master Problem (LMP)Restricted Linear Master Problem (RLMP)subproblem&#xff08;核能预警&#xff0c;非常重要&#xff09; 算法…

学习嵌入式可以胜任哪一些行业?

嵌入式技术之应用范围甚广&#xff0c;其多见于机器人、无人机、医疗器械以及军工等领域&#xff0c;为学习者带来诸多广泛之职业机遇。嵌入式工程师于此诸领域中扮演关键之角色&#xff0c;负责解决硬件平台适配等诸问题&#xff0c;以为创新提供支撑之力。 虽嵌入式技术与日…

实验案例一:交换机的初始配置

1、实验环境 实验用具包括一台 Cisco 交换机&#xff0c;一台 PC&#xff0c;一根 Console 线缆。 2、需求描述 如图 5.17 所示&#xff0c;实验案例一的配置需求如下。 通过 PC 连接并配置一台 Cisco 交换机在交换机的各个配置模式之间切换将交换机主机的名称改为 BDON 3、…

flutter滑动隐藏头部

模型代码 import packagegenerated/l10n.dart; import package:jade/bean/TabTypeMode.dart; import package:jade/customWidget/MyCustomIndicator.dart; import package:jade/experienceStationCreate/MyExpCellBillHistory.dart; import package:jade/utils/JadeColors.dar…

【Linux 学习】进程优先级和命令行参数!

1. 什么是优先级? 指定进程获取某种资源&#xff08;CPU&#xff09;的先后顺序&#xff1b; Linux 中优先级数字越小&#xff0c;优先级越高&#xff1b; 1.1 优先级和权限的区别&#xff1f; 权限 &#xff1a; 能不能做 优先级&#xff1a; 已经能了&#xff0c;但是获…

1653. 使字符串平衡的最少删除次数

1653. 使字符串平衡的最少删除次数 题目 链接&#xff1a;使字符串平衡的最少删除次数 题解 class Solution {public int minimumDeletions(String s) {int left0,right0;int ns.length();for(int i0;i<n;i){if(s.charAt(i)a){right;}}int resright;for(int i0;i<s.…

STM32学习笔记(11_1)- SPI简介和工作原理

无人问津也好&#xff0c;技不如人也罢&#xff0c;都应静下心来&#xff0c;去做该做的事。 最近在学STM32&#xff0c;所以也开贴记录一下主要内容&#xff0c;省的过目即忘。视频教程为江科大&#xff08;改名江协科技&#xff09;&#xff0c;网站jiangxiekeji.com 本期学…

Pytest接口自动化测试进阶

背景 随着Web应用的发展&#xff0c;越来越多的功能需要用户登录才能使用。而在接口测试中&#xff0c;往往需要模拟用户的登录状态来进行测试。一种常见的做法是通过Cookie来维持用户的登录状态。然而&#xff0c;由于Cookie的有效期限制以及网站的安全策略&#xff0c;如何在…

YOLOv5标签值含义根据标签将检测框色块替换(马赛克)

以一个检测人脸的图片为例&#xff1a; 检测后生成的标签txt如下&#xff0c; 此时&#xff0c;如何根据标签值将检测到的人脸同色块替换呢&#xff1f; 关键是获取检测框的左上角坐标和右下角坐标。 img Image.open(D:/PythonWokspace/JINX/datasets_transform/dataset/im…

YUDAO源码中的正序倒序表格ElmentUI的实现,与后端的配合?

前端展示和实现&#xff1a; 1. elmentUI表格的定义 2. JS请求参数改造 <!-- 列表 --><el-table v-loading"loading" :data"list" sort-change"handleSortChange"><el-table-column label"Expiry Date" prop"…