树和森林
6.7 树和森林的实现
6.7.1 树的存储结构
1.双亲表示法
- 由树的定义可以知道,在树中除根结点外的每个结点都有唯一的一个双亲结点,因此,可以考虑用一组连续的存储空间存储树中的每一个结点,数组中的一个元素表示为树中的一个结点。在数组元素中除包括结点本身的数据信息外,还保存该结点的双亲结点在数组中的序号(根结点的双亲域赋予-1)树的这种存储方法称为双亲表示法。
- 每一个数组元素有两个域:data 和 parent, data域存储结点的数据信息;parent 域存储结点的双亲在数组中的序号。
typedef struct Node{
char data;
int parent;
}PTNode;
typedef struct{
PTNode nodes[100];
int n;
}PTree;
3. 树的双亲表示法【优点】对于实现求双亲操作很方便,时间复杂度为O(1),但【缺点】①对于求某结点的孩子结点的操作,则需要询整个数组。②另外,这种存储方式不能直接反映各兄弟结点之间的关系,所以实现求兄弟的操作也比较困难(若要找结点的孩子或者兄弟,要遍历整个树)。
4. 实际上,如果需要实现这些操作,只需将上述存储结构稍加改进:给每个数组元素增加两个域,一个域存储该数组元素所表示的结点的第一个孩子结点在数组中的序号,另一个域存储该结点的右兄弟结点在数组中的序号。在这种改进的存储结构下,就能够较方便地实现树的各种基本操作。
(1)改进一:方便获取孩子结点
/*树的双亲表示法结点结构定义*/
#define MAX_TREE_SIZE 100
typedef int TElemType;
typedef struct PTNode //结点结构
{
TElemType data; //结点数据
int parent; //双亲位置
int child1; //孩子结点1
int child2; //孩子结点2
int child3; //孩子结点3
}PTNode;
typedef struct //树结构
{
PTNode nodes[MAX_TREE_SIZE]; //结点数组
int r, n; //r是根位置,n是结点数
}PTree;
- 【缺点】消耗了大量的空间,是不必要的
- 我们尽可能使用较小的空间,所以我们一般只添加一个长子域(最左边孩子的域),可以获取到有0个或1个孩子结点,甚至两个子树都可以获取,但是对于较多的孩子我们若是非得使用顺序存储,就得使用上面方法。
/*树的双亲表示法结点结构定义*/
#def