九度OJ_1385:重建二叉树

来源:互联网 发布:clothcard淘宝有吗 编辑:程序博客网 时间:2024/05/29 18:11
题目描述:

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{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;  }  

原创粉丝点击