主题:
- 树和森林的双亲表示法,
- 树的左孩子右兄弟表示法
- 创建树的左孩子右兄弟二叉树
- 二叉树到树的双亲表示法的转换思路和算法
后续文章:
【数据结构】代码实现:左孩子右兄弟表示法转换为树的双亲表示法,左孩子右兄弟表示法转化为树的孩子兄弟链表表示法,树的双亲表示法转化为左孩子右兄弟的二叉树表示法
树和森林生成二叉树算法:
数据结构定义:
输入:
1
2
5
-1
6
-1
-1
3
-1
4
7
-1
8
-1
9
10
-1
-1
-1
-1
-1
函数代码:
Trees.h
#include <iostream>
#define MAX_SIZE 50
#include <stack>
#include <queue>
typedef struct ForestNode
{
int data;
struct ForestNode *lchild, *rbrother;
} ForestNode, *ForestHead;
/***
* 树的前序遍历建立森林
*/
ForestHead CreateForestHead(ForestHead fr, bool isRoot)
{
if (isRoot)
std::cout << "请输入第一棵树根节点,-1标识空:";
int data;
fr = (ForestNode *)malloc(sizeof(ForestNode));
std::cin >> data;
fr->lchild = NULL;
fr->rbrother = NULL;
fr->data = data;
if (data != -1)
{
bool isRoot = false;
std::cout << "请输入" << data << "的首个孩子:";
fr->lchild = CreateForestHead(fr->lchild, isRoot);
std::cout << "请输入" << data << "的相邻兄弟:";
fr->rbrother = CreateForestHead(fr->rbrother, isRoot);
}
return fr;
}
/***
* 双亲表示法
*/
typedef struct TreeNode
{
int valid = 0; //该节点是否存储了父节点信息,如果没有,那么只是跳转指针,存储的是兄弟信息
int parent = 0; //-1表示无父节点,其他表示指向的父节点
} TreeNode;
typedef struct Forest
{
TreeNode f[MAX_SIZE];
} Forest; //森林的数列定义
/***
* 将左孩子,右兄弟的存储方式的树,转化为双亲表示法
*/
void TransChildBrother2PrentArray(ForestHead fr, Forest *farray)
{
if (fr)
{
TransChildBrother2PrentArray(fr->lchild, farray);
if (fr->data != -1)
{
//std::cout << fr->data << "\t左孩子:" << fr->lchild->data << "\t右兄弟: " << fr->rbrother->data << std::endl;
if (fr->rbrother->data != -1) //有了兄弟,记录类型为指针,指向第一个兄弟,
{
farray->f[fr->rbrother->data].valid = 0;
farray->f[fr->rbrother->data].parent = fr->data;
}
if (fr->lchild->data != -1) //有了孩子,记录类型为真实值,孩子的parent置为父亲值
{
farray->f[fr->lchild->data].valid = 1;
farray->f[fr->lchild->data].parent = fr->data;
}
}
TransChildBrother2PrentArray(fr->rbrother, farray);
}
}
/***
* 把树链表转换为双亲表示法
*
* 如果树有左孩子,那么左孩子的父节点就是双亲节点
* 如果树有右孩子,那么说明树的父节点也是右孩子父节点
* 最好用中序遍历二叉树,这样会先遍历全部的孩子节点
*
* 中序遍历:5 6 2 3 7 8 10 9 4 1
*
*/
void GetParentArrayTreeList(ForestHead fr, Forest *farray, int nodeNum)
{
TransChildBrother2PrentArray(fr, farray); //将左孩子,右兄弟的存储方式的树,转化为双亲表示法
std::cout<<"将左孩子,右兄弟的存储方式的树,转化为双亲表示法:\n";
for (int i = 1; i <= nodeNum; i++)
{
if (farray->f[i].valid != 0 && farray->f[i].valid != 1) //进行迭代,如果是树的根节点,有效位和双亲标志-1
{
farray->f[i].valid = -1;
farray->f[i].parent = -1;
}
while (farray->f[i].valid == 0) //当有效位为0时,根据兄弟节点,去查找父亲节点值,直到找到为止。
{
if (farray->f[farray->f[i].parent].valid == 1)
farray->f[i].valid = 1;
farray->f[i].parent = farray->f[farray->f[i].parent].parent;
}
std::cout << "数据" << i << "指向:\t" << farray->f[i].parent << "\t是否指向父节点: " << farray->f[i].valid << std::endl;
}
}
调用代码
Trees_use.cpp
#include"Trees.h"
int main()
{
ForestHead tr = NULL;
tr = CreateForestHead(tr, true); // 根据左孩子,右节点的规则创建树;
Forest *farray = (Forest *)malloc(sizeof(Forest));
GetParentArrayTreeList(tr, farray,10);//转化上面的树为 孩子双亲表示法
}
左孩子右节点转化为孩子双亲表示法思路:
最后得到结果,符合树的结构: