二叉树基础-由中根序列和后根序列重建二叉树(数据结构基础 第5周)

问题描述
二叉树基础-由中根序列和后根序列重建二叉树(数据结构基础 第5周)_第1张图片
分析
1. 这道题建立二叉树需要使用递归来做,具体思路可参考:http://blog.csdn.net/ditian1027/article/details/19981849
2. 下面代码中需要注意一点,在createTree()函数中使用指针作为函数返回值,并且这个指针又是在函数内定义,这样是有风险的,因为函数结束时这个指针内存就被释放了(这里程序能AC通过只是碰巧而已)。暂时想到的一个方法是在函数外定义一个存放节点的数组来解决此问题,还没有做。关于这个问题很容易被忽视,详见如下PPT讲解:

二叉树基础-由中根序列和后根序列重建二叉树(数据结构基础 第5周)_第2张图片

源码

#include <iostream>
#include <vector>
using namespace std;

vector<int> vIn;
vector<int> vPost;

template <class T>
class BinaryTreeNode  
{
private:
    T  element;                                         //二叉树结点数据域
    BinaryTreeNode<T>*  left;                           //二叉树结点指向左子树的指针
    BinaryTreeNode<T>*  right;                          //二叉树结点指向左子树的指针
public:
    BinaryTreeNode();
    BinaryTreeNode(const T& ele);                       //给定数据的构造函数
    T  value() const;                                   //返回当前结点的数据
    void  setLeftchild(BinaryTreeNode<T>*);             //设置当前结点的左子树
    void  setRightchild(BinaryTreeNode<T>*);            //设置当前结点的右子树
    BinaryTreeNode<T>*  leftchild() const;              //返回当前结点指向左子树的指针
    BinaryTreeNode<T>*  rightchild() const;             //返回当前结点指向右子树的指针
};
template <class T>
class BinaryTree  
{
private:
    BinaryTreeNode<T>*  root;                               //二叉树根结点指针
    vector<T> elements;  //用于保存遍历的元素
private:
    void Visit(T elem) {elements.push_back(elem);};  //遍历访问元素的值
    void PreOrder(BinaryTreeNode<T>* root); //从root前序遍历二叉树或其子树(递归部分)
    void DeleteBinaryTree(BinaryTreeNode<T>* root);     //递归删除二叉树或其子树 
public:
    BinaryTree(){root=NULL;};                               //构造函数
    virtual ~BinaryTree(){DeleteBinaryTree(root);};            //析构函数
    void Initialize(BinaryTreeNode<T>* pointer) {root=pointer;};    
    vector<T> traversePreOrder();  //从根节点前序遍历,以下依次对应
};
//根据后序和中序创建二叉树
//中序的首尾元素坐标,后序的首尾元素坐标
BinaryTreeNode<int>* createTree(int io1, int io2, int po1, int po2) {
    BinaryTreeNode<int> *p;  //新建一个结点(此处使用局部变量有风险)
    p=new BinaryTreeNode<int>(vPost[po2]);  //后序的最后一个元素是根结点

    //在中序里寻找根结点
    int i;
    for(i=io1; i<=io2; i++) {
        if (p->value() == vIn[i]){
            break;
        }
    }
    //左子树是中序从io1到io1+i-1, 后序从po1到po1+i-1
    //注意递归出口,只有当io1<=io1+i-1即i>=1时才有意义
    if (io1<=i-1){
        p->setLeftchild(createTree(io1, i-1, po1, po1+(i-1-io1)));
    }
    //右子树类似
    if (i+1<=io2){
        p->setRightchild(createTree(i+1, io2, po2-1-(io2-i-1), po2-1));
    }
    return p;
}

int main() {
    int i;
    while(cin >> i) {
        vIn.push_back(i);
        if (cin.get() == '\n')
            break;
    }
    while(cin >> i) {
        vPost.push_back(i);
        if (cin.get() == '\n')
            break;
    }

    BinaryTree<int> tr;
    tr.Initialize(createTree(0, vIn.size()-1, 0, vPost.size()-1));
    vector<int> res = tr.traversePreOrder();
    for (int i=0; i<res.size(); i++) {
        cout << res[i] << ' ';
    }
    return 0;
}

/*****************BinaryTreeNode类模板的实现************************/
template<class T>
BinaryTreeNode<T>::BinaryTreeNode()
{
    left=right=NULL;
}

template<class T>
BinaryTreeNode<T>::BinaryTreeNode(const T& ele) //给定数据的构造函数
{
    element=ele;
    left=right=NULL;
}

template<class T>
T  BinaryTreeNode<T>::value() const
{
    return element; 
}

template<class T>
BinaryTreeNode<T>*  BinaryTreeNode<T>::leftchild() const
{
    return left;                                //返回当前结点指向左子树的指针
}

template<class T>
BinaryTreeNode<T>*  BinaryTreeNode<T>::rightchild() const
{
    return right;                               //返回当前结点指向右子树的指针
}  

template<class T>
void  BinaryTreeNode<T>::setLeftchild(BinaryTreeNode<T>* subroot)//设置当前结点的左子树
{
    left=subroot;
}

template<class T>
void  BinaryTreeNode<T>::setRightchild(BinaryTreeNode<T>* subroot)//设置当前结点的右子树
{
    right=subroot;
}

/*****************BinaryTree类模板的实现************************/

template<class T>
void BinaryTree<T>::DeleteBinaryTree(BinaryTreeNode<T>* root)       //递归删除二叉树或其子树
{
    if(root)
    {
        DeleteBinaryTree(root->leftchild());
        DeleteBinaryTree(root->rightchild());
        delete root;
    };
};


template<class T>
void BinaryTree<T>::PreOrder(BinaryTreeNode<T>* root)               //前序遍历二叉树或其子树
{
    if(root!=NULL)
    {
        Visit(root->value());   
        PreOrder(root->leftchild());            //访问左子树
        PreOrder(root->rightchild());           //访问右子树
    }
};
template<class T>
vector<T> BinaryTree<T>::traversePreOrder() 
{
    elements.clear();
    PreOrder(root);
    return elements;
}

你可能感兴趣的:(二叉树基础-由中根序列和后根序列重建二叉树(数据结构基础 第5周))