二叉树遍历及C语言实现

二叉树遍历及C语言实现

已知中序和前序序列,或者已知中序和后序序列,都能够构造一棵二叉树。在本例中,本人用C语言写程序解答了下面两个算法题:

1)给出一棵二叉树的中序与后序遍历序列,求出它的先序遍历序列。

2)给出一棵二叉树的中序与先序遍历序列,求出它的后序遍历序列。

知识点扼要回顾:
所谓二叉树的遍历,是指按一定的顺序对二叉树中的每个结点均访问一次,且仅访问一。按照根结点访问位置的不同,通常把二叉树的遍历分为六种:
TLR(根左右), TRL(根右左), LTR(左根右)
RTL(右根左), LRT(左右根), RLT(右左根)

其中,TRLRTLRLT三种顺序在左右子树之间均是先右子树后左子树,这与人们先左后右的习惯不同,因此,往往不予采用。余下的三种顺序TLRLTRLRT根据根访问的位置不同分别被称为前序遍历、中序遍历和后序遍历。

前序遍历的规律是:输出根结点,输出左子树,输出右子树; 
中序遍历的规律是:输出左子树,输出根结点,输出右子树;
后序遍历的规律是:输出左子树,输出右子树,输出根结点;

不多说了,看代码吧:)

#include <iostream>  
#include <string>  
 
using namespace std;  
 
//存储节点数据,为简便起见,这里选用字符  
typedef char   DATA_TYPE;  
 
typedef struct tagBINARY_TREE_NODE  BINARY_TREE_NODE, *LPBINARY_TREE_NODE;  
 
struct tagBINARY_TREE_NODE  
{  
      DATA_TYPE             data;           //节点数据  
      LPBINARY_TREE_NODE    pLeftChild;     //左孩子指针  
      LPBINARY_TREE_NODE    pRightChild;    //右孩子指针  
};  
 
//  
//函数名称:TreeFromMidPost  
//函数功能:给出一棵二叉树的中序与后序序列,构造这棵二叉树。   
//输入参数:LPBINARY_TREE_NODE & lpNode:二叉树的结点   
//          string mid:存储了二叉树的中序序列的字符串   
//          string post:存储了二叉树的后序序列的字符串   
//          int lm, int rm:二叉树的中序序列在数组mid中的左右边界   
//          int lp, int rp:二叉树的后序序列在数组post中的左右边界  
//  
void TreeFromMidPost(LPBINARY_TREE_NODE & lpNode, string mid, string post, int lm, int rm, int lp, int rp)  
{  
    //构造二叉树结点  
    lpNode = new BINARY_TREE_NODE;  
    lpNode->data = post[rp];  
    lpNode->pLeftChild = NULL;  
    lpNode->pRightChild = NULL;  
 
    int pos = lm;  
 
    while (mid[pos] != post[rp])  
    {  
        pos++;  
    }  
    int iLeftChildLen = pos - lm;  
 
    if (pos > lm)//有左孩子,递归构造左子树  
    {  
        TreeFromMidPost(lpNode->pLeftChild, mid, post, lm, pos - 1, lp, lp + iLeftChildLen - 1);  
    }  
 
    if (pos < rm)//有右孩子,递归构造右子树  
    {  
        TreeFromMidPost(lpNode->pRightChild, mid, post, pos + 1, rm, lp + iLeftChildLen, rp - 1);  
    }  
}  
 
//  
//函数名称:TreeFromMidPre  
//函数功能:给出一棵二叉树的先序与中序序列,构造这棵二叉树。   
//输入参数: BINARY_TREE_NODE & lpNode:二叉树的结点  
//          string mid:存储了二叉树的中序序列的字符串   
//          string pre:存储了二叉树的先序序列的字符串   
//          int lm, int rm:二叉树的中序序列在数组mid中的左右边界   
//          int lp, int rp:二叉树的先序序列在数组pre中的左右边界  
//  
void TreeFromMidPre(LPBINARY_TREE_NODE & lpNode, string mid, string pre, int lm, int rm, int lp, int rp)  
{  
    //构造二叉树结点  
    lpNode = new BINARY_TREE_NODE;  
    lpNode->data = pre[lp];  
    lpNode->pLeftChild = NULL;  
    lpNode->pRightChild = NULL;  
 
    int pos = lm;  
 
    while (mid[pos] != pre[lp])  
    {  
        pos++;  
    }  
    int iLeftChildLen = pos - lm;  
 
    if (pos > lm)//有左孩子,递归构造左子树  
    {  
        TreeFromMidPre(lpNode->pLeftChild, mid, pre, lm, pos - 1, lp + 1, lp + iLeftChildLen);  
    }  
 
    if (pos < rm)//有右孩子,递归构造右子树  
    {  
        TreeFromMidPre(lpNode->pRightChild, mid, pre, pos + 1, rm, lp + iLeftChildLen + 1, rp);  
    }  
}  
 
//先序遍历  
void PreOrder(LPBINARY_TREE_NODE p)  
{  
       if(p != NULL)  
       {  
              cout << p->data;          //输出该结点  
              PreOrder(p->pLeftChild);  //遍历左子树   
              PreOrder(p->pRightChild); //遍历右子树  
       }  
}  
 
//中序遍历  
void MidOrder(LPBINARY_TREE_NODE p)  
{  
       if(p != NULL)  
       {  
              MidOrder(p->pLeftChild);   //遍历左子树   
              cout << p->data;           //输出该结点  
              MidOrder(p->pRightChild);  //遍历右子树  
       }  
}  
 
//后序遍历  
void PostOrder(LPBINARY_TREE_NODE p)  
{  
       if(p != NULL)  
       {  
              PostOrder(p->pLeftChild);  //遍历左子树   
              PostOrder(p->pRightChild); //遍历右子树  
              cout << p->data;           //输出该结点  
       }  
}  
 
//释放二叉树  
void Release(LPBINARY_TREE_NODE lpNode)  
{  
    if(lpNode != NULL)  
    {  
        Release(lpNode->pLeftChild);  
        Release(lpNode->pRightChild);  
        delete lpNode;  
        lpNode = NULL;  
    }  
}  
 
 
int main(int argc, char* argv[])  
{  
    string              pre;            //存储先序序列  
    string              mid;            //存储中序序列  
    string              post;           //存储后序序列  
 
    LPBINARY_TREE_NODE  lpRoot;         //二叉树根节点指针  
 
 
    cout<<"程序1已知二叉树的中序与后序序列,求先序序列"<<endl;  
    cout<<"请先输入中序序列,回车后输入后序序列:"<<endl;  
 
    cin >> mid;  
    cin >> post;  
 
    TreeFromMidPost(lpRoot, mid, post, 0, mid.size()-1, 0, post.size()-1);  
    cout<<"先序遍历结果:";  
    PreOrder(lpRoot);  
    cout<<endl;  
 
    cout<<"中序遍历结果:";  
    MidOrder(lpRoot);  
    cout<<endl;  
 
    cout<<"后序遍历结果:";  
    PostOrder(lpRoot);  
    cout<<endl;  
    Release(lpRoot);  
    cout<<endl;  
 
    cout<<"程序2已知二叉树的中序与先序序列,求后序序列"<<endl;  
    cout<<"请先输入先序序列,回车后输入中序序列:"<<endl;  
    cin >> pre;  
    cin >> mid;  
 
    TreeFromMidPre(lpRoot, mid, pre, 0, mid.size()-1, 0, pre.size()-1);  
    cout<<"先序遍历结果:";  
    PreOrder(lpRoot);  
    cout<<endl;  
 
    cout<<"中序遍历结果:";  
    MidOrder(lpRoot);  
    cout<<endl;  
 
    cout<<"后序遍历结果:";  
    PostOrder(lpRoot);  
    cout<<endl;  
    Release(lpRoot);  
    cout<<endl;  
 
 
    system("pause");  
    return 0;  

#include <iostream>
#include <string>

using namespace std;

//存储节点数据,为简便起见,这里选用字符
typedef char   DATA_TYPE;

typedef struct tagBINARY_TREE_NODE  BINARY_TREE_NODE, *LPBINARY_TREE_NODE;

struct tagBINARY_TREE_NODE
{
      DATA_TYPE    data;           //节点数据
      LPBINARY_TREE_NODE pLeftChild;     //左孩子指针
   LPBINARY_TREE_NODE pRightChild;    //右孩子指针
};

//
//函数名称:TreeFromMidPost
//函数功能:给出一棵二叉树的中序与后序序列,构造这棵二叉树。
//输入参数:LPBINARY_TREE_NODE & lpNode:二叉树的结点
//          string mid:存储了二叉树的中序序列的字符串
//          string post:存储了二叉树的后序序列的字符串
//          int lm, int rm:二叉树的中序序列在数组mid中的左右边界
//          int lp, int rp:二叉树的后序序列在数组post中的左右边界
//
void TreeFromMidPost(LPBINARY_TREE_NODE & lpNode, string mid, string post, int lm, int rm, int lp, int rp)
{
 //构造二叉树结点
    lpNode = new BINARY_TREE_NODE;
    lpNode->data = post[rp];
    lpNode->pLeftChild = NULL;
 lpNode->pRightChild = NULL;

    int pos = lm;

    while (mid[pos] != post[rp])
 {
        pos++;
 }
    int iLeftChildLen = pos - lm;

    if (pos > lm)//有左孩子,递归构造左子树
 {
        TreeFromMidPost(lpNode->pLeftChild, mid, post, lm, pos - 1, lp, lp + iLeftChildLen - 1);
 }

    if (pos < rm)//有右孩子,递归构造右子树
 {
        TreeFromMidPost(lpNode->pRightChild, mid, post, pos + 1, rm, lp + iLeftChildLen, rp - 1);
 }
}

//
//函数名称:TreeFromMidPre
//函数功能:给出一棵二叉树的先序与中序序列,构造这棵二叉树。
//输入参数: BINARY_TREE_NODE & lpNode:二叉树的结点
//          string mid:存储了二叉树的中序序列的字符串
//          string pre:存储了二叉树的先序序列的字符串
//          int lm, int rm:二叉树的中序序列在数组mid中的左右边界
//          int lp, int rp:二叉树的先序序列在数组pre中的左右边界
//
void TreeFromMidPre(LPBINARY_TREE_NODE & lpNode, string mid, string pre, int lm, int rm, int lp, int rp)
{
 //构造二叉树结点
    lpNode = new BINARY_TREE_NODE;
    lpNode->data = pre[lp];
    lpNode->pLeftChild = NULL;
 lpNode->pRightChild = NULL;

    int pos = lm;

    while (mid[pos] != pre[lp])
 {
        pos++;
 }
    int iLeftChildLen = pos - lm;

    if (pos > lm)//有左孩子,递归构造左子树
 {
        TreeFromMidPre(lpNode->pLeftChild, mid, pre, lm, pos - 1, lp + 1, lp + iLeftChildLen);
 }

    if (pos < rm)//有右孩子,递归构造右子树
 {
        TreeFromMidPre(lpNode->pRightChild, mid, pre, pos + 1, rm, lp + iLeftChildLen + 1, rp);
 }
}

//先序遍历
void PreOrder(LPBINARY_TREE_NODE p)
{
       if(p != NULL)
       {
              cout << p->data;          //输出该结点
              PreOrder(p->pLeftChild);  //遍历左子树
              PreOrder(p->pRightChild); //遍历右子树
       }
}

//中序遍历
void MidOrder(LPBINARY_TREE_NODE p)
{
       if(p != NULL)
       {
              MidOrder(p->pLeftChild);   //遍历左子树
     cout << p->data;           //输出该结点
              MidOrder(p->pRightChild);  //遍历右子树
       }
}

//后序遍历
void PostOrder(LPBINARY_TREE_NODE p)
{
       if(p != NULL)
       {
              PostOrder(p->pLeftChild);  //遍历左子树
              PostOrder(p->pRightChild); //遍历右子树
     cout << p->data;           //输出该结点
       }
}

//释放二叉树
void Release(LPBINARY_TREE_NODE lpNode)
{
 if(lpNode != NULL)
 {
  Release(lpNode->pLeftChild);
  Release(lpNode->pRightChild);
  delete lpNode;
  lpNode = NULL;
 }
}


int main(int argc, char* argv[])
{
 string    pre;            //存储先序序列
    string    mid;            //存储中序序列
 string    post;           //存储后序序列

    LPBINARY_TREE_NODE lpRoot;         //二叉树根节点指针


 cout<<"程序1已知二叉树的中序与后序序列,求先序序列"<<endl;
 cout<<"请先输入中序序列,回车后输入后序序列:"<<endl;

 cin >> mid;
 cin >> post;

 TreeFromMidPost(lpRoot, mid, post, 0, mid.size()-1, 0, post.size()-1);
 cout<<"先序遍历结果:";
 PreOrder(lpRoot);
 cout<<endl;

 cout<<"中序遍历结果:";
 MidOrder(lpRoot);
 cout<<endl;

 cout<<"后序遍历结果:";
 PostOrder(lpRoot);
 cout<<endl;
 Release(lpRoot);
 cout<<endl;

 cout<<"程序2已知二叉树的中序与先序序列,求后序序列"<<endl;
 cout<<"请先输入先序序列,回车后输入中序序列:"<<endl;
 cin >> pre;
 cin >> mid;

 TreeFromMidPre(lpRoot, mid, pre, 0, mid.size()-1, 0, pre.size()-1);
 cout<<"先序遍历结果:";
 PreOrder(lpRoot);
 cout<<endl;

 cout<<"中序遍历结果:";
 MidOrder(lpRoot);
 cout<<endl;

 cout<<"后序遍历结果:";
 PostOrder(lpRoot);
 cout<<endl;
 Release(lpRoot);
 cout<<endl;


    system("pause");
    return 0;
}


1)程序1的输入方式:
已知二叉树的中序与后序序列,求先序序列,请先输入中序序列,回车后输入后序序列:
例如输入:
DGBAECHF
GDBEHFCA
输出:
先序遍历结果:ABDGCEFH
中序遍历结果:DGBAECHF
后序遍历结果:GDBEHFCA

2)程序2的输入方式:
已知二叉树的先序与中序序列,求后序序列,请先输入先序序列,回车后输入中序序列:
例如输入:
abdefgc
debgfac
输出:
先序遍历结果:abdefgc
中序遍历结果:debgfac
后序遍历结果:edgfbca

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值