【笔记】树(Tree)

一、树的基本概念

1、树的简介

之前我们都是在谈论一对一的线性数据结构,可现实中也有很多一对多的情况需要处理,所以我们就需要一种能实现一对多的数据结构--"树"。

2、树的定义

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

在n=0时称为空树。在任意一颗非空树中:

  1. 有且仅有一个特定的称为根(Root)的结点;
  2. 当n>1时,其余结点可分为m(m > 0)个互不相交的有限集T1、T2、...... 、Tm,其中每一个集合本身又是一棵树,并且称为根的子树(SubTree)。

注意:在树型结构中,子树之间不能有交集,否则就不能是树形结构。 如果相交了,那就是图。

3、树的一些基本术语

就拿这张图来举例子

  1. 节点的度:一个节点含有的子树的个数称为该节点的度; 如上图:A的为6
  2. 叶节点或终端节点:度为0的节点称为叶节点; 如上图:B、C、H、I...等节点为叶节点
  3. 非终端节点或分支节点:度不为0的节点; 如上图:D、E、F、G...等节点为分支节点
  4. 双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图:A是B的父节点
  5. 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点; 如上图:B是A的孩子节点
  6. 兄弟节点:具有相同父节点的节点互称为兄弟节点; 如上图:B、C是兄弟节点
  7. 树的度:一棵树中,最大的节点的度称为树的度; 如上图:树的度为6
  8. 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
  9. 树的高度或深度:树中节点的最大层次; 如上图:树的高度为4
  10. 堂兄弟节点:双亲在同一层的节点互为堂兄弟;如上图:H、I互为兄弟节点
  11. 节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先
  12. 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙
  13. 森林:由m(m>0)棵互不相交的树的集合称为森林;

二、树的存储结构

提及存储结构,那必然会想到两种常用的存储结构。一个是顺序存储结构,另一个则是链式存储结构。这两个存储结构在我们之前学习其他的数据结构中也学习过。

树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,既要保存值域,也要保存结点和结点之间的关系 。实际中树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法等。我们这里就简单的了解双亲表示法,孩子表示法以及孩子兄弟表示法。

1、双亲表示法

我们人可能因为种种原因,没有孩子,但无论是谁都不可能是从石头里蹦出来的(孙悟空除外,它显然不算是人),所以人一定就会有父母。树这种结构也不例外,除了根结点外,其余的每个结点不一定有孩子,但一定有且一个双亲。

复制代码
#define MAX_TREE_SIZE 100

typedef int TElemType;              //树结点的数据类型,目前暂定为整形

typedef struct PTNode
{
    TElemType data;                //结点数据
    int parent;                    //双亲位置
}PTNode;

typedef struct
{
    PTNode nodes[MAX_TREE_SIZE];    //结点数组    
    int r,n;                        //根的位置和结点数
}

这样的存储结构,我们根据结点的 parent指针很容易找到它的双亲结点,所用的时间复杂度为O(1)。但麻烦的是如果想要知道结点的孩纸是谁,不好意思,请遍历整个结构才行。

2、孩子表示法

把每个结点的孩子结点排列起来,以单链表作为存储结构,则n个结点有n个孩子链表,如果是叶子结点则此单链表为空。然后n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组中。

为此,需要设计两种结点结构,一个是孩子链表的孩子结点,如下表所示

其中,child是数据域,用来存储某个结点在表头数组中的下标;next是指针域,用来存储指向某个结点的下一个孩子结点的指针。

另一个是表头数组的表头结点,如下表所示

其中,data是数据域,存储某个结点的数据信息;firstchild是头指针域,存储该结点的孩子链表的头指针。

复制代码
#define max_TREE_SIZE 100

typedef int TElemType;                //树结点的数据类型,目前暂定为整形

typedef struct CTNode                 //孩子结点
{
    int child;
    struct CTNode* next;    
} *ChildPtr;

typedef strucct                        //表头结构
{
    TElemType data;
    ChildPTr firstchild;
}CTBox;

typedef struct                         //树结构
{
    CTBox nodes[MAX_TREE_SIZE];        //结点数组
    int r,n;                           //结点位置和结点数
}CTree;

这样的数据结构对于我们要查找某个结点的孩子,或者找某个结点的兄弟,只需要查找这个结点的孩子单链表即可。对于遍历整棵树也是很方便的,对头结点的数组循环即可。

但是如果想知道某个结点的双亲是谁?就需要遍历整棵树。所以就衍生出了将二者合二为一的方法:孩子兄弟表示法。

3、孩子兄弟表示法

复制代码
typedef int DataType;
struct Node
{
 struct Node* _firstChild1; // 第一个孩子结点
 struct Node* _pNextBrother; // 指向其下一个兄弟结点
 DataType _data; // 结点中的数据域
};

这种表示法,给查找某个结点的某个孩子带来了方便,只需要通过firstchild找到此结点的长子,然后通过长子结点的nextbrother找到它的二弟,接着一直下去,直到找到具体的孩子。

三、树在实际中的运用(表示文件系统的目录树结构)


以上就是关于树的基本概念和存储结构的知识点。有关二叉树的内容会在下一个章节中再详细描述。

相关推荐
Nontee5 小时前
MySQL 插入冲突了怎么办?两种处理方式入门笔记
数据库·笔记·mysql
浔溺5 小时前
al+大数据每日学习笔记26
笔记·学习
老当益壮梁奶奶6 小时前
Linux软件编程学习笔记(七):线程分离与线程间通信详解
linux·c语言·c++·笔记·学习
sel_96 小时前
【多轮对话论文导读(三)】多轮对话与Agent论文阅读笔记:用户模拟、轨迹生成与长期记忆
论文阅读·人工智能·笔记·深度学习·算法·机器学习
zzm6287 小时前
《SIGIR 2018论文精读|深度学习点击序列模型:对搜索页面点击行为进行序列建模》
笔记·深度学习·推荐系统·论文精读
常驻客栈8 小时前
B-深入理解计算机系统第3版之第8章:异常控制流
笔记·学习·常驻客栈·深入理解计算机系统·学习笔记‘’
Seraphina368 小时前
记一次实验:利用路径分隔符进行网页缓存欺骗
经验分享·笔记·安全·网络安全·缓存
AOwhisky8 小时前
Linux 网络服务架设学习笔记(第五期)——Web 服务(上篇):Apache HTTP Server——从静态到动态
linux·运维·服务器·笔记·学习·云计算·apache
船厂电气自动化ai大模型9 小时前
AI大模型与数学·第57课 傅里叶全套工具链综合实战:串联级数/连续变换/DFT/FFT,图像、音频、扩散模型完整例题
数据结构·人工智能·深度学习·算法·机器学习
wuyk5559 小时前
从零吃透Modbus通信|第3章:STM32 Modbus RTU主机
服务器·开发语言·网络·数据结构·stm32·单片机·嵌入式硬件