二叉树为空意味着二叉树_算法与数据结构之二叉树的重建

点击蓝字 关注灯珑

二叉树的重建

前面几篇笔记讲了二叉树的表达与遍历。那么,有没可能根据二叉树遍历的结果,来重建出一棵二叉树呢?答案是肯定的。

给出二叉树前序遍历的结果和中序遍历的结果,我们就能根据这些信息,重新生成二叉树。这个问题相对来说有挑战性,需要花费更长的时间来思考。

看下面这棵树:

c53a89ae36e16f55a55083b943172d1f.png

 前序遍历结果为pre={1,2,3,4,5,6,7,8,9}

中序遍历结果为in={3,2,5,4,6,1,8,7,9}

我们可以发现,设前序遍历的当前节点为c,则在中序遍历的结果中,c点左侧和右侧就可以构成左子树和右子树。也就是说,把中序结果分成两半了。比如,前序当前为1时,那么中序的3,2,5,4,6都属于以1为父节点的左子树,7,8,9都属于以1为父结点的右子树。以此类推,我们就可以通过递归来重建整棵二叉树。

注意事项

我们在处理递归问题的时候,需要处理好区间边界的问题。也就是说,要明确我们的区间是开区间还是闭区间。不然很有可能就因为这区间的问题而导致程序出错。

而且,临界问题也容易出错。在这个问题里面就是结点的左子结点为空和右子结点为空的情况。所以,我在下面的程序里,用了两个标记变量去标记他们的左右子结点是否为空,为空则把它们指向NIL。

代码实现

#include#include#include#includeusing namespace std;#define MAX 100#define NIL -1struct Node{    int id;    int left;    int right;    bool is_left_null;    bool is_right_null;};Node T[MAX];int n;vector<int> st,mi;int pos=0;Node reconstruct(int left,int right){    int root = st[pos];    if(left >= right)    {        Node tmp;        tmp.left = NIL;        tmp.right = NIL;        tmp.id = root;        //处理好边界问题,也就是子节点为空的时候        tmp.is_left_null = true;        tmp.is_right_null = true;        return tmp;    }    pos++;    int m = distance(mi.begin(), find(mi.begin(), mi.end(), root));    Node tmp1 = reconstruct(left,m);    Node tmp2 = reconstruct(m+1,right);    if(tmp1.is_left_null)    {        T[root].left = NIL;    }    else{        T[root].left = tmp1.id;    }    if(tmp2.is_right_null)    {        T[root].right = NIL;    }    else{        T[root].right = tmp2.id;    }    T[root].id = root;    return T[root];}/*void check(){    for(int i=1;i<=n;i++)    {        if(T[i].left==T[i].right)        {            T[i].left = NIL;            T[i].right = NIL;        }        if(T[i].left==0)            T[i].left = NIL;        if(T[i].right == 0)            T[i].right = NIL;    }}*/void postOrder(int u){    if(u==NIL)    {        return;    }    postOrder(T[u].left);    postOrder(T[u].right);    printf("%d", u);    if(u!=st[0])        cout<<" ";}int main(){    for(int i=0;i    {        T[i].left = NIL;        T[i].id = NIL;        T[i].right = NIL;    }    cin>>n;    for(int i=0;i    {        int tt;        cin>>tt;        st.push_back(tt);    }    for(int i=0;i    {        int tt;        cin>>tt;        mi.push_back(tt);    }    reconstruct(0,n);    //check();    for(int i=1;i<=n;i++)    {        cout<<"id: "<" left: "<    }    cout<<endl;    postOrder(st[0]);    cout<<endl;}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值