主要内容 #
- 什么是父亲表示法
- 父亲表示法的优缺点
- 如何表示一棵树
1. 什么是父亲表示法 #
C++ 中的树的父亲表示法(Parent Representation)又称为双亲表示法,是一种使用数组来表示树的数据结构,其中数组的下标表示节点的编号,数组的元素表示该节点的父节点编号。
注意,根节点没有父节点(父节点又称为双亲节点),因此根节点记录父节点位置的变量通常置为 -1。
例如,采用双亲表示法存储下图的普通树:

上图存储普通树的过程转化为 C 语言代码为:
#define MAX_SIZE 100//宏定义树中结点的最大数量
typedef char ElemType;//宏定义树结构中数据类型
typedef struct Snode{
TElemType data;//树中结点的数据类型
int parent;//结点的父结点在数组中的位置下标
}PTNode;
typedef struct {
PTNode tnode[MAX_SIZE];//存放树中所有结点
int n;//根的位置下标和结点数
}PTree;
2. 父亲表示法的优缺点 #
使用父亲表示法可以有效地节省存储空间,同时还能够支持一些特殊的树算法,如 LCA(最近公共祖先)等。但是需要注意,使用父亲表示法表示一棵树时,不支持快速查找某个节点的子节点,需要进行线性遍历。
但是,使用父亲表示法存储一棵树也存在一些缺点,例如:
1. 插入、删除节点时需要更新父节点指针,而且需要保证更新完毕之后整棵树依然合法,否则会导致程序出错。
2. 在进行节点查找时,需要从根节点开始遍历整棵树才能找到目标节点,这样的时间复杂度是 $O(n)$ 的。
3. 父亲表示法并不支持高效的树的重构操作。当需要重构一棵树时,需要重新构建整棵树,而无法利用已有的部分信息来高效地进行重构。
因此,在实际应用中,应根据具体的需求来选择合适的树的表示方法。当需要高效地进行节点查找或树的重构操作时,可能需要使用其他的树的表示方法,如孩子表示法、邻接表等。
另外,需要注意的是,父亲表示法有一些限制和约束条件,如:
1. 父节点编号必须唯一。即每个节点的父节点编号不能相同,否则无法正确地表示树的结构。
2. 根节点的父节点编号必须为一个特定值。根节点没有父节点,因此需要为其指定一个特殊的父节点编号,通常为 $-1$ 或 $0$ 等。
3. 节点的编号必须连续。如果使用数组来存储节点信息,则节点的编号必须从 $1$ 开始连续编号,否则无法正确地使用数组来访问节点信息。
4. 树的深度不能太大。由于父亲表示法需要存储每个节点的父节点编号,因此树的深度不能太大,否则会占用过多的存储空间,导致程序出错。
3. 如何表示一棵树 #
存储上图中普通树的 C 语言实现代码为:
#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 20
typedef char ElemType;//宏定义树结构中数据类型
typedef struct Snode //结点结构
{
ElemType data;
int parent;
}PNode;
typedef struct //树结构
{
PNode tnode[MAX_SIZE];
int n; //结点个数
}PTree;
PTree InitPNode(PTree tree)
{
int i, j;
char ch;
printf("请输出节点个数:\n");
scanf("%d", &(tree.n));
printf("请输入结点的值其双亲位于数组中的位置下标:\n");
for (i = 0; i < tree.n; i++)
{
getchar();
scanf("%c %d", &ch, &j);
tree.tnode[i].data = ch;
tree.tnode[i].parent = j;
}
return tree;
}
void FindParent(PTree tree)
{
char a;
int isfind = 0;
printf("请输入要查询的结点值:\n");
getchar();
scanf("%c", &a);
for (int i = 0; i < tree.n; i++) {
if (tree.tnode[i].data == a) {
isfind = 1;
int ad = tree.tnode[i].parent;
printf("%c的父节点为 %c,存储位置下标为 %d", a, tree.tnode[ad].data, ad);
break;
}
}
if (isfind == 0) {
printf("树中无此节点");
}
}
int main()
{
PTree tree;
for (int i = 0; i < MAX_SIZE; i++) {
tree.tnode[i].data = " ";
tree.tnode[i].parent = 0;
}
tree = InitPNode(tree);
FindParent(tree);
return 0;
}
程序运行示例:
请输出节点个数: 10 请输入结点的值其双亲位于数组中的位置下标: R -1 A 0 B 0 C 0 D 1 E 1 F 3 G 6 H 6 K 6 请输入要查询的结点值: C C的父节点为 R,存储位置下标为 0