您的位置:首页 > 其它

九度OJ_1385:重建二叉树

2017-06-14 17:29 399 查看
题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的后序遍历序列。



输入:
输入可能包含多个测试样例,对于每个测试案例,

输入的第一行为一个整数n(1<=n<=1000):代表二叉树的节点个数。

输入的第二行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的前序遍历序列。

输入的第三行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的中序遍历序列。

输出:
对应每个测试案例,输出一行:

如果题目中所给的前序和中序遍历序列能构成一棵二叉树,则输出n个整数,代表二叉树的后序遍历序列,每个元素后面都有空格。

如果题目中所给的前序和中序遍历序列不能构成一棵二叉树,则输出”No

#include
#define MAX 1001

// 构建二叉树的结点
typedef struct Node
{
int data;            // 数据域
Node * lChild;       // 左子树
Node * rChild;       // 右子树
}BinaryTreeNode;
BinaryTreeNode biTreeNode[MAX];

bool canRebuildBinaryTree; // 判断能否重构二叉树
int preOrder[MAX];      // 二叉树的前序遍历序列
int inOrder[MAX];       // 二叉树的中序遍历序列

/**
* 初始化二叉树中的每个结点,将每个结点都看成是只有一个根结点而左右子树都为NULL的二叉树
* @param int n  二叉树的结点数
* @return void
*/
void initBinaryTree(int n)
{
int i;
canRebuildBinaryTree = true;
for(i = 0;i < n;i++)
{
biTreeNode[i].data = preOrder[i];  // 将前序遍历序列中的元素依次赋值给二叉树中的结点
biTreeNode[i].lChild = NULL;
biTreeNode[i].rChild = NULL;
}
}

/**
* 重构二叉树
* @param int beginPreOrder  前序遍历序列的起点
* @param int endPreOrder  前序遍历序列的终点
* @param int beginInOrder  中序遍历序列的起点
* @param int endInOrder  中序遍历序列的终点
* @return void
*/
void reBuildBinaryTree(int beginPreOrder,int endPreOrder,int beginInOrder,int endInOrder)
{
int i;
int partion = -1;     // 前序遍历序列第一个结点在中序遍历序列中的相对位置
bool isBeginPreOrderinInOrder = false; // 判断前序遍历序列中的第一个结点是否在中序遍历序列中,以此来判断是否能构成二叉树
// 遍历二叉树的中序遍历序列,得到根结点在中序遍历序列中的位置
for(i = beginInOrder;i <= endInOrder;i++)
{
if(preOrder[beginPreOrder] == inOrder[i])
{
partion = i - beginInOrder;
isBeginPreOrderinInOrder = true;
break;
}
}
if(false == isBeginPreOrderinInOrder)
{
canRebuildBinaryTree = false;
return;
}
else
{
// 以partion为分隔标识
// 将前序遍历序列分为[beginPreOrder + 1,beginPreOrder + partion]
// 和[beginPreOrder + partion + 1,endPreOrder]两个子序列
// 将中序遍历序列分为[beginInOrder,beginInOrder + partion - 1]
// 和[beginInOrder + partion + 1,endInOrder]两个子序列

// 用前序遍历子序列[beginPreOrder + 1,beginPreOrder + partion]
// 和中序遍历子序列[beginInOrder,beginInOrder + partion - 1]重构左子树
if(beginPreOrder + 1 <= beginPreOrder + partion && beginInOrder <= beginInOrder + partion - 1)
{
biTreeNode[beginPreOrder].lChild = &biTreeNode[beginPreOrder + 1];
reBuildBinaryTree(beginPreOrder + 1,beginPreOrder + partion,beginInOrder,beginInOrder + partion - 1);
}
// 用前序遍历子序列[beginPreOrder + partion + 1,endPreOrder]
// 和中序遍历子序列[beginInOrder + partion + 1,endInOrder]重构右子树
if(beginPreOrder + partion + 1 <= endPreOrder && beginInOrder + partion + 1 <= endInOrder)
{
biTreeNode[beginPreOrder].rChild = &biTreeNode[beginPreOrder + partion + 1];
reBuildBinaryTree(beginPreOrder + partion + 1,endPreOrder,beginInOrder + partion + 1,endInOrder);
}
}
}

/**
* 后序遍历二叉树
* @param BinaryTreeNode * root  后序遍历的根结点
* @return void
*/
void postOrder(BinaryTreeNode * root)
{
if(NULL == root)
return;
else
{
postOrder(root -> lChild);
postOrder(root -> rChild);
printf("%d ",root -> data);
}
}

int main()
{
int n;
int i;
while(EOF != scanf("%d",&n))
{
for(i = 0;i < n;i++)
{
scanf("%d",&preOrder[i]);
}
for(i = 0;i < n;i++)
{
scanf("%d",&inOrder[i]);
}
initBinaryTree(n);
reBuildBinaryTree(0,n - 1,0,n - 1);
if(false == canRebuildBinaryTree)
printf("No\n");
else
{
postOrder(&biTreeNode[0]); //因为 biTreeNode[0].data == preOrder[0],所以biTreeNode[0]是重构二叉树的根结点
printf("\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二叉树 遍历