本文概述:
- 本文主要介绍了树这种数据结构做了基本介绍,只涉及了树的基本名词和存储方式;
- 重点是树的存储方式,其本质还是链式和顺序存储结构而已;
- 图片、代码结合,旨在理解树的真正存储的思想。
树的基本名词
- 树的定义(特征):
- 每个节点都只有有限个子节点或无子节点;
- 没有父节点的节点称为根节点;
- 每一个非根节点有且只有一个父节点;
- 除了根节点外,每个子节点可以分为多个不相交的子树;
- 树里面没有环路(cycle)
- 结点的度:结点拥有的子女的个数。
- 叶子(leaf):没有儿子的结点。
- 分支结点:有儿子的结点。
- 树的度:树中的某个结点有最大的子女个数。
- 层次:根结点的层次为1,其余结点的层次等于该结点的双亲结点的层次加1。
- 树的高度(height):为该节点到一片树叶的最长路径的长;
- 某节点的深度(depth):为从根到该节点的唯一路径长;
- 无序树:如果树中结点的各子树之间的次序是不重要的,可以交换位置。
- 有序树:如果树中结点的各子树之间的次序是重要的, 不可以交换位置。
- 森林:0个或多个不相交的树组成。对森林加上一个根,森林即成为树;删去根,树即成为森林。
- 这个路径的长(length)为该路径上的边的条数;
- 具有相同父亲的节点互称为兄弟(sibling);
树的表示法
树通常有四种表示法:树形表示法、嵌套集合表示法、凹入表表示法、广义表表示法;
而我们常用的是树型表示法。
注:本图来自《大话数据结构》,下文中也有部分图来自该书。
树的存储结构
- 对于上文中的树型表示法,我们得像个办法把它保存下来(放在内存或磁盘中)。然而如何将它的那种树形的结构保存下来,在下次读取时能够恢复成这种结构呢?这,就是存储结构。
- 存储结构研究的就是:如何将树的这种逻辑物,更好地存储在线性的内存空间中,依然使得其拥有它原来的树形结构。
- 就像在线性表中,对于一个有限序列(1,2,3,……),我们把它放在了顺序表(即数组)和链表中一样,树的存储结构也有这类似的两种保存方式。
双亲存储法
- 本质:用一个结构体数组保存当前的具体数据和双亲的位置;
#define MAXSIZE 10 //树的节点个数;
typedef struct node
{
char data; //该节点的具体值;
int parent; //该节点的父节点的数组下标值;
}node;
typedef struct tree
{
node TreeArray[MAXSIZE]; //存放各个节点的数组;
int NodeNumber,root;//NodeNumber表示本树的所有节点的个数;root表示根节点的位置(一般为-1);
}tree;
//tree.TreeArray[0]=A,-1
数组方式孩子存储法
#define N 3 //表示每个节点所拥有得最大子女数是3个;即一个节点,只允许有最多3个小孩;
#define MAXSIZE 10 //表示本树的能存储最多10个节点;
typedef struct node
{
char data;
int child[N]; //child保存的是此data节点下的孩子的下标;
}node; //node是本结构体的新别名;
node tree[MAXSIZE]; //存储树的节点;
int root; //根节点的下标;
int NodeNumber; //树的所有节点的个数;
指针方式孩子存储法
因为每个节点所含子女数不同,因此child数组的大小是由N来决定的;由此造成了很多空间浪费;而树的链表方式孩子存储法解决了这个问题;
#define N 3 //表示每个节点所拥有得最大子女数是3个;即一个节点,只允许有最多3个小孩;
typedef struct node
{
char data;
struct node *child[N];
}node, *tree; //node是本结构体的新别名;tree是结构体指针;
tree root; //结构体指针tree指向root;
链表方式孩子存储法
#define MAXSIZE 10
typedef struct ChildNode //存储一个节点的在数组中的位置和下一个节点的地址;
{
int child;
struct ChildNode *NextChild;
}ChildNode, *ChildNodePoint;
typedef struct node
{
char data;
ChildNodePoint FirstChild;
}node;
typedef struct tree
{
node TreeAyyary[MAXSIZE];
int NodeNumber, root; //NodeNumber表示本个树总共含多少个节点,root表示根节点的位置;
}tree;
孩子兄弟存储法
typedef struct node
{
char data;
struct node *FirstChild, *RightChild; //分别指向该节点的第一个子女和其右兄弟;
}node, *NodePoint;
NodePoint root; //声明结构体指针变量,同时也让节点指针指向root;