题目:给出一棵二叉树的先序和中序遍历的序列,构造出该二叉树。
思路一:采用分治法。
1)取先序遍历序列的第一个值,用该值构造根结点,,然后在中序遍历序列中查找与该元素相等的值,这样就可以把序列分为三部分:左子树(如果有)、根结点和右子树(如果有)。
2)将两个序列都分成三部分,这样就分别形成了根结点的左子树和右子树的先序遍历和后序遍历的序列。
3)重复1)和2)步骤,直至所有结点都处理完就可以完整构成一颗二叉树了。
根据分治法构造二叉树的代码实现:
TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder)
{
if(preorder.empty() && inorder.empty())
return NULL;
int root_val = preorder[0];//该子树根结点的元素值为先序遍历的第一个元素
TreeNode* root = new TreeNode(root_val);//创建该子树的根结点
vector<int> preorderL, preorderR, inorderL, inorderR;
vector<int>::iterator it, it_a;//在中序遍历中查找根结点元素
int i = 0;
it = inorder.begin();
while(*it != root_val)
{
it++;
i++;
}
//确定中序遍历的左右子树序列
for(it_a = inorder.begin(); it_a != it; it_a++)
inorderL.push_back(*it_a);
for(it_a = it+1; it_a != inorder.end(); it_a++)
inorderR.push_back(*it_a);
//确定前序遍历的左右子树序列
it = preorder.begin();
while(i)
{
it++;
i--;
}
for(it_a = preorder.begin()+1; it_a != it+1; it_a++)
preorderL.push_back(*it_a);
for(it_a = it+1; it_a != preorder.end(); it_a++)
preorderR.push_back(*it_a);
//迭代构造二叉树
root->left = buildTree(preorderL, inorderL);
root->right = buildTree(preorderR, inorderR);
return root;
}
这段代码在OJ里运行就报错了: Status:
Memory Limit Exceeded
。具体原因我现在也没搞明白……思路二:用栈来实现。
1)用先序遍历序列中的第一个元素构造树的根结点,并将根结点指针入栈。
2)如果栈顶结点的元素值与中序遍历序列当前处理的元素值不相等,则一直用先序遍历序列中的元素构造树结点,如果flag标志值为0,将新结点添加为树当前处理结点的左孩子结点;否则,添加为右孩子结点。
3)如果栈顶结点的元素值与中序遍历序列当前处理的元素值相等,则将栈顶结点置为树的当前处理结点,然后将该结点出栈,并将flag标志置为1.
4)重复2)和3)的操作,直到先序遍历序列处理完。
用栈来实现构造二叉树的代码实现:
TreeNode *buildTree1(vector<int> &preorder, vector<int> &inorder)
{
if(preorder.size()==0)
return NULL;
stack<TreeNode *> st;
TreeNode *t, *root;
int i, j;//i,j分别作为前序和中序遍历序列的处理指针
int f;//用于标识是否要新建右结点
f = i = j = 0;
root = new TreeNode(preorder[i]);
st.push(root);
t = root;
i++;
while(i<preorder.size())
{
//case 1:栈顶结点的元素值与中序遍历当前值相等
if(!st.empty() && st.top()->val == inorder[j])
{
t = st.top();
st.pop();
f = 1;
j++;
}
else
{
//case 2a:f = 0,添加左结点
if(f == 0)
{
t -> left = new TreeNode(preorder[i]);
t = t -> left;
st.push(t);
i++;
}
//case 2b:f = 1,添加右结点
else
{
f = 0;
t -> right = new TreeNode(preorder[i]);
t = t -> right;
st.push(t);
i++;
}
}
}
return root;
}