树算法习题:
1.树的前序遍历建立树,访问顺序相当于二叉树的中序遍历
BroTreeHead CreateForestHead(BroTreeHead fr, bool isRoot)
2.求孩子兄弟表示法存储的森林的叶子节点数目
int GetTreeLeafNum(BroTreeHead tr)
3. 前序访问树节点
void VisitForestHead(BroTreeHead tr)
4.递归方法求孩子兄弟表示法存储的森林的叶子节点数目
int GetTreeLeafNumCircle(BroTreeHead tr)
5.建立孩子链表
RootArray *CreateRootArray()
6.访问孩子链表表示法的节点,打印
void VisitByChildTree(RootArray *rt)
7.孩子链表为存储结构,设计递归算法求解树的深度
int GetChildLinkDepth(RootArray *rtArray)
8.以孩子兄弟链表为存储结构,求解树的深度
int GetChildBrotherDepth(BroTreeHead tr)
9.已知一颗树的层次序列及每个节点的度, 编写算法构造这个树的孩子兄弟链表
BroTreeHead GetRootArray2(int levelOrder[], int degree[], int length)
函数调用:
Tree_use.cpp
#include "Tree.h"
int main()
{
BroTreeHead tr = CreateForestHead(tr, true);
std::cout << "(非递归)孩子兄弟表示法存储的森林的叶子节点数目: " << GetTreeLeafNum(tr) << std::endl;
std::cout << "(递归)孩子兄弟表示法存储的森林的叶子节点数目: " << GetTreeLeafNumCircle(tr) << std::endl;
VisitForestHead(tr);
RootArray* rtArray = CreateRootArray();
VisitByChildTree(rtArray);
std::cout << "以孩子链表为存储结构,树的深度: " << GetChildLinkDepth(rtArray) << std::endl;
std::cout << "\n以孩子兄弟为存储结构,树的深度: " << GetChildBrotherDepth(tr) << std::endl;
int length = 9;
int levelOrder[length] = {3, 2, 1, 5, 4, 6, 8, 7, 9};
int degree[length] = {3, 2, 0, 1, 1, 0, 1, 0, 0};
BroTreeHead btr = GetRootArray2(levelOrder, degree, length);
VisitForestHead(btr);
}
函数定义
Tree.h
#include <iostream>
#define MAX_SIZE 50
#include <stack>
#include <queue>
#include <string.h>
typedef struct BroTreeNode
{
int data;
struct BroTreeNode *lchild, *rbrother;
} BroTreeNode, *BroTreeHead;
/***
* 树的前序遍历建立树,可见访问顺序相当于二叉树的中序遍历
*/
BroTreeHead CreateForestHead(BroTreeHead fr, bool isRoot)
{
if (isRoot)
std::cout << "请输入第一棵树根节点,-1标识空:";
int data;
std::cin >> data;
if (data != -1)
{
fr = (BroTreeNode *)malloc(sizeof(BroTreeNode));
fr->lchild = NULL;
fr->rbrother = NULL;
fr->data = data;
bool isRoot = false;
std::cout << "请输入" << data << "的首个孩子:";
fr->lchild = CreateForestHead(fr->lchild, isRoot);
std::cout << "请输入" << data << "的相邻兄弟:";
fr->rbrother = CreateForestHead(fr->rbrother, isRoot);
}
else
{
fr = NULL;
}
return fr;
}
/**
* 求孩子兄弟表示法存储的森林的叶子节点数目
*/
int GetTreeLeafNum(BroTreeHead tr)
{
static int leafNum = 0;
if (tr)
{
GetTreeLeafNum(tr->lchild);
if (tr->lchild == NULL)
{
//std::cout << tr->data << std::endl;
leafNum += 1;
}
GetTreeLeafNum(tr->rbrother);
return leafNum;
}
}
/***
* 前序访问树节点
*/
void VisitForestHead(BroTreeHead tr)
{
if (tr)
{
std::cout << tr->data << " ";
VisitForestHead(tr->lchild);
VisitForestHead(tr->rbrother);
}
}
/***
* 递归方法求孩子兄弟表示法存储的森林的叶子节点数目
*/
int GetTreeLeafNumCircle(BroTreeHead tr)
{
if (tr)
{
if (tr->lchild == NULL)
return 1 + GetTreeLeafNumCircle(tr->rbrother);
else
return GetTreeLeafNumCircle(tr->lchild) + GetTreeLeafNumCircle(tr->rbrother);
}
return 0;
}
typedef struct ChildNode
{
int data;
struct ChildNode *nextChild;
} ChildNode;
typedef struct RootArray
{
ChildNode root[MAX_SIZE];
int length;
} RootArray;
/***
* 建立孩子链表
*/
RootArray *CreateRootArray()
{
int root = -1;
int child = -1;
int index = 0;
std::cout << "开始建立孩子兄弟链表,请输入根节点值:" << std::endl;
std::cin >> root;
RootArray *rtArray = (RootArray *)malloc(sizeof(RootArray));
while (root != -1)
{
index += 1;
rtArray->root[index].data = root;
rtArray->root[index].nextChild = NULL;
int i = 1;
std::cout << "请输入第" << i << "个孩子的节点值:" << std::endl;
std::cin >> child;
while (child != -1)
{
ChildNode *p = (ChildNode *)malloc(sizeof(ChildNode));
p->nextChild = rtArray->root[index].nextChild;
rtArray->root[index].nextChild = p;
p->data = child;
i += 1;
std::cout << "请输入第" << i << "个孩子的节点值:" << std::endl;
std::cin >> child;
}
std::cout << "请输入根节点值:" << std::endl;
std::cin >> root;
}
rtArray->length = index;
return rtArray;
}
/**
* 访问孩子链表表示法的节点,打印
*/
void VisitByChildTree(RootArray *rt)
{
std::cout << "\n访问孩子链表表示法的节点:";
for (int i = 1; i <= rt->length; i++)
{
ChildNode *p = rt->root[i].nextChild;
std::cout << std::endl;
std::cout << i << "-|";
while (p != NULL)
{
std::cout << "-> " << p->data;
p = p->nextChild;
}
}
std::cout << std::endl;
}
/***
* 孩子链表为存储结构,
* 设计递归算法求解树的深度
*/
int GetChildLinkDepthCircle(ChildNode *childNode)
{
if (childNode)
return GetChildLinkDepthCircle(childNode->nextChild) + 1;
return 0;
}
int GetChildLinkDepth(RootArray *rtArray)
{
int maxDepth = 0;
for (int i = 1; i < rtArray->length; i++)
{
int depth = 1 + GetChildLinkDepthCircle(rtArray->root[i].nextChild);
maxDepth = depth < maxDepth ? maxDepth : depth; //递归求解深度
}
return maxDepth;
}
/***
* 以孩子兄弟链表为存储结构,
* 求解树的深度
*/
int GetChildBrotherDepth(BroTreeHead tr)
{
if (tr)
{
int d1 = GetChildBrotherDepth(tr->lchild) + 1;
int d2 = GetChildBrotherDepth(tr->rbrother);
return d2 > d1 ? d2 : d1;
}
return 0;
}
/***
* 已知一颗树的层次序列及每个节点的度,
* 编写算法构造这个树的孩子兄弟链表
*
* 思路:类似于孩子表示法转为孩子兄弟链表
* 第一层是根,下一层的首个节点是根的孩子,
* 由于已知道每个节点的度,所以可以得到每个节点的孩子排列和孩子数目
*/
BroTreeHead GetRootArray2(int levelOrder[], int degree[], int length)
{
BroTreeNode *p = new BroTreeNode[length];
for (int i = 0; i < length; i++)
{
p[i].data = levelOrder[i];
p[i].lchild = p[i].rbrother = NULL;
}
int d;
int nodeId = 0;
for (int i = 0; i < length; i++)
{
d = degree[i]; //度为d
if (d) //有孩子
{
nodeId++;
p[i].lchild = &p[nodeId];
for (int j = 2; j <= d; j++) //绑定好全部的兄弟节点
{
nodeId++;
p[nodeId - 1].rbrother = &p[nodeId];
}
} //否则无孩子
}
return &p[0];
}
输入例子:
左孩子右兄弟链表的创建:
1
2
5
-1
6
-1
-1
3
-1
4
7
-1
8
-1
9
10
-1
-1
-1
-1
-1
和 孩子兄弟链表的创建:
3
2
1
5
-1
2
4
6
-1
1
-1
5
8
-1
4
7
-1
6
-1
8
9
-1
9
-1
-1
输出: