【数据结构】树的概念与结构 | 树的几种常见表示方法

简介: 本章将正式开启数据结构中 “树” 部分的讲解,本章将介绍树的概念和结构,以及树的表示方法。

383a80108554300dd19b44438b1e3265_84d23b15de1140c4b6d599f0e8c03082.gif

前言


本章将正式开启数据结构中 “树” 部分的讲解,本章将介绍树的概念和结构,以及树的表示方法。


0x00 树的概念

📚 树是一种非线性的数据结构,它是由 n(n >= 0)个有限节点组成的一个具有层次关系的集合。


❓ 那么为什么叫 "树" 呢?


💡 我们之所以把它成为 "树",是因为它很像我们现实生活中的树。只是它是倒过来的,根朝上叶子朝下。


0x01 树的结构

① 有一个特殊的节点,成为根节点,根节点不存在前驱节点。


② 除根节点外,其余节点被分成 M(M>0) 个互不相交的集合 T1、T2、……、Tm,期中没一个集合 Ti(1 <= i <= m) 又是一颗结构于树类似的字数。每颗子树的节点有且只有一个前驱,可以有0个或多个后继。


③ 因此,树是递归定义的。因为任何树都会被分成根和子树。


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

58686ce3cbcfb3216fd424b6a0d02800_d6690762c9c343faa42697045a50ae05.png


0x02 树的相关概念

620db63dd46f96132ff151cb06c87f00_958f68b1d8ae49b0ba8f29b868910f2c.png


💧  节点的度:一个节点含有的子树的个数称为该节点的度。 比如上图中,A的度为6。
🍃 叶子结点:又称终端节点,度为0的节点称为叶子结点。 比如上图中,BCHIPQ等节点就是叶子结点,因为它们的度为0。
➰ 分支节点:又称非终端节点,度不为0的节点称为分支节点。 比如上图中,DEFG等节点就是分支节点,因为他们的度不为0。
👨 父节点:又称双亲结点,若一个节点有子节点,则这个节点称作其子节点的父节点。 比如上图中,A是B的父节点。
👶 子节点:又称孩子节点,若一个节点有根节点,则称为该节点的子节点。 如上图,B是A的子节点。
👦 兄弟节点:具有相同父节点的节点互相称为兄弟节点。 同一个父亲生的才算。如上图,B和C是兄弟节点,它们的父节点都是A。
🌳 树的度:一棵树中最大的节点的度称为树的度。 如上图,最大的节点是A,有6个子树,故A的度为6,所以树的度为6。
💭 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推。 也有将根定义为第0层,根的子节点为第1层的。但是我们建议还是使用根为第1层来定义比较好。
🌊 树的高度:又称树的深度,树中节点的最大层次。 如上图,树的高度为 4。
👱‍♂️ 堂兄弟节点:父节点在同一层的节点,它们互为堂兄弟。如上图,H 和 I 互为堂兄弟。
🧔 节点的祖先:从根到该节点所经分支上的所有节点。 如上图·,A是所有节点的祖先。
👨‍👦‍👦 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。 如上图,所有节点都是A的子孙。
🌄 森林:由 m(m > 0) 棵互不相交的树的集合称为森林。 比如并查集,多个树构成森林。


0x02 树的表示

❓ 以前学单链表时只有一个指针,双链表两个指针,但是树有多少个指针是不确定的,因为树没有规定一个节点最多有多少个孩子。那我们该如何定义结构呢?


💬 方式一:假设说明了树的度为N,才能勉强用

struct TreeNode {
    int data;
    struct TreeNode* sub[N]; // 指针数组
};

问题点:


① 可能会存在不少的空间浪费。


② 万一没有限定树的度为多少呢?这个方式就废了。


💬 方式二:vector

// 假设我们定义了一个顺序表
// typedef int STLDataType;  //顺序表的数据类型
// 顺序表中存节点的指针
typedef struct TreeNode* SLDataType; //SeqList
struct TreeNode {
    int data;
    SeqList s;  // s为SLDataType* array;
};

(C++中这里可以用 vector,但是C里没有)


即使你没有告诉我度是多少,我有多少个孩子我就存多少个孩子,所以这里不需要关心度的问题。但是这里 s 的结构相对复杂,s 里面有一个类型为SLDataType* 的数组,这个数组已经是二级指针了,SLDataType 展开后又是一个 struct TreeNode* 。


💬 方式三:双亲表示法

dda6899379267dca9fa8ffbe44301156_222d2d17fea642df9b77e7898015512c.png

利用结构数组存储(更加复杂)

struct TreeNode {
    int parenti;
    int data;
};
[ A -1] [ B0 ] [ C0 ] [ D0 ] ...... [ H 3 ]


  👆  每一个元素中存的是结构体   struct TreeNode arr[10]


每个元素内只存自己的值和父亲的下标(A没有父亲是-1,B的父亲下标是0…… H的父亲是D下标为3),可以通过一个值找到自己父亲。


❓ 上列的方式各有优缺点,那么有没有最优的方法?


⚡ 当然有,它就是 —— 《左孩子右兄弟表示法》  有了这个方法,其他的都是渣渣!


typedef int DataType;
struct Node {
    struct Node* _firstChind1;   // 永远指向第一个孩子
    struct Node* _pNextBrother;  // 指向孩子右边的兄弟
    DataType _data;
};

2b87fa7cd9fae2a8d0f2af89f1750b6a_82edf7c1681048f0bb610464cc0aa31a.png

🔑 解读:无论你有多少个孩子,它都只存两个指针。一个指针永远指向第一个孩子,另一个指针指向孩子右边的兄弟(亲兄弟)。这个树的度无论为多少,也不需要用顺序表存,但是你任何一个节点有多少个孩子都能给你表示出来,通过第一个孩子把所有孩子都找出来。不复杂也没有浪费,只用两个指针就把链接关系都表示出来了,不得不说设计这个的人真是太🐂🍺了!


0x03 树在实际中的运用

文件系统的目录树结构、网络拓扑,最短路径问题,搜索引擎、思维导图等

2fd72ee2134931476471a2713d952f02_79cb2e7365fa4d8394452888b04482a3.png

相关文章
|
1月前
|
存储 算法
数据结构与算法学习二二:图的学习、图的概念、图的深度和广度优先遍历
这篇文章详细介绍了图的概念、表示方式以及深度优先遍历和广度优先遍历的算法实现。
48 1
数据结构与算法学习二二:图的学习、图的概念、图的深度和广度优先遍历
|
11天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
54 16
|
1月前
|
Java C++ 索引
让星星⭐月亮告诉你,LinkedList和ArrayList底层数据结构及方法源码说明
`LinkedList` 和 `ArrayList` 是 Java 中两种常见的列表实现。`LinkedList` 基于双向链表,适合频繁的插入和删除操作,但按索引访问元素效率较低。`ArrayList` 基于动态数组,支持快速随机访问,但在中间位置插入或删除元素时性能较差。两者均实现了 `List` 接口,`LinkedList` 还额外实现了 `Deque` 接口,提供了更多队列操作。
22 3
|
1月前
|
存储 算法 关系型数据库
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
18 0
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
|
27天前
|
存储
ES6中的Set数据结构的常用方法和使用场景
ES6中的Set数据结构的常用方法和使用场景
|
1月前
|
存储 算法 索引
HashMap底层数据结构及其增put删remove查get方法的代码实现原理
HashMap 是基于数组 + 链表 + 红黑树实现的高效键值对存储结构。默认初始容量为16,负载因子为0.75。当存储元素超过容量 * 负载因子时,会进行扩容。HashMap 使用哈希算法计算键的索引位置,通过链表或红黑树解决哈希冲突,确保高效存取。插入、获取和删除操作的时间复杂度接近 O(1)。
27 0
|
1月前
|
Java C++
【数据结构】探索红黑树的奥秘:自平衡原理图解及与二叉查找树的比较
本文深入解析红黑树的自平衡原理,介绍其五大原则,并通过图解和代码示例展示其内部机制。同时,对比红黑树与二叉查找树的性能差异,帮助读者更好地理解这两种数据结构的特点和应用场景。
25 0
|
1月前
探索顺序结构:栈的实现方式
探索顺序结构:栈的实现方式
|
12天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
85 9
|
3天前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
12 1

热门文章

最新文章