【数据结构】非线性表----树详解

news2024/11/13 8:05:13

是一种非线性结构,它是由**n(n>=0)**个有限结点组成一个具有层次关系的集合。具有层次关系则说明它的结构不再是线性表那样一对一,而是一对多的关系;随着层数的增加,每一层的元素个数也在不断变化(由上一层和该层的对应关系决定)。

关于树的名称的由来,是因为它的结构类型很像现实中的树倒过来,故称作——树。
在这里插入图片描述

根据树的名称,也对其所包含的元素进行了命名和定义。

树的基本术语

1.结点:包含一个数据元素及若干指向其子树的分支;

2.结点的度:一个结点拥有的子树的数目;

3.叶子或终端结点:度为0的结点;

4.非终端结点或分支结点:度不为0的结点;

5.树的度:树内各结点的度的最大值;(需要注意,树的度和结点的度的定义是有略微差异的)

除此之外,还使用人类亲缘关系进行了一系列描述:(注:下图的关系与节点名称无关,仅代表树的结构)
在这里插入图片描述

6.孩子结点或子结点:结点的子树的根称为该结点的孩子结点或子结点;

7.双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的双亲结点或父结点;

8.兄弟结点:同一个双亲的孩子之间互称兄弟;

9.祖先结点:从根到该结点所经分支上的所有结点;

10.子孙结点:以某结点为根的子树中任一结点都称为该结点的子孙;

11.结点的层次:从根开始定义起,根为第一层,根的孩子为第二层。若某结点在第L层.则其子树的根就在第L+1层;

12.堂兄弟结点:其双亲在同一层的结点互为堂兄弟;

13.树的深度或高度:树中结点的最大层次;

14.森林:由m(m>=0)棵互不相交的树的集合称为森林;

15.有序树和无序树:树中结点的各子树从左到右是有次序的,不能互换,称该树为有序树,否则称为无序树;

16.路径和路径长度:路径是由树中的两个结点之间的结点序列构成的。而路径长度是路径上所经过的边的个数

树的基本特征

针对树,我们有很多可以说的点。这里我们主要从其结构特征来进行总结。

  • 任何一棵树都是由根和子树构成的——子树又是一棵树——树是递归定义的

  • 树的根结点没有前驱;除根结点外的所有结点有且只有一个前驱(也就是一个父节点)

  • 树中所有结点有零个或多个后继

  • 子树是不相交的。

  • 当不再有子树的时候就说明该树已经到了尾结点。

树的公式

事实上,基于树的数据结构,可以衍生出很多数学公式来对其进行计算,但是这里只介绍基本的两个(其他重要的公式会在二叉树中进行介绍)

节点数量
  • 对于一棵有 n 个节点的树,节点数量公式为:n = I + L 其中,I 是内节点数量,L 是叶节点数量。
边数
  • 一棵有 n 个节点的树有 n−1 条边。

树的构建

树的存储结构主要有以下几种方法,每种方法都有其优缺点和适用场景:

1. 父节点表示法(Parent Representation)

每个节点记录其父节点的编号或指针。这种方法使用一个数组,其中每个元素表示节点,其值是该节点的父节点的索引。

  • 结构

    parent[i] 表示第 i 个节点的父节点
    
  • 示例

    节点:  0  1  2  3  4  5
    父节点: -1  0  0  1  1  2  (-1 表示根节点)
    
  • 优点:简单,适合快速查找父节点。

  • 缺点:查找子节点较慢,需要遍历整个数组。

2. 孩子表示法(Child Representation)

每个节点记录其所有子节点。这种方法使用一个链表或数组,其中每个节点包含一个指向其子节点列表的指针。

  • 结构

    children[i] 表示第 i 个节点的子节点列表
    
  • 示例

    节点:   0  1  2  3  4  5
    子节点: [1,2] [3,4] [5] [] [] []
    
  • 优点:适合快速查找子节点。

  • 缺点:查找父节点较慢,需要记录父节点指针或进行额外处理。

以上两种方法的缺点和优点是互补的。那么是否有更为方便的方法呢?

3. 孩子兄弟表示法(Left-Child Right-Sibling Representation)

当我们需要定义很多孩子的时候,我们可以使用左孩子右兄弟的定义法

也就是说根节点只指向它的第一个孩子结点,而其他的孩子节点就交给第一个孩子节点去指向

将树转换为二叉树,每个节点记录其最左子节点和右兄弟节点。这种方法使用两个指针,一个指向最左子节点,另一个指向右兄弟。

  • 结构

    节点: node
    左孩子: leftChild
    右兄弟: rightSibling
    
  • 示例

    节点:    0
            / \
           1   2
          / \
         3   4
    转换为:
    节点:    0
           /  \
          1    2
         /
        3
         \
          4
    
  • 优点:能将任意树转换为二叉树,利用二叉树的遍历和处理方法。

  • 缺点:需要两个指针,内存开销较大。

4. 邻接表表示法(Adjacency List Representation)

通常用于存储图结构,但也可以用于树。每个节点记录其相邻节点(即子节点和父节点)。

  • 结构

    adjList[i] 表示第 i 个节点的相邻节点列表
    
  • 示例

    节点:   0  1  2  3  4  5
    相邻节点: [1,2] [0,3,4] [0,5] [1] [1] [2]
    
  • 优点:适合处理树和图的遍历和搜索。

  • 缺点:需要额外处理以区分子节点和父节点。

5. 邻接矩阵表示法(Adjacency Matrix Representation)

使用一个二维数组表示节点之间的连接关系。通常用于稠密图,但在某些情况下也可用于树。

  • 结构

    adjMatrix[i][j] 表示节点 i 和节点 j 之间是否有边(0 或 1)
    
  • 示例

    节点:  0  1  2  3  4  5
    邻接矩阵:
    [0, 1, 1, 0, 0, 0]
    [1, 0, 0, 1, 1, 0]
    [1, 0, 0, 0, 0, 1]
    [0, 1, 0, 0, 0, 0]
    [0, 1, 0, 0, 0, 0]
    [0, 0, 1, 0, 0, 0]
    
  • 优点:简单,适合快速查找任意两个节点之间是否有边。

  • 缺点:存储空间开销大,不适合稀疏树。

这些存储结构各有特点,选择哪种方法主要取决于具体应用需求,例如查找子节点还是父节点更频繁,内存开销是否是主要考虑因素等。

树的初始化和一些基本操作

#include <stdio.h>
#include <stdlib.h>

// 定义树节点结构
typedef struct TreeNode {
    int data;
    struct TreeNode* child1;
    struct TreeNode* child2;
    struct TreeNode* child3;
    struct TreeNode* child4;
    ...
} TreeNode;

//树的初始化
TreeNode* createNode(int data)
{
    TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
    if(!newNode){
        printf("failed!\n");
        return NULL;
    }
    newNode->data = data;
    newNode->child1 = NULL;
    newNode->child2 = NULL;
    ...
    return newNode;
}

//插入、查找、遍历...
TreeNode* insertTree(TreeNode* parent,int data);
TreeNode* findTree(TreeNode* parent,int data);
TreeNode* inorderTraversal(TreeNode* parent);
...

总结

单纯的树实际上用处不大(子节点过多)。但是对于文件系统、目录以及某些分层过多的系统,使用的就是树。

通常在优化的数据结构中,使用更多的是叫做二叉树的数据结构

这是基于树的数据结构,一个根节点只有两个孩子结点,在下一节我们将会对二叉树进行剖析,敬请期待。
在这里插入图片描述

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

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

相关文章

算法——双指针(day3)

611.有效三角形的个数 611. 有效三角形的个数 - 力扣&#xff08;LeetCode&#xff09; 题目解析&#xff1a; 三角形的判定很简单&#xff0c;任意两边之和大于第三边即可。按照正常情况&#xff0c;我们得判断3次才可以确认是否构成三角形。 因为c在本来就是最大的情况下与…

安全测试必学神器 --BurpSuite 安装及使用实操

BurpSuite是一款功能强大的集成化安全测试工具&#xff0c;专门用于攻击和测试Web应用程序的安全性。适合安全测试、渗透测试和开发人员使用。本篇文章基于BurpSuite安装及常用实操做详解&#xff0c;如果你是一名安全测试初学者&#xff0c;会大有收获&#xff01; 一、BurpS…

C++ Qt 登录界面 Login

效果: 核心代码: #include "simpleapp.h" #include "ui_simpleapp.h" #include <QMessageBox>SimpleApp::SimpleApp(QWidget *parent): QMainWindow(parent), ui(new Ui::SimpleApp) {ui->setupUi(this); }SimpleApp::~SimpleApp() {delete ui; …

ROS、pix4、gazebo、qgc仿真ubuntu20.04

一、ubuntu、ros安装教程比较多&#xff0c;此文章不做详细讲解。该文章基于ubuntu20.04系统。 pix4参考地址&#xff1a;https://docs.px4.io/main/zh/index.html 二、安装pix4 1. git clone https://github.com/PX4/PX4-Autopilot.git --recursive 2. bash ./PX4-Autopilot…

MQTT服务端EMQX开源版安装和客户端MQTTX介绍

一、EMQX是什么 EMQX 是一款开源的大规模分布式 MQTT 消息服务器&#xff0c;功能丰富&#xff0c;专为物联网和实时通信应用而设计。EMQX 5.0 单集群支持 MQTT 并发连接数高达 1 亿条&#xff0c;单服务器的传输与处理吞吐量可达每秒百万级 MQTT 消息&#xff0c;同时保证毫秒…

C语言函数:编程世界的魔法钥匙(2)

引言 注&#xff1a;由于这部分内容比较抽象&#xff0c;而小编我又是一个刚刚进入编程世界的计算机小白&#xff0c;所以我的介绍可能会有点让人啼笑皆非。希望大家多多包涵&#xff01;万分感谢&#xff01;待到小编我学有所成&#xff0c;一定会把这块知识点重新介绍一遍&a…

Django前后端打通

跨域问题 【 0 】前言 ​ ​ 同源策略&#xff08;Same Origin Policy&#xff09;是浏览器安全策略的重要组成部分&#xff0c;它限制了来自不同源的网页之间的数据交互&#xff0c;以防止恶意攻击。当一个网页尝试执行与它的源&#xff08;即协议、域名和端口&#xff09…

Re:从零开始的C++世界——类和对象(下)

文章目录 前言1.再谈构造函数&#x1f34e;构造函数体赋值&#x1f34e;初始化列表&#x1f34e;特性&#x1f34c;特性一&#x1f34c;特性二&#x1f34c;特性三&#x1f34c;特性四&#x1f34c;特性五 &#x1f34e;explicit 关键字 2.static成员&#x1f34e;概念&#x1…

node.js动漫论坛-计算机毕业设计源码09947

摘 要 随着移动互联网的飞速发展&#xff0c;智能手机和移动互联网已经成为人们日常生活中不可或缺的一部分。在这样的背景下&#xff0c;微信小程序应运而生&#xff0c;凭借其无需下载安装、即用即走的特点&#xff0c;迅速成为连接用户与服务的桥梁。动漫作为一种深受年轻人…

《0基础》学习Python——第十六讲 __文件读写

<文件读写> 一、什么是文件读写 文件读写是指在Python程序中对文件进行读取和写入操作。通过文件读写&#xff0c;可以读取文件中的数据&#xff0c;或者向文件中写入数据。 Python提供了多种文件读写的方式&#xff0c;其中最常用的方式是使用open()函数打开一个文件&a…

ssrf复习(及ctfshow351-360)

1. SSRF 概述 服务器会根据用户提交的URL发送一个HTTP请求。使用用户指定的URL&#xff0c;Web应用可以获取图片或者文件资源等。典型的例子是百度识图功能。 如果没有对用户提交URL和远端服务器所返回的信息做合适的验证或过滤&#xff0c;就有可能存在“请求伪造"的缺陷…

huawei USG6001v1学习---信息安全概念

目录 1.什么是分布式&#xff1f; 2.什么是云计算&#xff1f; 3.APT攻击 4.安全风险能见度不足 5.常见的一些攻击 6.交换机转发原理&#xff1f; 7.各层攻击类型 7.1链路层&#xff1a; 7.2网络层&#xff1a; 7.3传输层&#xff1a; 7.4应用层&#xff1a; 1.什么…

mybatis plus json 格式转换踩坑记录

项目中有个字段存的是json数据。 我对应的实体类用的 fastjson2 中的 JsonObject 对象。 实体类&#xff1a; Data Accessors(chain true) TableName(value "plugin_template", autoResultMap true) public class PluginTemplateDo {TableId(type IdType.AUTO)p…

Mybatis<collection>实现一对多

时隔多年又用到这样的查询方式了,提前声明一下分页最后返回的数据会小于每页条数&#xff0c;废话不多说直接上代码&#xff01; Data public class PbcUserTargetTaskPageVO {ApiModelProperty("个人绩效指标id")private Long id;ApiModelProperty("月份"…

Modbus通讯接口选择分析

Modbus通讯接口选择分析 Modbus通讯接口的选择涉及到多个方面的考量&#xff0c;包括但不限于通讯距离、数据传输速率、成本、设备兼容性以及应用场景等。下面将从这些角度出发&#xff0c;对Modbus通讯接口的选择进行详细的分析。 Ip67防水面板法兰插座 通讯距离 Modbus通讯…

VLAN 划分案例详解

vlan 的应用在网络项目中是非常广泛的&#xff0c;基本上大部分的项目都需要划分 vlan&#xff0c;这里从基础的 vlan 的知识开始&#xff0c;了解 vlan 的划分原理。 为什么需要 vlan&#xff1a; 1、什么是 VLAN&#xff1f; VLAN&#xff08;Virtual LAN&#xff09;&…

【面试题】Redo log和Undo log

Redo log 介绍Redo log之前我们需要了解一下&#xff0c;mysql数据操作的流程&#xff1a; 上述就是数据操作的流程图&#xff0c;可以发现sql语句并不是直接操作的磁盘而是通过操作内存&#xff0c;然后进行内存到磁盘的一个同步。这里我们必须要了解一些区域&#xff1a; 缓…

推荐一款使用Java EE技术栈的企业应用定制化开发平台(带源码)

前言 在数字化转型的浪潮中&#xff0c;企业面临着多样化的信息系统建设需求。现有的软件系统往往存在定制化程度低、开发周期长、成-本高等问题。此外&#xff0c;随着企业规模的扩大和业务的复杂化&#xff0c;传统的软件系统难以满足灵活多变的业务需求。 为了解决这些痛点…

【前端7*】表格-表单2(弹窗在子组件)父子组件调用 vue element-ui

vue element-ui 中表单弹框的使用 写在最前面一、子组件 HelloWorld.vue1. 弹窗部分、将 visible 传值给父组件2.表单的 ruleForm 校验方法3.表单确认方法4. 提交确认方法&#xff1a;handleSummit5.表单渲染 二、父组件 HomeView.vue1.新增按钮、查看和编辑2.引用子组件弹窗3.…

【Linux网络】select{理解认识select/select与多线程多进程/认识select函数/使用select开发并发echo服务器}

文章目录 0.理解/认识回顾回调函数select/pollread与直接使用 read 的效率差异 1.认识selectselect/多线程&#xff08;Multi-threading&#xff09;/多进程&#xff08;Multi-processing&#xff09;select函数socket就绪条件select的特点总结 2.select下echo服务器封装套接字…