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.mzph.cn/news/803079.shtml

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

相关文章

C语言单链表

1. 单链表的概念和结构 概念&#xff1a;链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表 中的指针链接次序实现的 。 链表与顺序表都属于线性表&#xff0c;顺序表在物理存储结构上是线性的&#xff0c;但是链表在物理存储结构上…

基于springboot+vue+Mysql的学习平台

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

Centos 下载地址

下载镜像地址&#xff1a; 1、官网地址&#xff1a;The CentOS Project 2、阿里镜像站&#xff1a;centos安装包下载_开源镜像站-阿里云 3、清华镜像源&#xff1a;Index of /centos/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 3.、CentOS搜狐镜像&#xff1…

Spark-Scala语言实战(13)

在之前的文章中&#xff0c;我们学习了如何在spark中使用键值对中的keys和values,reduceByKey,groupByKey三种方法。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢…

JavaSE:图书管理系统

目录 一、前言 二、内容需求 三、类的设计 &#xff08;一&#xff09;图书类 1.Book 类 2.BookList 类 &#xff08;二&#xff09;操作类 1.添加图书AddOperation类 2.借阅图书BorrowOperation类 3.删除图书DelOperation类 4.显示图书ShowOperation类 5.退出系统Ex…

【三十六】【算法分析与设计】综合练习(3),39. 组合总和,784. 字母大小写全排列,526. 优美的排列

目录 39. 组合总和 对每一个位置进行枚举 枚举每一个数出现的次数 784. 字母大小写全排列 526. 优美的排列 结尾 39. 组合总和 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不…

手写Spring框架

手写Spring框架 准备工作Spring启动和扫描逻辑实现依赖注入的实现Aware回调模拟实现和初始化机制模拟实现BeanPostProcessor (Bean的后置处理器) 模拟实现Spring AOP 模拟实现Spring Bean生命周期源码分析 Spring中两种生成代理的方式题外话 Spring事务相关Spring事务传播机制S…

C++——栈和队列容器

前言&#xff1a;这篇文章我们将栈和队列两个容器放在一起进行分享&#xff0c;因为这两个要分享的知识较少&#xff0c;而且两者在结构上有很多相似之处&#xff0c;比如栈只能在栈顶操作&#xff0c;队列只能在队头和队尾操作。 不同于前边所分享的三种容器&#xff0c;这篇…

HarmonyOS 应用开发-ArkUI(ets)仿“腾讯新闻”APP

一、效果演示 1、新闻列表页 2、新闻详情页、图片展示页 3、视频页 4、动态页 二、 流程图 –本来自定义了视频的控制栏的&#xff0c;但是发现VideoController()控制器的bug会导致控制器失效&#xff0c;所以没继续做。视频页先不搞了。 三、文件组织&#xff08;“我的页面…

网工内推 | 深信服、宁德时代,最高20K招安全工程师,包吃包住

01 深信服科技 招聘岗位&#xff1a;安全服务工程师 职责描述&#xff1a; 1.负责现场安全服务项目工作内容&#xff0c;包含渗透测试、安全扫描、基线核查、应急响应等&#xff1b; 2.协助用户完成安全测试漏洞整改、复测工作&#xff1b; 3.为用户提供网络、主机、业务系统等…

dg_mmld部分复现

Ours ( K ˆ \^{K} Kˆ2)复现结果– Photo&#xff1a;0.9634730538922156 (at Epoch 23) Art&#xff1a;0.8125 (at Epoch 23) Cartoon&#xff1a;0.7713310580204779 (at Epoch 18) 差距在可接受范围内 辅助信息 If you send 作者 an e-mail, 作者 will tell you a URL w…

2022年蓝桥杯省赛——重合次数

目录 题目链接&#xff1a;1.重合次数 - 蓝桥云课 (lanqiao.cn) 题目描述 答案提交 运行限制 思路 总结 题目链接&#xff1a;1.重合次数 - 蓝桥云课 (lanqiao.cn) 题目描述 在同一天中, 从上午 6 点 13 分 22 秒到下午 14 点 36 分 20 秒, 钟表上的 分针和秒针一共重合…

HTML - 请你谈一谈img标签图片和background背景图片的区别

难度级别:中级及以上 提问概率:65% 面试官当然不会问如何使用img标签或者background来加载一张图片,这些知识点都很基础,相信只要从事前端开发一小段时间以后,就可以轻松搞定加载图片的问题。但很多人习惯用img标签,很多人习惯用backgro…

Java 数据类型转换

String 转 char 数组 String str "abc"; char[] charArr str.toCharArray();char 数组转 String char[] charArr{a, b, c}; String str new String(charArr);char 字符转 String 使用 String.valueOf() 方法 char ch a; String str String.valueOf(ch);使…

element-ui的年份范围选择器,选择的年份需等于或小于当前年份,选择的年份范围必须在三年之内

写在前面 日期限制处理&#xff08;禁用&#xff09;&#xff0c;下面我以我这边的需求为例&#xff0c; 选择的年份需等于或小于当前年份 选择的年份范围必须在三年之内 1.限制起始日期小于截止日期 1&#xff09;根据用户选中的开始日期&#xff0c;置灰不可选的日期范围&…

【腾讯云 TDSQL-C Serverless 产品体验】饮水机式使用云数据库

云计算的发展从IaaS&#xff0c;PaaS&#xff0c;SaaS&#xff0c;到最新的BaaS&#xff0c;FasS&#xff0c;在这个趋势中serverless(去服务器化&#xff09; 计算资源发展Physical -> Virtualisation -> Cloud Compute -> Container -> Serverless。 一、背景介绍…

什么是电子邮件组,为什么要使用它们?

在当今时代&#xff0c;电子邮件无处不在&#xff0c;尤其是对于商业活动而言。电子邮件的重要性不容忽视&#xff0c;因为它在沟通中极为高效。然而&#xff0c;电子邮件也存在降低工作效率和阻碍流程的风险。在这种情况下&#xff0c;电子邮件群组就是最佳的解决方案。什么是…

代码随想录算法训练营第二十九天|491.递增子序列,46.全排列,47.全排列 II

题目&#xff1a;491.递增子序列 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中至少有两个元素。你可以按任意顺序返回答案。 数组中可能含有重复元素&#xff0c;如出现两个整数相等&#xff0c;也可以视作递增序列的一…

【学习 在服务器上使用bypy直接下载百度云盘的资源。

参考&#xff1a;bypy 具体步骤 step1&#xff1a; pip install bypystep2&#xff1a; bypy info第一次输入该命令&#xff0c; 点击进入网址&#xff0c;点击登陆后&#xff0c;获取token&#xff08;10分钟内有效&#xff09;&#xff0c;然后输入到命令行&#xff1a;…

【linux深入剖析】深入理解基础外设--磁盘

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 前言1.磁盘物理结构2.磁盘…