您的位置:首页 > 其它

已知前序和中序、后序和中序建立二叉树

2015-04-12 23:38 274 查看
首先明确先序遍历的顺序为:根结点→左结点→右结点;中序遍历的顺序为:左结点→根结点→右结点;后序遍历的顺序为:左结点→右结点→根结点。

1. 给定先序和中序建立二叉树。

1) 函数原型:

void CreateByPreAndIn(BinaryTree &T,charpreorder[],char inorder[],int first,int last)

2) 参数说明:

T是当前要建立的二叉树结点;

preorder是先序遍历的数组;inorder是中序遍历的数组;

first是以T为根结点的树中所有元素在inorder数组的最左下标,last是最右下标

3) 算法描述:

由于二叉树是递归定义的,遍历也是递归进行的,因此,递归建树比较方便。

假设当前要建立的二叉树的根结点在preorder中的下标为index(对整棵树而言index=0),当前要建立的二叉树在inorder中的范围为[first,last](对整棵树而言,自然就是[0,strlen(inorder)-1]),当前根结点在inorder中的下标为loc。

对当前要建立的二叉树结点T(当前树的根结点):

若first>last:该结点不存在,即T=NULL;

若first==last:该结点存在,分配内存,T->data=preorder[index],但是该结点没有左右子结点,即T->leftchild=T->rightchild=NULL,继续向下建立下一个结点,即index++;

若first<last:该结点存在且左右子结点至少存在一个,那么T->data=preorder[index],index++后,由于先序遍历的顺序为:根结点→左结点→右结点,所以下一个首先建立左子结点(相对于结点T而言),然后建立右子结点。由于中序遍历的顺序为:左结点→根结点→右结点,所以inorder中的[first,loc-1]均为T的左子树结点,[loc+1,last]均为T的右子树节点,所以调用 CreateByPreAndIn(T->leftchild,preorder,inorder,first,loc-1)和
CreateByPreAndIn(T->rightchild,preorder,inorder,loc+1,last)建立T的左右子树。

2. 给定后序和中序建立二叉树。

1) 函数原型:

voidCreateByPostAndIn(BinaryTree &T,char postorder[],char inorder[],intfirst,int last)

2) 参数说明:

postorder是先序遍历的数组,其余同上。

3) 算法描述:

基本同上,区别在于上个算法中index从0加到strlen(preorder)-1,当first<last时,建立完结点T后,首先建立左子结点(相对于结点T而言),然后建立右子结点。而本算法由于给定后序,整棵树的根结点在后序遍历的最后,所以index应该从strlen(postorder)-1减到0,当first<last时,建立完结点T后,首先建立的应该是右子结点(相对于结点T而言),然后建立左子结点,这是因为index从大向小递减,而后序遍历为左、右、根,为保持与index同样的顺序,所以应该按照根(T本身)、右、左的顺序来建立二叉树。

3. 注意:给定前序和后序无法求出唯一的二叉树。

举例如下:

树A:有结点1,2,3,2是1的左孩子,3是2的右孩子

树B:有结点1,2,3,2是1的右孩子,3是2的左孩子

则A,B的前序都是123,后序都是321,但A的中序是231,B的中序是132.

/*   数据结构分析与学习专栏
*   Copyright (c) 2015, 山东大学 计算机科学与技术专业 学生
*   All rights reserved.
*   作    者:   高祥
*   完成日期:  2015 年 4 月 12 日
*   版 本 号:017

*任务描述
*   1:给定先序和中序建立二叉树 ;
*   2:给定后序和中序建立二叉树 ;

*主要函数:
*   1.void CreateByPreAndIn(BinaryTree &T,char preorder[],char inorder[],int first,int last);//给定先序和中序建立二叉树
*   2.void CreateByPostAndIn(BinaryTree &T,char postorder[],char inorder[],int first,int last);//给定后序和中序建立二叉树
*   3.void PreOrderTraverse(BinaryTree T);//前序遍历输出二叉树
*   4.void InOrderTraverse(BinaryTree T);//中序遍历输出二叉树
*   5.void PostOrderTraverse(BinaryTree T);//后序遍历输出二叉树
*   6.void print(BinaryTree T);//打印二叉树

*/

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

typedef struct BTNode//二叉树结点类型
{
    char data;
    struct BTNode *leftchild;
    struct BTNode *rightchild;
} BTNode,*BinaryTree;

int index;

void CreateByPreAndIn(BinaryTree &T,char preorder[],char inorder[],int first,int last);//给定先序和中序建立二叉树
void CreateByPostAndIn(BinaryTree &T,char postorder[],char inorder[],int first,int last);//给定后序和中序建立二叉树
void PreOrderTraverse(BinaryTree T);//前序遍历输出二叉树
void InOrderTraverse(BinaryTree T);//中序遍历输出二叉树
void PostOrderTraverse(BinaryTree T);//后序遍历输出二叉树
void print(BinaryTree T);//打印二叉树

int main()
{
    cout<<"第一组测试数据:\n";

    char preorder[]= {'A','B','C','D','E','G','F'};
    char inorder[]= {'C','B','E','G','D','F','A'};
    char postorder[]= {'C','G','E','F','D','B','A'};

    BinaryTree T1;
    index=0;
    cout<<"\n由先序和中序建立二叉树:\n";
    CreateByPreAndIn(T1,preorder,inorder,0,6);
    print(T1);

    BinaryTree T2;
    index=6;
    cout<<"\n由后序和中序建立二叉树:\n";
    CreateByPostAndIn(T2,postorder,inorder,0,6);
    print(T2);

    cout<<"\n\n第二组测试数据:\n";

    char preorder2[]= {'A','B','D','E','F','G','C','H','J','I','K'};
    char inorder2[]= {'D','B','F','G','E','A','H','J','C','I','K'};
    char postorder2[]= {'D','G','F','E','B','J','H','K','I','C','A'};

    BinaryTree T3;
    index=0;
    cout<<"\n由先序和中序建立二叉树:\n";
    CreateByPreAndIn(T3,preorder2,inorder2,0,10);
    print(T3);

    BinaryTree T4;
    index=10;
    cout<<"\n由后序和中序建立二叉树:\n";
    CreateByPostAndIn(T4,postorder2,inorder2,0,10);
    print(T4);

    return 0;
}

void CreateByPreAndIn(BinaryTree &T,char preorder[],char inorder[],int first,int last)
//给定先序和中序建立二叉树
{
    if(first>last)
    {
        T=NULL;
    }

    if(first==last)
    {
        T=(BinaryTree)malloc(sizeof(BTNode));
        T->data=preorder[index];
        T->leftchild=T->rightchild=NULL;

        index++;
    }

    if(first<last)
    {
        int loc;
        for(loc=first; first<=last; loc++)
        {
            if(inorder[loc]==preorder[index])
            {
                break;
            }
        }

        T=(BinaryTree)malloc(sizeof(BTNode));
        T->data=preorder[index];
        index++;

        CreateByPreAndIn(T->leftchild,preorder,inorder,first,loc-1);
        CreateByPreAndIn(T->rightchild,preorder,inorder,loc+1,last);
    }
}

void CreateByPostAndIn(BinaryTree &T,char postorder[],char inorder[],int first,int last)
//给定后序和中序建立二叉树
{
    if(first>last)
    {
        T=NULL;
    }

    if(first==last)
    {
        T=(BinaryTree)malloc(sizeof(BTNode));
        T->data=postorder[index];
        T->leftchild=T->rightchild=NULL;

        index--;
    }

    if(first<last)
    {
        int loc;
        for(loc=first; first<=last; loc++)
        {
            if(inorder[loc]==postorder[index])
            {
                break;
            }
        }

        T=(BinaryTree)malloc(sizeof(BTNode));
        T->data=postorder[index];
        index--;
        CreateByPostAndIn(T->rightchild,postorder,inorder,loc+1,last);
        CreateByPostAndIn(T->leftchild,postorder,inorder,first,loc-1);
    }
}

void PreOrderTraverse(BinaryTree T)//前序遍历输出二叉树
{
    if(T)
    {
        cout<<T->data<<" ";
        PreOrderTraverse(T->leftchild);
        PreOrderTraverse(T->rightchild);
    }
}

void InOrderTraverse(BinaryTree T)//中序遍历输出二叉树
{
    if(T)
    {
        InOrderTraverse(T->leftchild);
        cout<<T->data<<" ";
        InOrderTraverse(T->rightchild);
    }
}

void PostOrderTraverse(BinaryTree T)//后序遍历输出二叉树
{
    if(T)
    {
        PostOrderTraverse(T->leftchild);
        PostOrderTraverse(T->rightchild);
        cout<<T->data<<" ";
    }
}

void print(BinaryTree T)//打印二叉树
{
    cout<<"先序遍历为:\n";
    PreOrderTraverse(T);
    cout<<endl;

    cout<<"中序遍历为:\n";
    InOrderTraverse(T);
    cout<<endl;

    cout<<"后序遍历为:\n";
    PostOrderTraverse(T);
    cout<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐