剑指offer--据前序和中序遍历重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
分析:此时不由得想起前序遍历的顺序是根--左--右
- #include<stdio.h>
- #include<stdlib.h>
- #include<iostream>
- using namespace std;
- struct BTreeNode
- {
- int _value;
- BTreeNode*_left;
- BTreeNode*_right;
- };
- //解法一
- BTreeNode* RebuildCode(int * PreStart,int *PreEnd,int *InStart,int *InEnd);
- BTreeNode* RebuildTree(int *PreOrder,int *InOrder,int len)
- {
- //首先判断边界条件
- if(PreOrder == NULL || InOrder == NULL ||len <= 0)
- {
- return NULL;
- }
- else
- {
- return RebuildCode(PreOrder,PreOrder+len-1,InOrder,InOrder+len-1);
- }
- }
- BTreeNode* RebuildCode(int * PreStart,int *PreEnd,int *InStart,int *InEnd)
- {
- BTreeNode *root = new BTreeNode();
- //新建节点root保存前序第一个节点为根结点
- root->_value = PreStart[0];
- root-> _left = NULL;
- root->_right = NULL;
- if(InStart == InEnd && *InStart == *InEnd)
- {
- return root;
- }
- //据此节点找到中序遍历此节点的位置
- int *rootIn = InStart;
- while(*PreStart != *rootIn)
- {
- rootIn++;
- }
- //左子树的长度
- int leftlen = rootIn-InStart;
- //重建左子树
- if(leftlen > 0)
- {
- root->_left = RebuildCode( PreStart+1,PreStart+leftlen,InStart,InStart+leftlen-1);
- }
- //重建右子树
- if(InStart+leftlen < InEnd)
- {
- root->_right = RebuildCode( PreStart+leftlen+1,PreEnd,InStart+leftlen+1,InEnd);
- }
- return root;
- }
- //后序遍历输出二叉树序列
- void PostOrder(BTreeNode *root)
- {
- if(root->_left != NULL)
- {
- PostOrder(root->_left);
- }
- if(root->_right != NULL)
- {
- PostOrder(root->_right);
- }
- if(root != NULL)
- {
- cout<<root->_value<<" ";
- }
- }
- int main()
- {
- int PreOrder[8] = {1,2,4,7,3,5,6,8};
- int InOrder[8] = {4,7,2,1,5,3,8,6};
- BTreeNode *root = NULL;
- PostOrder(RebuildTree(PreOrder,InOrder,8));
- system("pause");
- return 0;
- }
- //解法二
- void RebuildTree(int * PreOrder,int *InOrder,int len,BTreeNode ** root)
- {
- if(PreOrder == NULL || InOrder == NULL)
- {
- return;
- }
- BTreeNode*tmp = new BTreeNode();
- tmp->_value = PreOrder[0];
- tmp->_left = NULL;
- tmp->_right = NULL;
- if( root == NULL)
- {
- *root = tmp;
- }
- if(len == 1)
- {
- return;
- }
- int *OriOrder = InOrder;
- int *LeftEnd = InOrder;
- int tmplen = 0;
- //找到左子树的结尾
- while(*PreOrder != *LeftEnd)
- {
- if(PreOrder == NULL || LeftEnd == NULL)
- {
- return;
- }
- tmplen++;
- if(tmplen>len)
- {
- break;
- }
- LeftEnd++;
- }
- //计算左子树的长度
- int leftlen = 0;
- leftlen = LeftEnd-OriOrder;
- //计算右子树的长度
- int rightlen = 0;
- rightlen = len-leftlen-1;
- //重建左子树
- if(leftlen > 0)
- {
- RebuildTree(PreOrder+1,InOrder,leftlen,&((*root)->_left));
- }
- //重建右子树
- if(rightlen < 0)
- {
- RebuildTree(PreOrder+leftlen+1,InOrder+leftlen+1,rightlen, &((*root)->_right));
- }
- }
其实还可以优化,就是利用栈和队列来实现,相对来说较递归要好理解一些。
其实这还出现一些问题,倘若出现相同元素怎么处理,这就需要下去继续深究了

浙公网安备 33010602011771号