二叉树——根据二叉树遍历序列构造二叉树

根据前序序列和中序序列构造二叉树

  二叉树的节点类型声明如下:

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;  
}

  运行结果如下:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值