什么是树的孩子表示法?
树的孩子表示法(Child-Sibling Representation),也称为左孩子右兄弟表示法(Left-Child Right-Sibling Representation),是一种用于表示树结构的常见方法。在这种表示法中,每个节点包含两个指针,分别指向其第一个孩子节点和其兄弟节点。这样的表示方法适合描述不同的树结构,如二叉树和多叉树等。
具体地,对于一个节点而言,其第一个孩子节点可以通过其左指针找到,而其兄弟节点可以通过其右指针找到。如果一个节点没有孩子节点,那么其左指针指向空,如果一个节点没有兄弟节点,那么其右指针指向空。
树的孩子表示法可以有效地描述树的结构,尤其是在需要进行树的遍历和搜索等操作时,具有一定的优势。
#include <iostream>
#include <vector>
using namespace std;
// 树节点的结构体定义
struct TreeNode {
int val;
TreeNode* firstChild; // 指向第一个孩子节点
TreeNode* nextSibling; // 指向兄弟节点
TreeNode(int x) : val(x), firstChild(NULL), nextSibling(NULL) {}
};
// 建立一棵树
TreeNode* buildTree() {
int n, val;
cout << "请输入节点个数: ";
cin >> n;
vector<TreeNode*> nodes(n); // 存放每个节点的指针
cout << "请依次输入每个节点的值: ";
for (int i = 0; i < n; i++) {
cin >> val;
nodes[i] = new TreeNode(val);
}
int rootIndex, parentIndex, childIndex;
cout << "请依次输入每个节点的父节点编号(根节点编号为 0): ";
for (int i = 1; i < n; i++) {
cin >> parentIndex;
childIndex = i;
// 将当前节点作为其父节点的孩子节点或兄弟节点
if (nodes[parentIndex]->firstChild == NULL) {
nodes[parentIndex]->firstChild = nodes[childIndex];
} else {
TreeNode* sibling = nodes[parentIndex]->firstChild;
while (sibling->nextSibling != NULL) {
sibling = sibling->nextSibling;
}
sibling->nextSibling = nodes[childIndex];
}
}
return nodes[0]; // 返回根节点指针
}
// 先序遍历输出树
void preorderTraversal(TreeNode* root) {
if (root == NULL) {
return;
}
cout << root->val << " ";
preorderTraversal(root->firstChild);
preorderTraversal(root->nextSibling);
}
int main() {
TreeNode* root = buildTree();
cout << "先序遍历输出树的节点值: ";
preorderTraversal(root);
return 0;
}在上面的示例中,我们首先定义了一个树节点的结构体,其中包含了节点的值 val、指向第一个孩子节点的指针 firstChild 和指向兄弟节点的指针 nextSibling。
接下来,我们定义了一个 buildTree() 函数,用于通过输入建立一棵树。在该函数中,我们首先输入节点个数和每个节点的值,并存放到一个 vector 中。然后,我们逐个输入每个节点的父节点编号,并将当前节点作为其父节点的孩子节点或兄弟节点。最后,我们返回根节点的指针。
最后,我们定义了一个 preorderTraversal() 函数,用于先序遍历输出树的节点值。在该函数中,我们首先输出当前节点的值,然后递归遍历其第一个孩子节点和兄弟节点。
代码2:
#include <iostream>
using namespace std;
// 树节点的结构体定义
struct TreeNode {
int val;
TreeNode* firstChild; // 指向第一个孩子节点
TreeNode* nextSibling; // 指向兄弟节点
TreeNode(int x) : val(x), firstChild(NULL), nextSibling(NULL) {}
};
// 树节点的个数
const int MAX_N = 100;
// 存放每个节点的指针
TreeNode* nodes[MAX_N];
// 当前节点编号
int nodeIndex = 0;
// 建立一棵树
TreeNode* buildTree() {
int n, val, parentIndex, childIndex;
cout << "请输入节点个数: ";
cin >> n;
cout << "请依次输入每个节点的值: ";
for (int i = 0; i < n; i++) {
cin >> val;
nodes[i] = new TreeNode(val);
}
cout << "请依次输入每个节点的父节点编号(根节点编号为 0): ";
for (int i = 1; i < n; i++) {
cin >> parentIndex;
childIndex = i;
// 将当前节点作为其父节点的孩子节点或兄弟节点
if (nodes[parentIndex]->firstChild == NULL) {
nodes[parentIndex]->firstChild = nodes[childIndex];
} else {
TreeNode* sibling = nodes[parentIndex]->firstChild;
while (sibling->nextSibling != NULL) {
sibling = sibling->nextSibling;
}
sibling->nextSibling = nodes[childIndex];
}
}
return nodes[0]; // 返回根节点指针
}
// 先序遍历输出树
void preorderTraversal(TreeNode* root) {
if (root == NULL) {
return;
}
cout << root->val << " ";
preorderTraversal(root->firstChild);
preorderTraversal(root->nextSibling);
}
int main() {
TreeNode* root = buildTree();
cout << "先序遍历输出树的节点值: ";
preorderTraversal(root);
return 0;
}在这个示例代码中,我们使用一个 nodes 数组来存放每个节点的指针,其大小为常量 MAX_N。在建立树时,我们先输入节点个数和每个节点的值,并将其存放到 nodes 数组中。然后,我们逐个输入每个节点的父节点编号,并将当前节点作为其父节点的孩子节点或兄弟节点。最后,我们返回根节点的指针。
在 preorderTraversal() 函数中,我们同样使用了递归的方式进行先序遍历,并输出当前节点的值、其第一个孩子节点和兄弟节点的值。

