树
多年前,还是一个对计算机懵懵懂的少年,学了一门犹如天书般的课程叫数据结构,课程里面每个知识点在当时来说是异常抽象。毕业后写了几年代码,再次学习一下数据结构中的一个重要概念--树。
思考:如何理解数据结构的概念?
数据结构是指相互之间存在一种或多种特定关系的数据元素集合在计算机中组织和存储的方式。我个人觉着也可以理解为数据结构是现实世界中关系实体在计算机世界中的一种抽象描述。
- 结点的度:子结点的个数。上图中node1有3个子结点,故其度为3。
- 树的度:树的度等于所有结点度最高的值。结点最高的度为3,树的度为3。
- 叶子结点:度为0的结点,即没有子结点的结点。上图中node4,node5,node6,node7为叶子结点。
树的存储
“树”这种数据结构是我们用计算机对现实世界中关系实体的抽象描述,那么这种描述在计算机内存中的存储需要进一步转换为内存可以解析的结构。计算机内存中可以解析的“存储结构”有两种,顺序表(连续存储空间)和链表(非连续存储空间)。
1 双亲表示法(顺序存储结构)
顺序存储用一组连续的内存空间来存储树的结点,同时在每个结点中附加一个标识(整数类型),用于指示双亲结点的位置(下标值),如下图所示。
// JavaScript
[
{value: 'node1', parent: -1},
{value: 'node2', parent: 0},
{value: 'node3', parent: 0},
{value: 'node4', parent: 0},
{value: 'node5', parent: 1},
{value: 'node6', parent: 2},
{value: 'node7', parent: 2},
]
复制代码
2 孩子链表表示法(链式存储结构)
链式存储用非连续的内存空间来存储树的结点,孩子链表表示存储可以很方便的找到每个结点的子结点及其兄弟结点,如下图所示。如果带上双亲域(即与双亲表示法结合),还可以很方便的找出其双亲结点。
[
{
value: 'node1',
child: {
index: 1,
siblings: {
index: 2,
siblings: {
index: 3,
siblings: null
}
}
}
},
{
value: 'node2',
child: {
index: 4,
siblings: null
}
},
{
value: 'node3',
child: {
index: 5,
siblings: {
index: 6,
siblings: null
}
}
},
{value: 'node4', child: null},
{value: 'node5', child: null},
{value: 'node6', child: null},
{value: 'node7', child: null},
]
复制代码
3 孩子兄弟表示法(链式存储结构)
孩子兄弟存储结构每个结点有两个指针,分别指向其左右孩子结点,比较适用于二叉树(结点的度小于3的树)。孩子兄弟存储结构可以很方便的找到每个结点的子结点,如下图所示。
{
value: 'node1',
left: {
value: 'node2',
left: {
value: 'node4',
left: null,
right: null
}
right: {
value: 'node5',
left: null,
right: null
}
},
right: {
value: 'node3',
left: {
value: 'node6',
left: null,
right: null
}
}
}
复制代码
用计算机来解决现实社会中的问题,需要把现实世界中的实体关系模拟到计算机世界中,那么这个时候就会产生数据结构,这是“数据结构”最终需要映射到内存中,所以需要进一步用计算机可以解析的程序来进行描述。
树的遍历
树的遍历是指依照一定的规律不反复的访问树中的每个结点,其遍历过程实质上是将树这样的非线性结构按一定规律转化为线性结构,遍历方式一般有先序和后续两种(二叉树有三种)。
后根次序遍历:先访问子结点,后访问根结点,上树遍历结果为whdexafbsmonijtucR
本篇文章是作者参考了一些文献之后加上个人理解对数据结构中的“树”做出的部分总结,如果有解释不正确的地方,希望读者在评论区果断提出来,我们一起共同进步。