c++数据结构:树(概念二)树和森林

树:

树的存储结构如下:

1.双亲表示法

优点:容易找双亲

缺点:不易找孩子

2.孩子表示法

把每个节点的孩子列成节点存储成一个单链表,所以 n个节点就有n个链表;如果是叶子节点,那么这个孩子单链表为空,然后n个单链表的头指针又存储在一个顺序表中。

//孩子表示法
const int Max_size = 150;
class CTNode//孩子节点
{
public:
	int child;//孩子节点数组下表
	CTNode* next;//指向该节点的下一个节点
};
template<class T>
class CTBox
{
public:
	T data;//数据
	CTNode* fristchild;//孩子链表头指针
};
template<class T>
class CTree
{
public:
	CTBox<T> nodes[Max_size];//链表数组
	int n;//节点数
	int r;//根的位置
};

 3.孩子兄弟表示法

 又称为二叉树表示法,以二叉链表作为数的存储结构,链表中的两个链域分别指向该节点的第一个节点和下一个兄弟节点。

//孩子兄弟表示法
template<class T>
class CSTree
{
public:
	T data;
	CSTree<T>* fristchild;//第一个孩子节点
	CSTree<T>* nextsibling;//下一个兄弟节点
};

树与二叉树之间的转换:

树和二叉树的节点的结构是相似的,但指针的表示不同,所树和二叉树之间是可以相互转化的。

树转换成二叉树的转换规则:

  • 加线:在兄弟之间加线
  • 抹线:每个节点只留左孩子,出去与其他孩子的关系
  • 旋转:以树根为轴心顺时针旋转45° 

总结为:兄弟相连留长子

二叉树转换成树的规则:

  • 加线:若节点是双亲节点的左孩子,则将该节点的右孩子,右孩子的右孩子...,沿这条线的所有右孩子,都与该节点的双亲相连。
  • 抹线:抹掉原二叉树中双亲和右孩子之间的连线
  •  调整:将节点按层次排列

 森林与二叉树的转换:

森林转换成二叉树:

  • 将森林中的各棵树转换为二叉树
  • 将每棵树的根节点用线相连
  • 以第一颗树为数的根节点,再以根节点为轴心,顺时针旋转构成二叉树型结构

 二叉树转换为森林:

  • 抹线:将二叉树的根节点与其右孩子的连线,和沿着这条线方向的有右孩子方向的线抹除,使其称为独立的几个二叉树。
  • 还原:将二叉树换为树 

 树和森林的遍历:

树的遍历方法: 

  • 层次遍历:从上到下,从左到右访问。        
  • 先根遍历:先访问树的根节点,然后依次先根遍历的每棵子树。
    • (相当于在二叉树结构时的先序遍历)
  • 后根遍历:先依次访问后跟遍历每颗子树,然后访问根节点。
    • (相当于在二叉树结构时的中序遍历)

注意:树没有中根遍历,子树无左右之分。

 

 森林的遍历方法:

  • 先序遍历森林
    • 访问森林中第一棵树的根节点
    • 先序遍历第一棵树中的根节点的子树森林
    • 先序遍历除第一个树剩余的树构成的森林
  • 中序遍历森林
    • 中序遍历第一棵树中的根节点的子树森林
    • 访问森林中第一棵树的根节点
    • 中序遍历除第一个树剩余的树构成的森林

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.实验目的 (1)掌握森林孩子兄弟链表(叉链表)表示方法。 (2)掌握的结构及算法之间的对应关系。 (3)掌握的两种遍历算法及其应用。 2.实验任务 设计、实现算法求解下列问题: (1)按先序、后序、层次遍历森林。 实验测试数据基本要求: 第一组数据: tree11.tre 第组数据: f20.tre (2)求森林的高度。 实验测试数据基本要求: 第一组数据: tree11.tre 第组数据: f20.tre (3)求森林结点总数。 实验测试数据基本要求: 第一组数据: tree11.tre 第组数据: f20.tre (4)求森林叶子结点数。 实验测试数据基本要求: 第一组数据: tree11.tre 第组数据: f20.tre (5)求森林的度。 实验测试数据基本要求: 第一组数据: tree11.tre 第组数据: f20.tre (6)先序输出结点值及其层次号。 例对图7-1所示森林,输出为:(A,1) (B,2) (E,3) (K,4) (F,3) (G,3) (C,2) (H,3) (I,3) (D,2) (J,3) (L,1) (M,2) (N,2) (O,1) (P,2) 实验测试数据基本要求: 第一组数据: tree11.tre 第组数据: f20.tre (7)输出广义表表示的。 例对图7-1所示森林,输出为:A( B(E(K),F,G),C(H,I),D(J)), L(M,N), O(P) ) 实验测试数据基本要求: 第一组数据: tree11.tre 第组数据: f20.tre 3.实验说明 (以下给出的森林创建方法仅供参考,实验者可自行设计其它创建方法) (1)森林)的创建 本实验提供的创建代码,创建叉链表表示的森林)分为2个步骤,第一步:读取文本文件,创建双亲表示的森林);第部:从双亲表示转换为叉链表表示的森林)。 (2)森林)数据文件格式说明 数据文件主要包含三个部分:森林)标识;结点列表;父子结点对(边)。 ①标识行 Tree or Forest,以区别其它数据文件,这一行是非必须的。 ②结点列表 给出森林)中的所有结点,结点次序无关,只要列出所有结点即可。如图7-1所示的森林,结点列表可为: //下面为森林)的结点列表 A B C D E F G H I J K L M N O P。 ③父子结点对(边)信息 父子对信息严格按照父结点、子结点表示一对父子结点,父子对也次序无关,只要列出森林中所有父子对即可,例图7-1所示森林,所有父子对为: //以下为父子结点对(边)信息 A B A C A D B E B F B G C H C I D J E K L M L N O P (3)创建森林)包含文件说明 createTree.h,包括森林)的双亲存储、叉链表存储的定义;从文件创建双亲表示的森林);从双亲表示的森林创建叉链表表示的森林;其它辅助算法。
### 回答1: 将森林转换为的具体实现需要考虑输入森林数据结构数据结构的定义。以下是一种可能的实现方式,假设输入森林数据结构为一个数组,每个元素代表一棵的根节点,每个节点包含一个值和指向其子节点的指针数组。数据结构为一个节点结构体,每个节点包含一个值和指向其子节点和父节点的指针。 ``` // 定义节点结构体 typedef struct TreeNode { int val; struct TreeNode* parent; struct TreeNode** children; int numChildren; } TreeNode; // 将森林转换为的函数 TreeNode* forestToTree(TreeNode** forest, int numTrees) { if (numTrees == 0) { // 森林为空,返回空指针 return NULL; } else if (numTrees == 1) { // 森林只包含一棵,直接返回根节点 return forest[0]; } else { // 森林包含多棵,将它们合并为一棵 // 创建一个虚拟根节点 TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode)); root->val = -1; root->parent = NULL; root->numChildren = numTrees; root->children = (TreeNode**)malloc(numTrees * sizeof(TreeNode*)); // 将森林的根节点作为虚拟根节点的子节点 for (int i = 0; i < numTrees; i++) { root->children[i] = forest[i]; forest[i]->parent = root; } // 返回虚拟根节点 return root; } } ``` 注意这只是一种实现方式,具体实现可能因数据结构定义和需求而异。 ### 回答2: 首先,需要明确森林变成是指将不同森林组成的数据结构转换为这种数据结构。假设我们已经定义了森林数据结构数据结构,下面是一种可能的C语言代码实现: ```c #include <stdio.h> #include <stdlib.h> // 定义森林数据结构 typedef struct forest { int value; struct forest* next; // 指向同级的下一个 struct tree* children; // 指向当前的第一个子 } Forest; // 定义数据结构 typedef struct tree { int value; struct tree* next; // 指向同级的下一个 struct tree* children; // 指向当前的第一个子 } Tree; // 将森林变成的函数 Tree* forestToTree(Forest* forest) { if (forest == NULL) { return NULL; } Tree* tree = (Tree*) malloc(sizeof(Tree)); tree->value = forest->value; tree->next = NULL; tree->children = NULL; Forest* currentForest = forest->children; Tree* currentTree = tree; // 递归将森林中的每个子加入中 while (currentForest != NULL) { currentTree->next = forestToTree(currentForest); currentForest = currentForest->next; currentTree = currentTree->next; } return tree; } int main() { // 创建一个森林的示例 Forest* f1 = (Forest*) malloc(sizeof(Forest)); f1->value = 1; Forest* f2 = (Forest*) malloc(sizeof(Forest)); f2->value = 2; Forest* f3 = (Forest*) malloc(sizeof(Forest)); f3->value = 3; f1->next = f2; f2->next = f3; f3->next = NULL; f1->children = NULL; Forest* f4 = (Forest*) malloc(sizeof(Forest)); f4->value = 4; Forest* f5 = (Forest*) malloc(sizeof(Forest)); f5->value = 5; f4->next = f5; f5->next = NULL; f2->children = f4; f3->children = NULL; f4->children = NULL; f5->children = NULL; // 将森林转变成 Tree* t = forestToTree(f1); // 打印的结构 printf("转变后的的结构:\n"); Tree* currentTree = t; while (currentTree != NULL) { printf("%d ", currentTree->value); currentTree = currentTree->next; } return 0; } ``` 以上代码中,我们定义了森林数据结构`Forest`和数据结构`Tree`。然后,我们实现了`forestToTree`函数,该函数通过递归地将每个森林中的子添加到中,实现了将森林变成的功能。在`main`函数中,我们创建了一个森林的示例,并将其转换成,并打印出的结构。 说明:以上代码只是一种可能的实现方式,具体的实现方式还取决于森林的具体定义和需求。 ### 回答3: 以下是将森林转换成的一种实现方式的C语言代码: ```c #include <stdio.h> #include <stdlib.h> // 定义节点结构 typedef struct TreeNode { int value; struct TreeNode* left; struct TreeNode* right; } TreeNode; // 定义森林节点结构 typedef struct ForestNode { int value; struct ForestNode* next; TreeNode* tree; } ForestNode; // 森林的函数 TreeNode* convertForestToTree(ForestNode* forest) { TreeNode* root = NULL; TreeNode* current = NULL; while (forest != NULL) { if (forest->tree != NULL) { // 复制节点 TreeNode* temp = (TreeNode*)malloc(sizeof(TreeNode)); temp->value = forest->value; temp->left = temp->right = NULL; if (root == NULL) { root = current = temp; } else { current->right = temp; current = temp; } if (forest->tree->left != NULL) { current->left = forest->tree->left; forest->tree->left = NULL; } if (forest->tree->right != NULL) { current->right = forest->tree->right; forest->tree->right = NULL; } // 释放森林节点 ForestNode* tempForest = forest; forest = forest->next; free(tempForest->tree); free(tempForest); } else { // 移动到下一个森林节点 current = NULL; forest = forest->next; } } return root; } // 前序遍历的函数 void preOrderTraversal(TreeNode* root) { if (root == NULL) { return; } printf("%d ", root->value); preOrderTraversal(root->left); preOrderTraversal(root->right); } // 主函数 int main() { // 构建森林 ForestNode* forest = (ForestNode*)malloc(sizeof(ForestNode)); forest->value = 1; forest->next = (ForestNode*)malloc(sizeof(ForestNode)); forest->next->value = 2; forest->next->next = (ForestNode*)malloc(sizeof(ForestNode)); forest->next->next->value = 3; forest->next->next->next = NULL; // 构建 forest->tree = (TreeNode*)malloc(sizeof(TreeNode)); forest->tree->value = 4; forest->tree->left = (TreeNode*)malloc(sizeof(TreeNode)); forest->tree->left->value = 5; forest->tree->left->left = NULL; forest->tree->left->right = NULL; forest->tree->right = NULL; forest->next->tree = (TreeNode*)malloc(sizeof(TreeNode)); forest->next->tree->value = 6; forest->next->tree->left = NULL; forest->next->tree->right = NULL; forest->next->next->tree = (TreeNode*)malloc(sizeof(TreeNode)); forest->next->next->tree->value = 7; forest->next->next->tree->left = NULL; forest->next->next->tree->right = NULL; // 转换森林 TreeNode* tree = convertForestToTree(forest); // 前序遍历 printf("的前序遍历结果为:"); preOrderTraversal(tree); // 释放内存 free(tree); return 0; } ``` 以上代码通过定义了森林节点和节点的结构体,并实现了森林的函数convertForestToTree。主函数中构建了一个森林,并通过convertForestToTree函数将森林转换成,最后使用前序遍历函数preOrderTraversal打印出的遍历结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值