【数据结构与算法】JavaScript实现树结构(一)

news2025/1/11 19:58:05

文章目录

      • 一、树结构简介
        • 1.1.简单了解树结构
        • 1.2.树结构的表示方式
      • 二、二叉树
        • 2.1.二叉树简介
        • 2.2.特殊的二叉树
        • 2.3.二叉树的数据存储
      • 三、二叉搜索树
        • 3.1.认识二叉搜索树
        • 3.2.二叉搜索树应用举例

一、树结构简介

1.1.简单了解树结构

什么是树?

真实的树:

在这里插入图片描述

树的特点:

  • 树一般都有一个,连接着根的是树干
  • 树干会发生分叉,形成许多树枝,树枝会继续分化成更小的树枝
  • 树枝的最后是叶子

现实生活中很多结构都是树的抽象,模拟的树结构相当于旋转180°的树。

在这里插入图片描述

树结构对比于数组/链表/哈希表有哪些优势呢:

数组:

  • 优点:可以通过下标值访问,效率高;
  • 缺点:查找数据时需要先对数据进行排序,生成有序数组,才能提高查找效率;并且在插入和删除元素时,需要大量的位移操作

链表:

  • 优点:数据的插入和删除操作效率都很高;
  • 缺点:查找效率低,需要从头开始依次查找,直到找到目标数据为止;当需要在链表中间位置插入或删除数据时,插入或删除的效率都不高。

哈希表:

  • 优点:哈希表的插入/查询/删除效率都非常高;
  • 缺点:空间利用率不高,底层使用的数组中很多单元没有被利用;并且哈希表中的元素是无序的,不能按照固定顺序遍历哈希表中的元素;而且不能快速找出哈希表中最大值或最小值这些特殊值。

树结构:

优点:树结构综合了上述三种结构的优点,同时也弥补了它们存在的缺点(虽然效率不一定都比它们高),比如树结构中数据都是有序的,查找效率高;空间利用率高;并且可以快速获取最大值和最小值等。

总的来说:每种数据结构都有自己特定的应用场景

树结构:

  • 树(Tree):由 n(n ≥ 0)个节点构成的有限集合。当 n = 0 时,称为空树

对于任一棵非空树(n > 0),它具备以下性质:

  • 数中有一个称为**根(Root)**的特殊节点,用 **r **表示;
  • 其余节点可分为 m(m > 0)个互不相交的有限集合 T1,T2,…,Tm,其中每个集合本身又是一棵树,称为原来树的子树(SubTree)

树的常用术语:

在这里插入图片描述

  • 节点的度(Degree):节点的子树个数,比如节点B的度为2;
  • 树的度:树的所有节点中最大的度数,如上图树的度为2;
  • 叶节点(Leaf)度为0的节点(也称为叶子节点),如上图的H,I等;
  • 父节点(Parent):度不为0的节点称为父节点,如上图节点B是节点D和E的父节点;
  • 子节点(Child):若B是D的父节点,那么D就是B的子节点;
  • 兄弟节点(Sibling):具有同一父节点的各节点彼此是兄弟节点,比如上图的B和C,D和E互为兄弟节点;
  • 路径和路径长度:路径指的是一个节点到另一节点的通道,路径所包含边的个数称为路径长度,比如A->H的路径长度为3;
  • 节点的层次(Level):规定根节点在1层,其他任一节点的层数是其父节点的层数加1。如B和C节点的层次为2;
  • 树的深度(Depth):树种所有节点中的最大层次是这棵树的深度,如上图树的深度为4;
1.2.树结构的表示方式
  • 最普通的表示方法

在这里插入图片描述

如图,树结构的组成方式类似于链表,都是由一个个节点连接构成。不过,根据每个父节点子节点数量的不同,每一个父节点需要的引用数量也不同。比如节点A需要3个引用,分别指向子节点B,C,D;B节点需要2个引用,分别指向子节点E和F;K节点由于没有子节点,所以不需要引用。

这种方法缺点在于我们无法确定某一结点的引用数。

  • 儿子-兄弟表示法

在这里插入图片描述

这种表示方法可以完整地记录每个节点的数据,比如:

//节点A
Node{
  //存储数据
  this.data = data
  //统一只记录左边的子节点
  this.leftChild = B
  //统一只记录右边的第一个兄弟节点
  this.rightSibling = null
}

//节点B
Node{
  this.data = data
  this.leftChild = E
  this.rightSibling = C
}

//节点F
Node{
  this.data = data
  this.leftChild = null
  this.rightSibling = null
}

这种表示法的优点在于每一个节点中引用的数量都是确定的。

  • 儿子-兄弟表示法旋转

以下为儿子-兄弟表示法组成的树结构:

在这里插入图片描述

将其顺时针旋转45°之后:

在这里插入图片描述

这样就成为了一棵二叉树,由此我们可以得出结论:任何树都可以通过二叉树进行模拟。但是这样父节点不是变了吗?其实,父节点的设置只是为了方便指向子节点,在代码实现中谁是父节点并没有关系,只要能正确找到对应节点即可。

二、二叉树

2.1.二叉树简介

二叉树的概念:如果树中的每一个节点最多只能由两个子节点,这样的树就称为二叉树

二叉树十分重要,不仅仅是因为简单,更是因为几乎所有的树都可以表示成二叉树形式。

二叉树的组成

  • 二叉树可以为空,也就是没有节点;
  • 若二叉树不为空,则它由根节点和称为其左子树TL和右子树TR的两个不相交的二叉树组成;

二叉树的五种形态

在这里插入图片描述

上图分别表示:空的二叉树、只有一个节点的二叉树、只有左子树TL的二叉树、只有右子树TR的二叉树和有左右两个子树的二叉树。

二叉树的特性

  • 一个二叉树的第 i 层的最大节点树为:2(i-1),i >= 1;
  • 深度为k的二叉树的最大节点总数为:2k - 1 ,k >= 1;
  • 对任何非空二叉树,若 n0 表示叶子节点的个数,n2表示度为2的非叶子节点个数,那么两者满足关系:n0 = n2 + 1;如下图所示:H,E,I,J,G为叶子节点,总数为5;A,B,C,F为度为2的非叶子节点,总数为4;满足n0 = n2 + 1的规律。

在这里插入图片描述

2.2.特殊的二叉树

完美二叉树

完美二叉树(Perfect Binary Tree)也成为满二叉树(Full Binary Tree),在二叉树中,除了最下一层的叶子节点外,每层节点都有2个子节点,这就构成了完美二叉树。

在这里插入图片描述

完全二叉树

完全二叉树(Complete Binary Tree):

  • 除了二叉树最后一层外,其他各层的节点数都达到了最大值;
  • 并且,最后一层的叶子节点从左向右是连续存在,只缺失右侧若干叶子节点;
  • 完美二叉树是特殊的完全二叉树;

在这里插入图片描述

在上图中,由于H缺失了右子节点,所以它不是完全二叉树。

2.3.二叉树的数据存储

常见的二叉树存储方式为数组链表

使用数组:

  • 完全二叉树:按从上到下,从左到右的方式存储数据。

在这里插入图片描述

节点ABCDEFGH
序号12345678

使用数组存储时,取数据的时候也十分方便:左子节点的序号等于父节点序号 * 2,右子节点的序号等于父节点序号 * 2 + 1 。

  • 非完全二叉树:非完全二叉树需要转换成完全二叉树才能按照上面的方案存储,这样会浪费很大的存储空间。

在这里插入图片描述

节点ABC^^F^^^^^^M
序号12345678910111213

使用链表

二叉树最常见的存储方式为链表:每一个节点封装成一个Node,Node中包含存储的数据、左节点的引用和右节点的引用。

在这里插入图片描述

三、二叉搜索树

3.1.认识二叉搜索树

二叉搜索树BST,Binary Search Tree),也称为二叉排序树二叉查找树

二叉搜索树是一棵二叉树,可以为空;

如果不为空,则满足以下性质

  • 条件1:非空左子树的所有键值小于其根节点的键值。比如三中节点6的所有非空左子树的键值都小于6;
  • 条件2:非空右子树的所有键值大于其根节点的键值;比如三中节点6的所有非空右子树的键值都大于6;
  • 条件3:左、右子树本身也都是二叉搜索树;

在这里插入图片描述

如上图所示,树二和树三符合3个条件属于二叉树,树一不满足条件3所以不是二叉树。

总结:二叉搜索树的特点主要是较小的值总是保存在左节点上,相对较大的值总是保存在右节点上。这种特点使得二叉搜索树的查询效率非常高,这也就是二叉搜索树中"搜索"的来源。

3.2.二叉搜索树应用举例

下面是一个二叉搜索树:

在这里插入图片描述

若想在其中查找数据10,只需要查找4次,查找效率非常高。

  • 第1次:将10与根节点9进行比较,由于10 > 9,所以10下一步与根节点9的右子节点13比较;
  • 第2次:由于10 < 13,所以10下一步与父节点13的左子节点11比较;
  • 第3次:由于10 < 11,所以10下一步与父节点11的左子节点10比较;
  • 第4次:由于10 = 10,最终查找到数据10 。

在这里插入图片描述

同样是15个数据,在排序好的数组中查询数据10,需要查询10次:

在这里插入图片描述

其实:如果是排序好的数组,可以通过二分查找:第一次找9,第二次找13,第三次找15…。我们发现如果把每次二分的数据拿出来以树的形式表示的话就是二叉搜索树。这就是数组二分法查找效率之所以高的原因。

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

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

相关文章

Redis数据库双写一致性解决方案

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

SpringCloud微服务:Nacos和Eureka的区别

目录 配置&#xff1a; 区别&#xff1a; ephemeral设置为true时 ephemeral设置为false时&#xff08;这里我使用的服务是order-service&#xff09; 1. Nacos与eureka的共同点 都支持服务注册和服务拉取 都支持服务提供者心跳方式做健康检测 2. Nacos与Eu…

vscode调试pytorch的DistributedDataParallel代码

这里写自定义目录标题 一、查找launch.py二、修改launch.json三、特别提醒3.1 错误的写法3.2 正确的写法 一、查找launch.py 使用代码。 find / -name launch.py | grep distributed得到的结果如下 这里我们得到了两个结果&#xff0c;看目标文件的路径名&#xff0c;第二个…

深度学习到智能小车(1)深度学习框架

0.前提 最近新开了一门叫机器学习的课程&#xff0c;老师一直在跟我们讲一些有关这方面的知识&#xff0c;告诉我们一定要学好数学&#xff0c;因为数学是算法的基础。我手上的donkeycar刚好也涉及到Keras深度神经网络&#xff0c;所以出于好奇我去图书馆借回了一本叫《Keras深…

一键免费去除视频水印和字幕的AI工具

最近有学员经常让我分享好用的智能抹除视频水印字幕AI工具&#xff0c;今天就给大家分享一个我经常用到的这款工具——腾讯智影&#xff0c;这个平台提供的智能抹除功能&#xff0c;借助这个工具我们可以将视频中不需要的字幕或者水印删除掉。 不过这款工具每天有三次免费次数…

端口映射软件

今天给大家介绍一个自己制作的工具&#xff0c;本工具可以把本地自己的项目映射到外网可以访问,自己有域名可以使用自己的,没有可以用软件自带的三级域名! Token获取 地址&#xff1a;传送 打开上面网址注册账号&#xff0c;然后点击验证&#xff0c;复制里面的值即可。 软件…

openpyxl获取单元格的主题色的颜色值

&#x1f4e2;作者&#xff1a; 小小明-代码实体 &#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/as604049322 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 欢迎讨论&#xff01; openpyxl 支持以下几种颜色类型&#xff1a; RGB (Red, Green, …

Stable Diffusion - StableDiffusion WebUI 软件升级与扩展兼容

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/134463035 目前&#xff0c;StableDiffusion WebUI 的版本是 1.6.0&#xff0c;同步更新 controlnet、tagcomplete、roop、easy-prompt-selector等…

Go 语言变量类型和声明详解

在Go中&#xff0c;有不同的变量类型&#xff0c;例如&#xff1a; int 存储整数&#xff08;整数&#xff09;&#xff0c;例如123或-123float32 存储浮点数字&#xff0c;带小数&#xff0c;例如19.99或-19.99string - 存储文本&#xff0c;例如“ Hello World”。字符串值用…

批量替换WordPress文章内图片链接

在WordPress使用过程中&#xff0c;如果中途更换了域名&#xff0c;原先文章内的图片使用的是原来的域名&#xff0c;就会造成文章页里面的图片链接无法显示。如果从后台文章挨个修改就比较麻烦。可以通过数据库进行批量替换即可。 使用 PHPMyadmin 打开 数据库&#xff0c;登…

我所理解的 UI Toolkit 启蒙阶段(一)

我所理解的 UI Toolkit 启蒙阶段&#xff08;一&#xff09; 对于自己不会的新东西的学习&#xff0c;我认为最合适的路径就是&#xff1a; 实例教学视频 —> 实操熟悉 —> 官方文档查漏补缺 —> 拟定思路实现功能 但这 4 步并非每一步都需要下 100% 的功夫&#x…

Linux C 线程

线程 概述线程和进程的异同如何选择使用进程还是线程 函数获取进程自身ID  pthread_self创建线程  pthread_create退出线程  pthread_exit线程等待  pthread_join 四种线程模型1 &#xff09;单线程2 &#xff09;单线程3 &#xff09;双线程4 &#xff09;三线程 概述…

选择Amazon EC2,走进云端新时代

目录 前言 选择云服务器 / 海外服务器需要关注的重点 Amazon EC2 云服务器的优势所在 文末总结 前言 常言道&#xff0c;工欲善其事必先利其器&#xff0c;无论你是资深开发者&#xff0c;还是普通爱好者&#xff0c;在日常开发和学习生活中都需要用到云服务器提供的丰富的…

自建es数据迁移阿里云方案

一、ElasticSearch数据迁移方法介绍 https://help.aliyun.com/document_detail/170095.html?spma2c4g.26937906.0.0.429240c9ymiXGm 可以通过Logstash、reindex和OSS等多种方式完成阿里云Elasticsearch间数据迁移、Elasticsearch数据迁移至Openstore存储中、自建Elasticsear…

GB28181学习(十六)——基于jrtplib实现tcp被动和主动收流

前言 GB/T28181-2022实时流的传输方式介绍&#xff1a;https://blog.csdn.net/www_dong/article/details/134255185 tcp passive收流 流程图 注意&#xff1a; m字段指定传输方式为TCP/RTP/AVP&#xff1b;sdp信息中增加"asetup:passive"&#xff1b;SIP服务器启…

微服务学习 | Ribbon负载均衡、Nacos注册中心、微服务技术对比

Ribbon负载均衡 负载均衡流程 负载均衡策略 通过定义IRule实现可以修改负载均衡规则&#xff0c;有两种方式&#xff1a; 1. 代码方式:在服务消费者order-service中的OrderApplication类中&#xff0c;定义一个新的IRule: 2.配置文件方式: 在order-service的application.yml…

技术分享 | 如何写好测试用例?

对于软件测试工程师来说&#xff0c;设计测试用例和提交缺陷报告是最基本的职业技能。是非常重要的部分。一个好的测试用例能够指示测试人员如何对软件进行测试。在这篇文章中&#xff0c;我们将介绍测试用例设计常用的几种方法&#xff0c;以及如何编写高效的测试用例。 ## 一…

【Rust】快速教程——模块mod与跨文件

前言 道尊&#xff1a;没有办法&#xff0c;你的法力已经消失&#xff0c;我的法力所剩无几&#xff0c;除非咱们重新修行&#xff0c;在这个世界里取得更多法力之后&#xff0c;或许有办法下降。——《拔魔》 \;\\\;\\\; 目录 前言跨文件mod多文件mod 跨文件mod //my_mod.rs…

C#语言的由来与发展历程

C#语言的由来与发展历程可以追溯到2000年&#xff0c;当时微软公司为了在.NET平台上开发应用程序&#xff0c;发布了一种新的编程语言——C#。C#语言的设计目标是成为一种简单、现代、通用和面向对象的编程语言&#xff0c;为开发者提供更强大的生产力、更强大的面向对象支持和…

Line多账号如何运营?

Line在亚洲地区非常流行&#xff0c;特别是在日本、台湾、泰国等地&#xff0c;是当地最受欢迎的即时通讯应用之一。 除了基本的聊天功能外&#xff0c;Line还提供了各种各样的贴图、表情包和游戏等娱乐功能&#xff0c;吸引了大量的用户。 一、选择利用line进行海外营销的原…