剑指offer--据前序和中序遍历重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
分析:此时不由得想起前序遍历的顺序是根--左--右

 

[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. #include<stdio.h>    
  2. #include<stdlib.h>    
  3. #include<iostream>    
  4. using namespace std;    
  5. struct BTreeNode    
  6. {    
  7.     int _value;    
  8.     BTreeNode*_left;    
  9.     BTreeNode*_right;    
  10. };    
  11.     
  12. //解法一    
  13. BTreeNode* RebuildCode(int * PreStart,int *PreEnd,int *InStart,int *InEnd);    
  14. BTreeNode* RebuildTree(int *PreOrder,int *InOrder,int len)    
  15. {    
  16.     //首先判断边界条件    
  17.     if(PreOrder == NULL || InOrder == NULL ||len <= 0)    
  18.     {    
  19.         return NULL;    
  20.     }    
  21.     else    
  22.     {    
  23.         return RebuildCode(PreOrder,PreOrder+len-1,InOrder,InOrder+len-1);    
  24.     }    
  25. }    
  26. BTreeNode* RebuildCode(int * PreStart,int *PreEnd,int *InStart,int *InEnd)    
  27. {    
  28.     BTreeNode *root = new BTreeNode();    
  29.     //新建节点root保存前序第一个节点为根结点    
  30.     root->_value = PreStart[0];    
  31.     root-> _left = NULL;    
  32.     root->_right  = NULL;    
  33.     if(InStart == InEnd && *InStart == *InEnd)    
  34.     {    
  35.         return root;    
  36.     }    
  37.     //据此节点找到中序遍历此节点的位置    
  38.     int *rootIn = InStart;    
  39.     while(*PreStart != *rootIn)    
  40.     {    
  41.         rootIn++;    
  42.     }    
  43.     //左子树的长度    
  44.     int leftlen = rootIn-InStart;    
  45.     //重建左子树    
  46.     if(leftlen > 0)    
  47.     {    
  48.         root->_left = RebuildCode( PreStart+1,PreStart+leftlen,InStart,InStart+leftlen-1);    
  49.         
  50.         
  51.     }    
  52.     //重建右子树    
  53.     if(InStart+leftlen < InEnd)    
  54.     {    
  55.         root->_right = RebuildCode( PreStart+leftlen+1,PreEnd,InStart+leftlen+1,InEnd);    
  56.             
  57.     }    
  58.     return root;    
  59. }    
  60. //后序遍历输出二叉树序列    
  61. void PostOrder(BTreeNode *root)    
  62. {    
  63.     if(root->_left != NULL)    
  64.     {    
  65.         PostOrder(root->_left);    
  66.     }    
  67.      if(root->_right != NULL)    
  68.     {    
  69.         PostOrder(root->_right);    
  70.     }    
  71.     if(root != NULL)    
  72.     {    
  73.         cout<<root->_value<<" ";    
  74.     }    
  75. }    
  76. int main()    
  77. {    
  78.     int PreOrder[8] = {1,2,4,7,3,5,6,8};    
  79.     int  InOrder[8] = {4,7,2,1,5,3,8,6};    
  80.     BTreeNode *root = NULL;    
  81.     
  82.     PostOrder(RebuildTree(PreOrder,InOrder,8));    
  83.     system("pause");    
  84.     return 0;    
  85. }    

 

[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. //解法二    
  2. void RebuildTree(int * PreOrder,int *InOrder,int len,BTreeNode ** root)    
  3. {    
  4.     if(PreOrder == NULL || InOrder == NULL)    
  5.     {    
  6.         return;    
  7.     }    
  8.     BTreeNode*tmp = new BTreeNode();    
  9.     tmp->_value = PreOrder[0];    
  10.     tmp->_left = NULL;    
  11.     tmp->_right = NULL;    
  12.     if( root == NULL)    
  13.     {    
  14.         *root = tmp;    
  15.     }    
  16.     if(len == 1)    
  17.     {    
  18.         return;    
  19.     }    
  20.     int *OriOrder = InOrder;    
  21.     int *LeftEnd = InOrder;    
  22.     int tmplen = 0;    
  23.     
  24.     //找到左子树的结尾    
  25.     while(*PreOrder != *LeftEnd)    
  26.     {    
  27.         if(PreOrder == NULL || LeftEnd == NULL)    
  28.         {    
  29.             return;    
  30.         }    
  31.         tmplen++;    
  32.         if(tmplen>len)    
  33.         {    
  34.             break;    
  35.         }    
  36.         LeftEnd++;    
  37.     }    
  38.     //计算左子树的长度    
  39.     int leftlen = 0;    
  40.     leftlen = LeftEnd-OriOrder;    
  41.     //计算右子树的长度    
  42.     int rightlen = 0;    
  43.     rightlen = len-leftlen-1;    
  44.     //重建左子树    
  45.     if(leftlen > 0)    
  46.     {    
  47.          RebuildTree(PreOrder+1,InOrder,leftlen,&((*root)->_left));    
  48.     }    
  49.     
  50.     //重建右子树    
  51.     if(rightlen < 0)    
  52.     {    
  53.         RebuildTree(PreOrder+leftlen+1,InOrder+leftlen+1,rightlen, &((*root)->_right));    
  54.     }    
  55.         
  56. }    


其实还可以优化,就是利用栈和队列来实现,相对来说较递归要好理解一些。
其实这还出现一些问题,倘若出现相同元素怎么处理,这就需要下去继续深究了

posted @ 2017-03-16 19:21  天涯海角路  阅读(143)  评论(0)    收藏  举报