9 二叉树的重建--来源于沈钰S同学(舒姐)

本文介绍了如何根据二叉树的前序和中序遍历,或者中序和后序遍历结果来重构二叉树。提供了两种重构算法的详细实现,包括递归函数和外壳函数,用于创建符合给定遍历顺序的二叉树结构。同时,给出了输入输出说明以及示例,帮助理解算法的工作原理。
摘要由CSDN通过智能技术生成

来源于沈钰S同学(舒姐)

来源于沈钰S同学(舒姐)

abyssfall的博客_CSDN博客-计科学子的头发账本,代码存档领域博主

问题描述 :

目的:现有两个结点序列,分别是对同一个二叉树进行前序遍历和中序遍历(或中序和后序)的结果。要求设计一个算法,重构该二叉树,并输出该二叉树按照后序(前序)遍历时的结点序列。假定二叉树所有的结点的数据域的值都不相同。二叉树的存储结构的建立参见二叉树应用1。

一、已知前序和中序的结果,进行二叉树的重构:

提示:preOrder按照先根再左再右的顺序递归遍历,inOrder按照先左再根再右的顺序递归遍历。

举例说明:preOrder的输入pre={A,B,D,G,H,C,E,I,F},inOrder的输入in={G,D,H,B,A,E,I,C,F}。首先按preOrder遍历的顺序依次访问各结点。访问过程中,通过in得知各子树内inOrder遍历的顺序,从而重建以当前访问结点c为根的左子树与右子树。即:设preOrder遍历的当前结点为c,c在in中的位置为m,m左侧就是c的左子树,右侧就是c的右子树。同理递归。

(2)

参考函数原型:

(1)//重建二叉树的存储结构 (外壳)
template<class ElemType>
BinaryTreeNode<ElemType> *ReBuildTree_Pre_In(vector[ElemType] &pre, vector[ElemType] &in);

(2)//重建二叉树的存储结构 (递归)
template<class ElemType>
BinaryTreeNode<ElemType> *reConstructCore_Pre_In(vector[ElemType] &pre, vector[ElemType] &in, int preStart, int preEnd, int inStart, int inEnd );

二、已知中序和后序的结果,进行二叉树的重构:

可参考一的思路。

参考函数原型:

(1)//重建二叉树的存储结构 (外壳)
template<class ElemType>
BinaryTreeNode<ElemType> *ReBuildTree_In_Post(vector[ElemType] &in, vector[ElemType] &post);

(2)//重建二叉树的存储结构 (递归)
template<class ElemType>
BinaryTreeNode<ElemType> *reConstructCore_In_Post(vector[ElemType] &in, vector[ElemType] &post, int inStart, int inEnd, int postStart, int postEnd );

输入说明 :

第一行:重构选择(0:前序中序重构  1:中序后序重构)  

0:

第二行:按前序遍历的结点序列,相邻结点用空格隔开

第三行:按中序遍历的结点序列,相邻结点用空格隔开

1:

第二行:按中序遍历的结点序列,相邻结点用空格隔开

第三行:按后序遍历的结点序列,相邻结点用空格隔开

输出说明 :

0:

第一行:按后序遍历的结点序列,相邻结点用","隔开

1:

第一行:按前序遍历的结点序列,相邻结点用","隔开

-----------

0
A B C D E
B D C E A

----------------

D,E,C,B,A

#include <bits/stdc++.h>
using namespace std;

template <class ElemType>
struct BinaryTreeNode
{
    ElemType data;
    BinaryTreeNode<ElemType> *left;
    BinaryTreeNode<ElemType> *right;
};

template <class ElemType>
void cinin(string str, vector<ElemType> &a)
{
    int len = str.length();
    string str0 = "";
    for (int i = 0; i < len; i++)
    {

        if (str[i] != ' ')
        {
            str0 += str[i];
        }

        else
        {
            a.push_back(str0);
            str0 = "";
        }
    }
    a.push_back(str0);
}

bool f = false;

//前序遍历
template <class ElemType>
void visit1(BinaryTreeNode<ElemType> *head)
{
    if (head)
    {
        if (f == false)
        {
            f = true;
            cout << head->data;
        }

        else
        {
            cout << "," << head->data;
        }
    }
    if (head->left)
        visit1(head->left);
    if (head->right)
        visit1(head->right);
    return;
}

//后序遍历
template <class ElemType>
void visit3(BinaryTreeNode<ElemType> *head)
{
    if (head->left)
        visit3(head->left);
    if (head->right)
        visit3(head->right);
    if (head)
    {
        if (f == false)
        {
            f = true;
            cout << head->data;
        }
        else
        {
            cout << "," << head->data;
        }
    }
    return;
}

template <class ElemType>
BinaryTreeNode<ElemType> *reConstructCore_Pre_In(vector<ElemType> &pre, vector<ElemType> &in)
{
    if (pre.size() == 0)
    {
        return NULL;
    } //先序读完了,不进下一层递归了,没叶子了

    vector<ElemType> left_pre, right_pre, left_in, right_in; //总之分一下,左右子树咔咔一下准备进递归

    BinaryTreeNode<ElemType> *head = new BinaryTreeNode<ElemType>;
    head->data = pre[0];

    int root = 0;
    int inlen = in.size();
    for (int i = 0; i < inlen; i++)
    {
        if (pre[0] == in[i])
        {
            root = i;
            break;
        }
        else
            continue;
    } //找一下根结点

    for (int i = 0; i < root; i++)
    {
        left_in.push_back(in[i]);       //中序遍历,根结点之前全是左子树
        left_pre.push_back(pre[i + 1]); //先序遍历,第一个是根节点,往后读取相同数量丢入左子树
    }

    for (int i = root + 1; i < inlen; i++)
    {
        right_in.push_back(in[i]);   //中序遍历,根节点之后全是右子树
        right_pre.push_back(pre[i]); //先序遍历,往后读取相同数量丢入左子树
    }

    head->left = reConstructCore_Pre_In(left_pre, left_in);    //新分好的左子树
    head->right = reConstructCore_Pre_In(right_pre, right_in); //新分好的右子树

    return head;
}

template <class ElemType>
BinaryTreeNode<ElemType> *reConstructCore_In_Post(vector<ElemType> &in, vector<ElemType> &post)
{
    if (post.size() == 0)
    {
        return NULL;
    } //先序读完了,不进下一层递归了,没叶子了

    vector<ElemType> left_in, right_in, left_post, right_post; //总之分一下,左右子树咔咔一下准备进递归

    BinaryTreeNode<ElemType> *head = new BinaryTreeNode<ElemType>;

    int postlen = post.size();
    head->data = post[postlen - 1]; //后序遍历末尾为根节点

    int root = 0;
    int inlen = in.size();
    for (int i = 0; i < inlen; i++)
    {
        if (post[postlen - 1] == in[i])
        {
            root = i;
            break;
        }
        else
            continue;
    } //找一下根结点在中序遍历的位置,分左右子树

    //cout << "root = " << root << "in[root] = " << in[root] << endl;

    for (int i = 0; i < root; i++)
    {
        left_in.push_back(in[i]);     //中序遍历,根结点之前全是左子树
        left_post.push_back(post[i]); //后序遍历,往后读取相同数量丢入左子树
    }

    //for (int i = 0; i < root; i++)
    //{
    //    cout << "left_in:" << endl;
    //    cout << left_in[i] << " ";
    //}
    ///cout << endl;

    //for (int i = 0; i < root; i++)
    //{
    //    cout << "left_post:" << endl;
    //    cout << left_post[i] << " ";
    //}
    //cout << endl;

    for (int i = root + 1; i < inlen; i++)
    {
        right_in.push_back(in[i]);         //中序遍历,根节点之后全是右子树
        right_post.push_back(post[i - 1]); //后序遍历,挨着上个循环结尾往后读取相同数量丢入左子树
    }

    //for (int i = 0; i < right_in.size(); i++)
    //{
    //    cout << "right_in:" << endl;
    //    cout << right_in[i] << " ";
    //}
    //cout << endl;

    //for (int i = 0; i < right_post.size(); i++)
    //{
    //    cout << "right_post:" << endl;
    //    cout << right_post[i] << " ";
    //}
    //cout << endl;

    head->left = reConstructCore_In_Post(left_in, left_post);
    head->right = reConstructCore_In_Post(right_in, right_post);

    return head;
}

int main()
{
    char flag;
    cin >> flag;
    getchar();

    if (flag == '0')
    {
        string linepre;
        vector<string> pre;
        getline(cin, linepre);

        cinin(linepre, pre);

        vector<string> in;
        string linein;
        getline(cin, linein);

        cinin(linein, in);

        BinaryTreeNode<string> *root = new BinaryTreeNode<string>;
        root = reConstructCore_Pre_In(pre, in);
        visit3(root);
    }

    else if (flag == '1')
    {
        string linein;
        vector<string> in;
        getline(cin, linein);

        cinin(linein, in);

        string linepost;
        vector<string> post;
        getline(cin, linepost);

        cinin(linepost, post);

        BinaryTreeNode<string> *root = new BinaryTreeNode<string>;
        root = reConstructCore_In_Post(in, post);
        visit1(root);
    }

    getchar();
    getchar();
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨骅麟(Patrick Young)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值