给定中序遍历和另外一种遍历方法确定一棵二叉树

本文介绍了如何根据中序遍历和另一种遍历(前序或后序)来唯一确定一棵二叉树。详细解析了利用根节点在中序遍历中的位置来划分左右子树,并给出了递归实现的代码示例。同时,讨论了从已知前序和中序遍历结果推导后序遍历结果的方法。
摘要由CSDN通过智能技术生成

 给定中序遍历和另外一种遍历方法,可以得到一棵二叉树;原因是中序遍历的根节点可以把左右节点分成两半;而其他遍历方法都是给出子树头结点,不能把左右子树分开;因此另外三种遍历方法,任意给出两种遍历方法或者三种遍历方法一起都不能确定一棵二叉树;

    1)给出中序遍历和前序遍历确定一棵二叉树:
    假定前序遍历区间:[preL,preR];中序遍历:[midL,midR];
    k为中序遍历的二叉树的根节点;那么不难得知:
     左子树的个数:numl=k-midL;
        前序遍历的左子树区间:[preL+1,preL+numl],中序遍历的左子树区间:[midL,midL+numl-1];
        前序遍历的右子树区间:[preL+numl+1,preR],中序遍历的右子树区间:[mid+numl+1,midR];

/**
    给定中序遍历和另外一种遍历方法,可以得到一棵二叉树;
    原因是中序遍历的根节点可以把左右节点分成两半;而其他遍历方法都是给出子树头结点,不能把左右子树
    分开;因此另外三种遍历方法,任意给出两种遍历方法或者三种遍历方法一起都不能确定一棵二叉树;
*/

/**
    1)给出中序遍历和前序遍历确定一棵二叉树:
    假定前序遍历区间:[preL,preR];中序遍历:[midL,midR];
    k为中序遍历的二叉树的根节点;那么不难得知:
     左子树的个数:numl=k-midL;
        前序遍历的左子树区间:[preL+1,preL+numl],中序遍历的左子树区间:[midL,midL+numl-1];
        前序遍历的右子树区间:[preL+numl+1,preR],中序遍历的右子树区间:[mid+numl+1,midR];
    data:
    7
    4 1 3 2 6 5 7
    1 2 3 4 5 6 7
*/

/**
#include <iostream>

using namespace std;

typedef struct TNode* BinTree;
struct TNode
{
    int data;
    BinTree lchild,rchild;
    TNode()
    {
        lchild=rchild=NULL;
    }
};
BinTree CreateTree_with_Pre_and_Mid(int preL,int preR,int midL,int midR);
void BehTraver(BinTree BT);

const int maxn=20;
int pre[maxn],mid[maxn];
int main()
{
    int n;
    cout << "输入树的结点数目:\n";
    cin >> n;
    cout << "输入前序遍历数据\n";
    for(int i=0;i<n;++i)
        cin >> pre[i];
    cout << "输入中序遍历数据:\n";
    for(int i=0;i<n;++i)
        cin >> mid[i];
    BinTree BT=CreateTree_with_Pre_and_Mid(0,n-1,0,n-1);
    BehTraver(BT);
    return 0;
}

BinTree CreateTree_with_Pre_and_Mid(int preL,int preR,int midL,int midR)
{
    if(preL>preR)
        return NULL;
    BinTree BT=new TNode;
    BT->data=pre[preL];
    int k;
    for(k=midL;k<=midR;++k)
    {
        if(mid[k]==pre[preL])
            break;
    }
    int numl=k-midL;
    BT->lchild=CreateTree_with_Pre_and_Mid(preL+1,preL+numl,midL,midL+numl-1);
    BT->rchild=CreateTree_with_Pre_and_Mid(preL+numl+1,preR,midL+numl+1,midR);
    return BT;
}

void BehTraver(BinTree BT)
{
    if(BT)
    {
        BehTraver(BT->lchild);
        BehTraver(BT->rchild);
        printf("%d ",BT->data);
    }
}
*/

 

知道前序遍历结果和中序遍历结果,得到后序遍历结果;
    用数组表示后序遍历结果:(浙大代码讲解)

/**
    知道前序遍历结果和中序遍历结果,得到后序遍历结果;
    用数组表示后序遍历结果:(浙大代码讲解)
*/

#include <iostream>
#include <string>
#include <stack>

using namespace std;

const int maxn=35;
int pre[maxn],mid[maxn],beh[maxn],prenum=0,midnum=0;
int n;
bool flag=0;

void Read_data();  //读入数据
//用前序遍历结果和中序遍历结果,得到后序遍历结果;
void create_tree_with_pre_and_mid(int preL,int midL,int behL,int num);


int main()
{
    Read_data();
    create_tree_with_pre_and_mid(1,1,1,n);
    for(int i=1;i<=n;++i)
    {
        if(i!=1)
            cout << ' ';
        cout << beh[i];
    }
    return 0;
}

void Read_data()
{
    cin >> n;
    stack<int> st;
    for(int i=-n;i<n;++i)
    {
        string str;
        cin >> str;
        if(str=="Push")
        {
            int index;
            cin >> index;
            st.push(index);
            pre[++prenum]=index;
        }
        else
        {
            int top=st.top();
            st.pop();
            mid[++midnum]=top;
        }
    }
}

void create_tree_with_pre_and_mid(int preL,int midL,int behL,int num)
{
    if(num==0)  //递归边界
        return;
    if(num==1)
    {
        beh[behL]=pre[preL];
        return ;
    }

    int root=pre[preL],index;
    beh[behL+num-1]=root;  //要将根节点存在beh数组里;每次都是以根结点为分界点,进行左右子树递归
    for(index=0;index<=n;++index)
        if(mid[midL+index]==root)
            break;
    int numL=index, numR=num-index-1;
    create_tree_with_pre_and_mid(preL+1,midL,behL,numL);
    create_tree_with_pre_and_mid(preL+numL+1,midL+numL+1,behL+numL,numR);
}

 

2)给出中序遍历和后序遍历确定一棵二叉树:
    假定后序遍历区间:[behL,behR];中序遍历:[midL,midR];
    k为中序遍历的二叉树的根节点;那么不难得知:
     右子树的个数:numr=midR-k;
      后序遍历的左子树区间:[behL,behR-numr-1],中序遍历的左子树区间:[midL,midR-numr-1];
     后序遍历的右子树区间:[behR-numr,behR-1],中序遍历的右子树区间:[midR-numr+1,midR];

/**
    2)给出中序遍历和后序遍历确定一棵二叉树:
    假定后序遍历区间:[behL,behR];中序遍历:[midL,midR];
    k为中序遍历的二叉树的根节点;那么不难得知:
     右子树的个数:numr=midR-k;
        后序遍历的左子树区间:[behL,behR-numr-1],中序遍历的左子树区间:[midL,midR-numr-1];
        后序遍历的右子树区间:[behR-numr,behR-1],中序遍历的右子树区间:[midR-numr+1,midR];

    data:
    7
    2 3 1 5 7 6 4
    1 2 3 4 5 6 7
*/

#include <iostream>

using namespace std;

typedef struct TNode* BinTree;
struct TNode
{
    int data;
    BinTree lchild,rchild;
    TNode()
    {
        lchild=rchild=NULL;
    }
};
BinTree CreateTree_with_Beh_and_Mid(int behL,int behR,int midL,int midR);
void PreTraver(BinTree BT);

const int maxn=20;
int beh[maxn],mid[maxn];
int main()
{
    int n;
    cout << "输入树的结点数目:\n";
    cin >> n;
    cout << "输入后序遍历数据\n";
    for(int i=0;i<n;++i)
        cin >> beh[i];
    cout << "输入中序遍历数据:\n";
    for(int i=0;i<n;++i)
        cin >> mid[i];
    BinTree BT=CreateTree_with_Beh_and_Mid(0,n-1,0,n-1);
    PreTraver(BT);
    return 0;
}

BinTree CreateTree_with_Beh_and_Mid(int behL,int behR,int midL,int midR)
{
    if(behL>behR)
        return NULL;
    BinTree BT=new TNode;
    BT->data=beh[behR];
    int k;
    for(k=midL;k<=midR;++k)
    {
        if(mid[k]==beh[behR])
            break;
    }
    int numr=midR-k;
    BT->lchild=CreateTree_with_Beh_and_Mid(behL,behR-numr-1,midL,midR-numr-1);
    BT->rchild=CreateTree_with_Beh_and_Mid(behR-numr,behR-1,midR-numr+1,midR);
    return BT;
}

void PreTraver(BinTree BT)
{
    if(BT)
    {
        printf("%d ",BT->data);
        PreTraver(BT->lchild);
        PreTraver(BT->rchild);
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值