数据结构——树的三种表示方法

目录

引言

1.树的定义

2.树的基本概念

3.树的表示方式

(1)双亲表示法

(2)孩子表示法

(3)左孩子右兄弟表示法

(4)树的应用

结束语


引言

在学习完栈和队列的之后后,我们接下来学习新的数据结构——树。

1.树的定义

树是一种非线性数据结构,它模拟了具有层次关系的数据的集合。树(数据结构)在形态上与自然界中的树木具有相似性,因此树才被称之为树,只不过它是倒挂着的树。

树中有一个特别的节点,称为根节点。它是整棵树的起点,没有前驱节点

除根节点外,其余结点被分成M(M > 0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1 <= i<= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继因此,树是递归定义的。

如下图所示:

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

例如这样:

子树是不相交的。

除了根节点外,每个节点有且仅有一个父节点。

一棵N个节点的树有N-1条边。

2.树的基本概念

我们根据这棵树来介绍一下树的基本概念

如下表所示:

术语定义
节点的度一个节点含有的子树的个数称为该节点的度,比如说节点1的度为2
叶节点或终端节点度为0的节点,比如说4,5,6节点
非终端节点或分支节点度不为0的节点,比如说2,3节点
双亲结点或父节点若一个节点含有子节点,则这个节点称为其子节点的父节点。比如说2是4,5的父节点
孩子节点或子节点一个节点含有的子树的根节点称为该节点的子节点,比如说4,5是2的子节点
兄弟节点具有相同父节点的节点互称为兄弟节点,比如说4,5就是兄弟节点
树的度一棵树中,最大的节点的度称为树的度,比如说上面这棵树的度为2
节点的层次从根开始定义起,根为第1层,根的子节点为第2层,以此类推
树的高度或深度树中节点的最大层次,比如说上面这棵树的高度为3
堂兄弟节点双亲在同一层的节点互为堂兄弟,比如说5,6节点
节点的祖先从根到该节点所经分支上的所有节点,比如说1就是所有节点的祖先
子孙以某节点为根的子树中任一节点都称为该节点的子孙,比如说所有节点都是1的子孙
森林由m(m>0)棵互不相交的树的集合称为森林

3.树的表示方式

我们有三种方法表示下面这棵树:

(1)双亲表示法

双亲表示法是用顺序表,也就是数组对树进行表示的。即用顺序表存储各个节点的数据,并且同时存储其双亲节点的下标。

注意:根节点没有双亲节点,所以特别记为-1。

如下图所示:

存储方式如下:

说明:

1.因为根节点没有父节点,将其父节点数组下标设置为-1,根节点存储在顺序表的第1个位置。
2.数据元素2、3、4的父节点为0,父节点数组下标为0,分别存储在顺序表的2、3、4个位置。
3.数据元素5、6的父节点为1,父节点数组下标为1,分别存储在顺序表的第5、6个位置。
4.数据元素7的父节点为3,父节点数组下标为3,存储在顺序表的第7个位置。

优缺点:

优点:查找父节点方便

缺点:在查找子节点或兄弟节点时不够直接,通常需要遍历整棵树。

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 10
typedef int DataType;
typedef struct TreeNode
{DataType data;int parent;
}Node;typedef struct ParentTree
{// 数据结构的树节点Node Tnode[MAXSIZE];int n;		//当前节点个数
}Ptree;// 初始化树
void TreeInit(Ptree* ptree, int x, int parentIndex) 
{if (ptree->n >= MAXSIZE) {printf("Tree is full!\n");return;}ptree->Tnode[ptree->n].data = x;ptree->Tnode[ptree->n].parent = parentIndex;ptree->n++; // 增加节点计数  
}
(2)孩子表示法

树的孩子表示法就是采用顺序表与链表结合的形式,用顺序表存储树的值与链表的头节点,而链表的头节点存储其孩子节点在顺序表中的下标,若没有则记为空(NULL)。

相当于对树进行这样的处理:

存储方式如下:

说明:

添加一个数据(插入一个结点)

  1. 既要在数组中依次添加新的数据。
  2. 也要在其父节点后面用头插法插入。

头插法:数据结构——单链表 

优缺点:

优点:

1.可以快速访问子节点。由于每个节点的子节点都被直接存储在链表中,因此可以快速访问任意节点的所有子节点。

2.易于插入和删除节点。当需要向树中插入或删除节点时,只需在相应的链表中添加或删除节点即可,操作相对简单。

缺点:

查找双亲节点不便。与双亲表示法相反,孩子表示法在查找节点的父节点时不太方便。通常需要从树的根节点开始遍历整个树或至少遍历该节点所在子树的一部分才能找到父节点。

代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>#define MAXSIZE 10
typedef int DataType;
typedef struct ListNode
{int index;struct ListNode* next;
}ListNode;typedef struct TreeNode
{DataType data;ListNode* child;
}TNode;typedef struct Tree
{TNode nodes[MAXSIZE];int n;
}Tree;// 创建一个新的ListNode  
ListNode* createListNode(int index) 
{ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));if (newNode == NULL){perror("malloc fail:");exit(0);}newNode->index = index;newNode->next = NULL;return newNode;
}// 初始化树  
void TreeInit(Tree* t, DataType x) 
{if (t->n >= MAXSIZE) {printf("Tree is full!\n");return;}t->nodes[t->n].data = x;t->nodes[t->n].child = NULL;  t->n++;
}// 向节点的子链表中添加一个新节点  
void InsertChild(Tree* t, int parentIndex, int childIndex)
{if (parentIndex >= t->n || childIndex >= t->n) {printf("error\n");return;}ListNode* newNode = createListNode(childIndex);if (newNode == NULL){perror("malloc fail:");return; // 内存分配失败  }newNode->next = t->nodes[parentIndex].child;t->nodes[parentIndex].child = newNode;
}
(3)左孩子右兄弟表示法

最常用表示树的的方法就是左孩子右兄弟表示法,即定义两个指针,让左指针指向子节点,右指针指向兄弟节点。如果没有节点,则都指向空(NULL)。

如图所示:

说明:

  1. 先找到在谁的后面插入,即找到父节点
  2. 然后再看看父节点的孩子指针空不空
  3. 空的话就插入到父节点的孩子指针域里,如果这个位置有结点的话(孩子指针域不空),就要插入到这个孩子结点的兄弟指针域里,插入方式选择头插法。

代码如下:

#include <stdio.h>
#include <stdlib.h>
typedef int DataType;typedef struct TreeNode
{DataType data;struct TreeNode* leftChild;  // 指向左孩子  struct TreeNode* rightBro; // 指向右兄弟  
} TNode;// 创建一个新的树节点
TNode* createTreeNode(DataType x)
{TNode* newNode = (TNode*)malloc(sizeof(TNode));if (newNode == NULL){perror("malloc fail:");exit(0);}newNode->data = x;newNode->leftChild = NULL;newNode->rightBro = NULL;return newNode;
}void InsertChild(TNode* t, DataType x, int isLeftChild) 
{if (t == NULL) {printf("Cannot insert into NULL node\n");return;}TNode* newNode = createTreeNode(x);if (newNode == NULL) {return;}// 如果isLeftChild为1,表示新节点应该作为左孩子插入  if (isLeftChild) {// 如果当前节点还没有右兄弟,则直接将新节点设置为右兄弟if (t->leftChild == NULL) {t->leftChild = newNode;}// 如果当前节点已经有左孩子,则遍历左孩子的右兄弟链表// 找到最后一个右兄弟,并将新节点插入为它的下一个右兄弟else {TNode* tmp = t->leftChild;while (tmp->rightBro != NULL) {tmp = tmp->rightBro;}tmp->rightBro = newNode;}}// 如果isLeftChild为0,表示新节点应该作为右兄弟插入else{// 如果当前节点还没有右兄弟,则直接将新节点设置为右兄弟if (t->rightBro == NULL) {t->rightBro = newNode;}// 如果当前节点已经有右兄弟,则遍历右兄弟链表// 找到最后一个右兄弟,并将新节点插入为它的下一个右兄弟else {TNode* tmp = t->rightBro;while (tmp->rightBro != NULL) {tmp = tmp->rightBro;}tmp->rightBro = newNode;}}
}
(4)树的应用

在linux环境下目录结构就是有一颗树构成,而在Windows环境下,目录许多内容并不交叉,所以是由森林构成。

结束语

下一篇我们将继续学习树的知识。

感谢各位大佬的支持!!!

求点赞收藏关注!!!

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

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

相关文章

智慧公路大数据运营中心整体解决方案

方案简介&#xff1a; 智慧公路大数据运营中心解决方案的实施&#xff0c;不仅提高了公路交通的运行效率和管理水平&#xff0c;还推动了智慧交通建设的深入发展。通过消除信息孤岛、促进数据共享和开放&#xff0c;实现了交通信息资源的有效整合和利用。未来&#xff0c;随着…

ctfhub-web-SSRF通关攻略

一、内网访问 1.打开ctfhub给的环境地址 2.观察题目 发现让我们访问127.0.0.1下的flag.php 在地址栏后面有一个url参数 ?urlhttp://127.0.0.1/flag.php 提交即可 二、伪协议读取文件 1.打开ctfhub给的环境 2.观察题目 发现让我们读取flag.php文件 读取文件用到的协议是…

QT Mainwindow下指定控件的setMouseTracking(true)和mousemoveevent函数失效-问题解决

目录&#xff1a; 一&#xff0c;问题描述二&#xff0c;解决方法2.1解决依据2.2方法实操 三&#xff0c;参考资料 一&#xff0c;问题描述 ☀️之前碰到过的一个问题&#xff0c;现在分享出来&#xff1a;想在qt哪里搞个鼠标移动在控件显示的图片上&#xff0c;然后实时显示对…

设备状态图表-甘特图

1.背景&#xff1a;设备状态监控图表&#xff0c;监控不同状态的时间段&#xff0c;可以使用甘特图来展示效果 鼠标经过时的数据提示框 2、代码实现 <template><divref"ganttChartRefs":style"{ height: 6.2rem, width: 100% }"class"bg…

java Boss直聘爬虫数据分析

摘要 本报告利用Java和Selenium爬虫技术获取数据&#xff0c;并使用ECharts库对薪资数据进行可视化分析&#xff0c;旨在探究不同经验和学历的薪资分布情况。 数据来源 数据来源于Boss直聘&#xff0c;使用Java结合Selenium库进行数据抓取。 数据总数&#xff1a;约2000家企…

如何设置Winfrom中dataGridView中的内容换行并行高自适应

如何设置Winfrom中dataGridView行高 在 Windows Forms (WinForms) 应用程序中&#xff0c;DataGridView 控件用于显示和编辑数据的表格形式。如果你想要设置 DataGridView 控件中行的高度&#xff0c;可以通过以下几种方式来实现&#xff1a; 1. 通过属性设置行高 你可以直接…

Vue:组件化开发

我们为什么要组件化开发&#xff1f; 在之前的vue中&#xff0c;我们要么是通过本地引入vue.js进行开发&#xff0c;要么就是通过CLI&#xff08;脚手架&#xff09;来创建环境然后单独在App.vue中进行开发&#xff0c;这样的开发模式当然没有问题&#xff0c;但是当项目庞大起…

3 Python开发工具:VSCode+插件

本文是 Python 系列教程第 3 篇&#xff0c;完整系列请查看 Python 专栏。 Visual Studio Code的安装非常简单&#xff0c;就不放这里增加文章篇幅了。 相比PyCharm&#xff0c;VSCode更加轻量&#xff0c;启动速度快。并且搭配Python插件就能实现和Pycharm一样的代码提示、高…

摄影曝光:曝光模式认知

写在前面 学习整理《摄影曝光&#xff1a;拍出好照片的49个关键技法》读书笔记博文内容涉及曝光模式简单认知适合小白认知理解不足小伙伴帮忙指正 &#x1f603;,生活加油 99%的焦虑都来自于虚度时间和没有好好做事&#xff0c;所以唯一的解决办法就是行动起来&#xff0c;认真…

PyTorch深度学习模型训练流程:(二、回归)

回归的流程与分类基本一致&#xff0c;只需要把评估指标改动一下就行。回归输出的是损失曲线、R^2曲线、训练集预测值与真实值折线图、测试集预测值散点图与真实值折线图。输出效果如下&#xff1a; 注意&#xff1a;预测值与真实值图像处理为按真实值排序&#xff0c;图中呈现…

【JS】使用MessageChannel实现深度克隆

前言 通常使用简便快捷的JSON 序列化与反序列化实现深克隆&#xff0c;也可以递归实现或者直接使用lodash。 但 JSON 序列化与反序列化 无法处理如下的循环引用&#xff1a; 实现 MessageChannel 内部使用了浏览器内置的结构化克隆算法&#xff0c;该算法可以在不同的浏览器上…

Qt WebAssembly 警告:构建套件中未设置编译器

目录 Qt WebAssembly 警告:构建套件中未设置编译器问题解决方法 参考资料 Qt WebAssembly 警告:构建套件中未设置编译器 问题 安装好QT之后构建套件中出现黄色感叹号Qt WebAssembly 警告:构建套件中未设置编译器。 原因是现在你只安装了qt for webassembly的qt的库&#xff…

Task-Embedded Control Networks for Few-Shot Imitation Learning

发表时间&#xff1a;CoRL 2018 论文链接&#xff1a;https://readpaper.com/pdf-annotate/note?pdfId4500197057754718210&noteId2424798567891365120 作者单位&#xff1a;Imperial College London Motivation&#xff1a;就像人类一样&#xff0c;机器人应该能够利用来…

JVM上篇:内存与垃圾回收篇-07-方法区

笔记来源&#xff1a;尚硅谷 JVM 全套教程&#xff0c;百万播放&#xff0c;全网巅峰&#xff08;宋红康详解 java 虚拟机&#xff09; 文章目录 7. 方法区7.1. 栈、堆、方法区的交互关系7.2. 方法区的理解7.2.1. 方法区在哪里&#xff1f;7.2.2. 方法区的基本理解7.2.3. HotSp…

无人机之基本结构篇

无人机&#xff08;Unmanned Aerial Vehicle, UAV&#xff09;作为一种无人驾驶的飞行器&#xff0c;其基本结构涵盖了多个关键组件&#xff0c;这些组件共同协作以实现无人机的自主飞行和执行各种任务。以下是无人机基本结构的详细解析&#xff1a; 一、飞机平台系统 机身&am…

vue2表单校验:添加自定义el-form表单校验规则

前言 在vue2表单校验&#xff1a;el-form表单绑定数组并使用rules进行校验_vue2 rules校验-CSDN博客中&#xff0c;使用form原生的rules对表单中每个控件的必填、格式等做了校验。但是保存时&#xff0c;除了验证每一个控件的输入合乎要求外&#xff0c;还需要验证控件之间的数…

SpringBoot集成kafka-生产者发送消息

springboot集成kafka发送消息 1、kafkaTemplate.send()方法1.1、springboot集成kafka发送消息Message对象消息1.2、springboot集成kafka发送ProducerRecord对象消息1.3、springboot集成kafka发送指定分区消息 2、kafkaTemplate.sendDefault()方法3、kafkaTemplate.send(...)和k…

WIN/MAC 图像处理软件Adobe Photoshop PS2024软件下载安装

目录 一、软件概述 1.1 基本信息 1.2 主要功能 二、系统要求 2.1 Windows 系统要求 2.2 macOS 系统要求 三、下载 四、使用教程 4.1 基本界面介绍 4.2 常用工具使用 4.3 进阶操作 一、软件概述 1.1 基本信息 Adobe Photoshop&#xff08;简称PS&#xff09;是一款…

springboot嵌入式数据库实践-H2内嵌数据库(文件、内存)

本文章记录笔者的嵌入式数据库简单实现&#xff0c; 记录简要的配置过程。自用文章&#xff0c;仅作参考。 目录 本文章记录笔者的嵌入式数据库简单实现&#xff0c; 记录简要的配置过程。自用文章&#xff0c;仅作参考。 嵌入式数据库 -------------------------------具…

16岁激活交学费银行卡需要本人实名电话卡,线下营业厅不给办,怎么办?

16岁激活交学费银行卡需要本人实名电话卡&#xff0c;线下营业厅不给办&#xff0c;怎么办&#xff1f; 话卡办理规定&#xff1a; 根据《民法典》和《电话用户真实身份信息登记规定》的相关要求&#xff0c;未满16周岁的用户通常需要在监护人的陪同下办理电话卡&#xff0c;并…