数据结构其他章节
一,树的性质与概念
一,节点与度
首先,我们需要了解树相关的两个重要概念——节点与度
节点是指其实就是指的是树的关节,其中树的第一个节点叫做根节点
度则是衡量节点分支多寡的一个概念,若一个节点无分支,则这个节点的度为零。
以下是有关节点和度的相关概念:
二,树的概念
——有一个特殊的结点,称为根结点,根节点没有前驱结点
——除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i <= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
因此,树是递归定义的。
二,树的储存方式
方法一:已知树的度,直接定义
typedef int DataType;
struct TreeNode {
DataType* a;
struct TreeNode* child1;//储存第一个孩子的地址
struct TreeNode* child2;//储存第二个孩子的地址
//.....
};
如果按以上方式去定义一个树的结构体,那肯定只能是在已知树的度的前提下我们才能这样做;这样做显然局限性很大,那么如果不知道树的度,该如何去定义树的结构体呢?
方法二:利用顺序表结构定义
答案就是利用顺序表储存,实现方式如下:
typedef int DataType;
struct TreeNode {
DataType* a;
struct TreeNode** childarr;//一个结构体指针数组,用来存储子节点的地址
int size;
int capacity;
};
在结构体内添加一个类似顺序表的结构,这样便能表示树了。但是上面这种实现方式任然存在一些问题:结构体指针childarr的初始容量该定义为多大?按怎样的方式进行扩容?等等。这些问题虽然可以解决,但是几乎不可避免的会导致内存空间的浪费,所以还有没有更加简约有效的实现方式?
方法三:左孩子右兄弟表示法
有!左孩子右兄弟表示法(之后实现二叉树使用的是左孩子右孩子表示法,切勿混淆)
typedef int DataType;
struct TreeNode {
DataType* a;
struct TreeNode* Firstchild;//第一个孩子的地址
struct TreeNode* Nextbrother;//下一个兄弟的地址
};
像这样,一个指针指向节点的第一个孩子节点的地址,一个指针指向其最近的兄弟节点的地址,就能完整的表示出树的结构。这里需要注意的是,树这一数据结构本身是没有顺序的,但是在这样的结构体定义下,同一父亲节点的子节点就有了先后顺序。
方法四:双亲表示法
typedef int DataType;
struct TreeNode {
DataType* a;
int parent;//存储父亲节点的下标
};
上图使用双亲表示法实现可获得如下表格:
节点对应下标 | 节点 | 节点对应父亲节点下标 |
1 | A | 0 |
2 | B | 1 |
2 | C | 1 |
3 | E | 2 |
3 | F | 2 |
3 | G | 2 |
以上便是描述树这一结构的四种实现方式,接下来让我们看一看树这一结构在生活中有什么具体的应用吧!
三,树结构的应用
Linux文件管理系统
如图,是linux文件管理系统的示意图,使用的正是我们刚刚学习的树结构。不过在Windows系统中,文件管理系统则是森林结构(由多颗树组成),你可以点开你的文件资源管理器看看我说的对不对噢!
四,全文总结
本文介绍了树的相关概念和储存方式,其中不同节点之间的关系是重中之重,切勿混淆;树的四种不同的储存方式中,左孩子右兄弟表示法是最为常用的一种方法,需要牢记;
下期预告
如图,这是一棵树,但它的结构却完美满足我们下一期将要学习的满二叉树的结构(下一期内容预告:二叉树与堆)