构造思想:
假设当前处理先序序列pre
的处理区间是[a,b]
,中序序列in
处理的区间是[c,d]
。
例如:
string pre = "123456789";
string in = "325416879";
pre
的处理区间是[0,8]
,中序序列in
处理的区间是[0,8]
若a<b
,则以pre[a]
建立二叉树的根结点,然后搜索in[c,d]
,找到in[i] == pre[a]
的位置i
,从而把中序序列分为两个中序子序列in[c,i-1]
和in[i+1,d]
,前者有i-1-c+1 = i - c
个元素,后者有d-(i+1) +1
个元素。再分别以pre[a+1,a+i-c]
和in[c,i-1]
递归构造根的左子树(pre[a]
为根,不用 再处理),以pre[a+i-c+1,b]
和in[i+1,d]
递归构造根的右子树。
注:为什么以pre[a+1,a+i-c]
和in[c,i-1]
递归构造根的左子树,,以pre[a+i-c+1,b]
和in[i+1,d]
递归构造根的右子树?
因为先序遍历和中序遍历的共同点是后访问右子树,所以i
前面的在pre
里除了pre[a]
都是左子树,有i-c
个元素。
代码:
#include<iostream>
#include<string>
#include<vector>
#include<queue>
using namespace std;
struct TreeNode
{
char data;
TreeNode *lchild,*rchild;
};
void createBinTree_pre_in(TreeNode *&root,string pre,string in,int a,int b,int c,int d)
{//由二叉树的先序序列和中序序列构建二叉树
if(a <= b)
{
root = new TreeNode(); //创建根节点
root->data = pre[a];
root->lchild = NULL;
root->rchild = NULL;
int i;
for(i = c; i <= d; i++) //中序序列中查找根的位置,此处为i
{
if(in[i] == pre[a])
break;
}
createBinTree_pre_in(root->lchild,pre,in,a+1,a+i-c,c,i-1); //递归建左子树
createBinTree_pre_in(root->rchild,pre,in,a+i-c+1,b,i+1,d); //递归建右子树
}
}
void levelOrder(TreeNode* root) //利用队列实现二叉树的层次遍历
{
queue<TreeNode*>que;
TreeNode* p = root;
que.push(p);
while(!que.empty())
{
p = que.front(); que.pop();
cout<<p->data;
if(p->lchild != NULL)
{
que.push(p->lchild);
}
if(p->rchild != NULL)
{
que.push(p->rchild);
}
}
}
int main() //test
{
TreeNode *root;
string pre = "123456789";
string in = "325416879";
createBinTree_pre_in(root,pre,in,0,8,0,8);
levelOrder(root);
return 0;
}
参考:
《数据结构C语言描述第2版》—殷人昆