根据前序序列和中序序列构造二叉树
二叉树的节点类型声明如下:
struct BTNode {
char val;
BTNode *left;
BTNode *right;
BTNode(char c):val(c), left(NULL), right(NULL);
};
定理1 任何(n>=0)个不同节点的二叉树,都可由它的前序序列和中序序列唯一地确定。
根据前序遍历的特点, 知前序序列(PreSequence)的首个元素(PreSequence[0])为二叉树的根(root), 然后在中序序列(InSequence)中查找此根(root), 根据中序遍历特点, 知在查找到的根(root) 前边的序列为根的左子树的中序遍历序列, 后边的序列为根的右子树的中序遍历序列。 设在中序遍历序列(InSequence)根前边有left个元素. 则在前序序列(PreSequence)中, 紧跟着根(root)的left个元素序列(即PreSequence[1…left]) 为根的左子树的前序遍历序列, 在后边的为根的右子树的前序遍历序列.而构造左子树问题其实跟构造整个二叉树问题一样,只是此时前序序列为PreSequence[1…left]), 中序序列为InSequence[0…left-1], 分别为原序列的子串, 构造右子树同样, 显然可以用递归方法解决。算法如下:
//根据前序遍历序列和中序遍历序列构造二叉树
void CreateBT1(BTNode* &T, string pre, string in) {
if(pre.length()==0) {
T=NULL;
return;
}
char nodeVal = pre[0];
int index = in.find(nodeVal);
string lin = in.substr(0,index);
string rin = in.substr(index+1);
int leftChildLength = lin.length();
string lpre = pre.substr(1,leftChildLength);
string rpre = pre.substr(leftChildLength+1);
T = new BTNode(nodeVal);
CreateBT1(T->left,lpre,lin);
CreateBT1(T->right,rpre,rin);
}
根据中序序列和后续序列构造二叉树
定理2 任何(n>=0)个不同节点的二叉树,都可由它的中序序列和后序序列唯一地确定。
构造过程类似,算法如下:
//根据中序遍历序列和后序遍历序列构造二叉树
void CreateBT2(BTNode* &T, string in, string post) {
int len = post.length();
if(len == 0) {
T = NULL;
return;
}
char nodeVal = post[len-1];
int index = in.find(nodeVal);
string lin = in.substr(0,index);
string rin = in.substr(index+1);
int leftChildLength = lin.length();
int rightChildLength = rin.length();
string lpost = post.substr(0,leftChildLength);
string rpost = post.substr(leftChildLength,rightChildLength);
T = new BTNode(nodeVal);
CreateBT2(T->left,lin,lpost);
CreateBT2(T->right,rin,rpost);
}
完整测试代码
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
struct BTNode {
char val;
BTNode *left;
BTNode *right;
BTNode(char c) : val(c),left(NULL),right(NULL) {}
};
//根据前序遍历序列和中序遍历序列构造二叉树
void CreateBT1(BTNode* &T, string pre, string in) {
if(pre.length()==0) {
T=NULL;
return;
}
char nodeVal = pre[0];
int index = in.find(nodeVal);
string lin = in.substr(0,index);
string rin = in.substr(index+1);
int leftChildLength = lin.length();
string lpre = pre.substr(1,leftChildLength);
string rpre = pre.substr(leftChildLength+1);
T = new BTNode(nodeVal);
CreateBT1(T->left,lpre,lin);
CreateBT1(T->right,rpre,rin);
}
//根据中序遍历序列和后序遍历序列构造二叉树
void CreateBT2(BTNode* &T, string in, string post) {
int len = post.length();
if(len == 0) {
T = NULL;
return;
}
char nodeVal = post[len-1];
int index = in.find(nodeVal);
string lin = in.substr(0,index);
string rin = in.substr(index+1);
int leftChildLength = lin.length();
int rightChildLength = rin.length();
string lpost = post.substr(0,leftChildLength);
string rpost = post.substr(leftChildLength,rightChildLength);
T = new BTNode(nodeVal);
CreateBT2(T->left,lin,lpost);
CreateBT2(T->right,rin,rpost);
}
//前序遍历(递归)
void PreOrder(BTNode *root) {
if(root) {
cout<<root->val<<" ";
PreOrder(root->left);
PreOrder(root->right);
}
}
//中序遍历(递归)
void InOrder(BTNode *root) {
if(root) {
InOrder(root->left);
cout<<root->val<<" ";
InOrder(root->right);
}
}
//后序遍历(递归)
void PostOrder(BTNode *root) {
if(root) {
PostOrder(root->left);
PostOrder(root->right);
cout<<root->val<<" ";
}
}
//测试用例
int main() {
cout<<"根据前序遍历序列和中序遍历序列构造二叉树"<<endl;
BTNode *t;
string presequence = "ABCDEFG";
string insequence = "CBEDAFG";
CreateBT1(t,presequence,insequence);
cout<<"前序遍历:";
PreOrder(t);
cout<<"中序遍历:";
InOrder(t);
cout<<endl;
cout<<"根据中序遍历序列和后序遍历序列构造二叉树"<<endl;
BTNode *n;
string in = "DGBAECF";
string post = "GDBEFCA";
CreateBT2(n,in,post);
cout<<"中序遍历:";
InOrder(n);
cout<<"后序遍历:";
PostOrder(n);
return 0;
}
运行结果如下: