题目:先序遍历为1,2,4,7,3,5,6,8,中序遍历为4,7,2,1,5,3,8,6,根据以上遍历序列生成原来的二叉树。
思路:先序遍历的第一个节点为1,即头节点为1,找到头节点1在中序遍历中的位置,根据中序遍历的特点,可以知道头节点1左边的序列是位于左子树上的节点,头节点1右边的序列是位于右子树上的节点,于是构造头节点1,得到头节点左子树的中序遍历序列为4,7,2,总共3个数,那么说明左子树的先序遍历数字也应该有3个,根据先序遍历为VLR,在先序遍历头节点1后面的3个节点为左子树的先序遍历序列,这个序列为2,4,7,而剩下的序列为右子树上先序遍历的顺序,其右边节点的中序遍历为3,5,6,8。于是将该问题划分为两个字问题:
从先序遍历为2,4,7,中序遍历为4,7,2构造一个子树作为根节点的左子树。
从先序遍历为3,5,6,8,中序遍历为5,3,8,6构造一个子树作为根节点的右子树。
构造子树的过程重复以上构造过程即可,直到遍历序列为空则返回空指针
二叉树节点构造如下:
//二叉树节点定义
template<typename T>struct BTNode
{
public:
BTNode(const T& v=0):data(v),left(nullptr),right(nullptr){}
BTNode():data(0),left(nullptr),right(nullptr){}
BTNode<T>* left,right;
T data;
};
//寻找下标函数
template<typename T>
int findIndex(const T& num,const vector<T>& srcVec)
{
for(int i = 0;i!=srcVec.size();++i)
if(srcVec[i]==num)
return i;
return -1;
}
//按照层序遍历打印树上的节点
template<typename T>
void levelVisitBinaryTree(BTNode<T>* root)
{
if(root==nullptr)
return;
queue<BTNode<T>*> myQueue;
myQueue.push(root);
while(!myQueue.empty())
{
BTNode<T>* r=nullptr;
while(!myQueue.empty())
{
r = myQueue.front();
cout<<r->data<<" ";
myQueue.pop();
if(r->left)
myQueue.push(r->left);
if(r->right)
myQueue.push(r->right);
}
cout<<endl;
}
}
//根据先序遍历和中序遍历构造二叉树
template<typename T>
BTNode<T>* createBinaryTree(vector<T>& preOrder,vector<T>& inOrder)
{
if(preOrder.size()==0||inOrder.size()==0)
return nullptr;
//findIndex函数找到头节点在中序遍历中的下标
int rootIndex = findIndex(preOrder[0],inOrder);
BTNode<T>* root=new BTNode<T>(preOrder[0]);//构造根节点
if(rootIndex>=0)
{
BTNode<T>* left=nullptr,*right=nullptr;//左子树和右子树
vector<T> leftPreOrder;//左子树先序遍历序列
vector<T> leftInOrder;//左子树中序遍历序列
if(rootIndex>0)
{
//构造左子树的先序遍历序列
leftPreOrder.assign(preOrder.begin()+1,
preOrder.begin()+rootIndex+1);
//构造左子树的中序遍历序列
leftInOrder.assign(inOrder.begin(),
inOrder.begin()+rootIndex);
//根据先序和中序构造左子树
left = createBinaryTree(leftPreOrder,leftInOrder);
}
vector<T> rightPreOrder;//右子树先序遍历序列
vector<T> rightInOrder;//右子树中序遍历序列
if(static_cast<int>(rootIndex)<preOrder.size()-1)
//构造右子树的先序遍历序列
rightPreOrder.assign
(preOrder.begin()+rootIndex+1,preOrder.end());
if(static_cast<int>(rootIndex)<inOrder.size()-1)
//构造右子树的中序遍历序列
rightInOrder.assign
(inOrder.begin()+rootIndex+1,inOrder.end());
//根据先序和中序构造右子树
right= createBinaryTree(rightPreOrder,rightInOrder);
//left和right赋值给root
root->left = left;
root->right = right;
}
return root;
}
//以下代码用于测试
int main()
{
vector<int> preOrder;
int a[]={1,2,4,7,3,5,6,8};
preOrder.assign(begin(a),end(a));
vector<int> inOrder;
int b[]={4,7,2,1,5,3,8,6};
inOrder.assign(begin(b),end(b));
BTNode<int>* root = createBinaryTree(preOrder,inOrder);
}