一、先序序列加中序序列构造二叉树
从左到右遍历先序序列,访问到的当前元素即为根结点的值,每遍历到一个元素,从左至右遍历中序序列,直到找到中序序列中与之对应的值,记录位置pos,将中序序列一分为二,左边即为左子树的序列,右边为右子树序列。然后据此计算左子树结点个数,即用pos减去中序序列起始位置,从而得到先序序列中以当前结点为根的左子树序列和右子树序列的起始和结束位置。最后对两个子序列继续如上递归操作,直到子树序列长度为0时停止。
二、图示
三、代码实现
#include <iostream>
using namespace std;
typedef struct BiTNode {
char data;
struct BiTNode *lchild;
struct BiTNode *rchild;
} BiTNode, *BiTree;
string PreOrder; //保存先序序列
string InOrder;//保存中序序列
string PostOrder;//保存后序序列
//preleft先序序列的起始位置,preRight先序序列的终止位置,inLeft中序序列的起始位置,inRight中序序列的终止位置
BiTree CreateBiTree_PI(int preLeft, int preRight, int inLeft, int inRight) {
if (preLeft <= preRight) { //先序序列长度至少为1,即对应子树至少有一个结点
BiTree T = (BiTNode *) malloc(sizeof(BiTNode));//创建根结点
T->data = PreOrder[preLeft];//赋值,即为先序序列的第一个元素
int pos;//记录当前元素在中序序列中的位置
for (pos = inLeft; pos <= inRight; ++pos) {//求pos
if (InOrder[pos] == PreOrder[preLeft])
break;
}
int LeftTreeNum = pos - inLeft;//统计左子树结点个数
T->lchild = CreateBiTree_PI(preLeft + 1, preLeft + LeftTreeNum, inLeft, pos - 1);//递归构造左子树
T->rchild = CreateBiTree_PI(preLeft + LeftTreeNum + 1, preRight, pos + 1, inRight);//递归构造右子树
return T;
} else return NULL;
}
void PreOrderTraverse(BiTree T) { //先序遍历
if (T != NULL) {
cout << T->data << " "; //访问根结点
PreOrderTraverse(T->lchild);//访问左子树
PreOrderTraverse(T->rchild);//访问右子树
}
}
void InOrderTraverse(BiTree T) { //中序遍历
if (T != NULL) {
InOrderTraverse(T->lchild);//访问左子树
cout << T->data << " "; //访问根结点
InOrderTraverse(T->rchild);//访问右子树
}
}
void PostOrderTraverse(BiTree T) { //后序遍历
if (T != NULL) {
PostOrderTraverse(T->lchild);//访问左子树
PostOrderTraverse(T->rchild);//访问右子树
cout << T->data << " "; //访问根结点
}
}
int main() {
PreOrder = "ABDECFG";
InOrder = "DBEAFCG";
PostOrder = "DEBFGCA";
BiTree T = CreateBiTree_PI(0, 6, 0, 6);
cout << "先序遍历序列为:";
PreOrderTraverse(T);
cout << endl;
cout << "中序遍历序列为:";
InOrderTraverse(T);
cout << endl;
cout << "后序遍历序列为:";
PostOrderTraverse(T);
return 0;
}
四、后序序列加中序序列构造二叉树
与上面类似,只不过对后序序列,应从右往左遍历,同样访问到的当前元素即为根结点的值,每遍历到一个元素,从左至右遍历中序序列,直到找到中序序列中与之对应的值,将中序序列一分为二,左边即为左子树的序列,右边为右子树序列,计算左子树结点个数,得到先序序列中以当前结点为根左子树序列和右子树序列。在对两个子序列继续如上操作,直到子树序列长度为0时停止。
#include <iostream>
using namespace std;
typedef struct BiTNode {
char data;
struct BiTNode *lchild;
struct BiTNode *rchild;
} BiTNode, *BiTree;
string PostOrder; //保存后序序列
string InOrder;//保存中序序列
string PostOrder;//保存后序序列
//postleft为后序序列的起始位置,postRight后序序列的终止位置,inLeft中序序列的起始位置,inRight中序序列的终止位置
BiTree CreateBiTree_HI(int postLeft, int postRight, int inLeft, int inRight) {
if (postLeft <= postRight) {//后序序列长度至少为1,即对应子树至少有一个结点
BiTree T = (BiTNode *) malloc(sizeof(BiTNode));
T->data = PostOrder[postRight];
int pos;
for (pos = inLeft; pos <= inRight; ++pos) {
if (InOrder[pos] == PostOrder[postRight])
break;
}
int LeftTreeNum = pos - inLeft;//计算左子树结点个数
//后序子树序列依旧从左往右,和中序序列相对应
T->lchild = CreateBiTree_HI(postLeft, postLeft + LeftTreeNum - 1, inLeft, pos - 1);//递归构造左子树
T->rchild = CreateBiTree_HI(postLeft + LeftTreeNum, postRight - 1, pos + 1, inRight);//递归构造右子树
return T;
} else return NULL;
}
void PreOrderTraverse(BiTree T) { //先序遍历
if (T != NULL) {
cout << T->data << " "; //访问根结点
PreOrderTraverse(T->lchild);//访问左子树
PreOrderTraverse(T->rchild);//访问右子树
}
}
void InOrderTraverse(BiTree T) { //中序遍历
if (T != NULL) {
InOrderTraverse(T->lchild);//访问左子树
cout << T->data << " "; //访问根结点
InOrderTraverse(T->rchild);//访问右子树
}
}
void PostOrderTraverse(BiTree T) { //后序遍历
if (T != NULL) {
PostOrderTraverse(T->lchild);//访问左子树
PostOrderTraverse(T->rchild);//访问右子树
cout << T->data << " "; //访问根结点
}
}
int main() {
PreOrder = "ABDECFG";
InOrder = "DBEAFCG";
PostOrder = "DEBFGCA";
BiTree T = CreateBiTree_HI(0, 6, 0, 6);
cout << "先序遍历序列为:";
PreOrderTraverse(T);
cout << endl;
cout << "中序遍历序列为:";
InOrderTraverse(T);
cout << endl;
cout << "后序遍历序列为:";
PostOrderTraverse(T);
return 0;
}