同一棵二叉树(每个节点值唯一)具有唯一的先序序列、中序序列和后序序列,不同二叉树可能具有相同的先序序列、中序序列和后序序列。
同时给定先序序列和中序序列或者中序序列和后序序列都能唯一确定二叉树,但同时给定先序序列和后序序列不能唯一确定二叉树。
1.由先序和中序构建二叉树
由先序序列可知
a
0
a_0
a0是根节点,假设对应于
b
k
b_k
bk,则可得左子树有k个节点,右子树有n-k-1个节点,便可以取定左右子树。采用类似的方法一直进行。
void CreatBT1(BTnode* &T,string pre,string in)
{
if(pre.size() == 0)
{
T = nullptr;
return;
}
int n = pre.size();
char roots = pre[0];//获得根节点的值
int k = in.find(roots);//由根节点在中序的位置获得左子树的长度
//substr函数有两个参数,第一个是开始位置,第二个是获取子串的长度
string leftin = in.substr(0,k);//左子树中序
string rightin = in.substr(k+1,n-k-1);//右子树中序
string leftpre = pre.substr(1,k);//左子树先序
string rightpre = pre.substr(k+1,n-k-1);//右子树先序
T = (BTnode*)malloc(sizeof(BTnode));
if(T != nullptr)
{
T->data = roots;
CreatBT1(T->lnode,leftpre,leftin);
CreatBT1(T->rnode,rightpre,rightin);
}
}
2.由后序和中序构建二叉树
由后序序列可以确定根节点,由中序序列可以确定左右子树。
void CreatBT2(BTnode* &T, string post, string in){//由后序序列和中序序列确定树
if (post.size() == 0){
T = nullptr;
return;
}
else{
int n = post.size();
char roots = post[n-1];//确定根节点
int k = in.find(roots);//找出根节点在中序序列中的位置,得到左子树的长度
string leftpost = post.substr(0,k);//左子树的后序序列
string leftin = in.substr(0,k);//左子树的中序序列
string rightpost = post.substr(k,n-k-1);//右子树的后序序列
string rightin = in.substr(k+1,n-k-1);//右子树的中序序列
T = (BTnode*)malloc(sizeof(BTnode));//创建根节点
if (T != nullptr){
T->data = roots;
CreatBT2(T->lnode,leftpost,leftin);
CreatBT2(T->rnode,rightpost,rightin);
}
}
}
二叉树顺序存储和链式存储的转换
例1:设计算法将二叉树的顺序存储结构转换成二叉链存储结构。
递归模型:当i大于MaxSize时,f(a,i)=NULL;当i对应的节点为空时,f(a,i)=NULL;其他情况,创建根节点b,其值为a[i],b->lchild=f(a,2i),b->rchild=f(a,2i+1)。
typedef char SqBTree[MaxSize];
BTnode* trans1(SqBTree a, int i){//将顺序存储转换为二叉链存储结构
if (i>MaxSize) return nullptr;
if (a[i] == '#') return nullptr;
BTnode* b;
b = (BTnode*)malloc(sizeof(BTnode));
b->data = a[i];
b->lnode = trans1(a,2*i);
b->rnode = trans1(a,2*i+1);
return b;
}
例2:设计算法将二叉树的二叉链转换为顺序存储结构。
f(b,a,i):由b创建a[i]为根节点的顺序存储结构a。递归模型:
当b=NULL时,a[i] = ‘#’ ;其他情况,a[i] = b->data,f(b->lchild,a,2i),f(b->rchild,a,2i+1)。
void trans2(BTnode* b, SqBTree &a, int i){//将二叉链转换为顺序存储结构
if (b != nullptr){
a[i] = b->data;
trans2(b->lnode,a,2*i);
trans2(b->rnode,a,2*i+1);
}
else{
a[i] = '#';
}
}
int main() {
BTnode* root2;
char s[] = "0ABCD#EF##G####################";
root2 = trans1(s,1);
Display(root2);
cout << '\n' << endl;
SqBTree a;
trans2(root2,a,1);
BTnode* root3;
root3 = trans1(a,1);
Display(root3);
return 0;
}