二叉树遍历--前序+中序生成后序

给定一棵二叉树的前序遍历和中序遍历,求其后序遍历(提示:给定前序遍历与中序遍历能够唯一确定后序遍历)。

输入描述:
两个字符串,其长度n均小于等于26。
第一行为前序遍历,第二行为中序遍历。
二叉树中的结点名称以大写字母表示:A,B,C....最多26个结点。
输出描述:
输入样例可能有多组,对于每组测试样例,
输出一行,为后序遍历的字符串。
如:
输入:
ABC
BAC
FDXEAG
XDEFAG
输出:
BCA
XEDGAF

思路:先序+中序求后序,先序的第一个字符是根root,所以得在中序序列中遍历找出root所在位置,设由中序第一位向前挪i次后找到root,将中序一分为二,root的左子树和右子树,则相应的,前序中也可划分出左子树和右子树,只是现在只知道前序和中序的首地址,所以再加上长度len和挪动的次数就可以在前序,中序中分离出左和右。

#include <iostream>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
using namespace std;

typedef struct Tnode{
    char ch;
    Tnode *lc;
    Tnode *rc;
}Tnode;


Tnode *Create_Tree(Tnode *T,char *pre,char *in,int len){
    T=(Tnode*)malloc(sizeof(Tnode));
    T->lc=T->rc=NULL;//初始化节点,无值;
    if(len<=0){//若剩余长度<=0,停止;否则继续遍历查找
        T=NULL;
    }
    else{

            int i=0;
            while(*(pre)!=*(in+i)&&i<=len){//这里使用指针类型更方便,找出root在中序序列中的位置
                i++;
            }
            T->ch=*pre;
            T->lc=Create_Tree(T->lc,pre+1,in,i);/*这里preoder+1是指前序序列中的首元素已经确定位置了,所以前序序列需向前移动一位,而中序序列还是in是因为它没法指定自己的区间,但是有了长度i就可以了,区间是从0---i-1;所以此处无论是pre 还是in ,都是指向自己的起始地址,借助i可以知道截止地址在哪; */
            T->rc=Create_Tree(T->rc,pre+1+i,in+i+1,len-1-i);

    }
    return T;


}

void PostPrint(Tnode *T){
    if(T){
        PostPrint(T->lc);
        PostPrint(T->rc);
        cout<<T->ch;
    }
}

int main()
{
    char pre[27],in[27];
    while(cin>>pre){
        cin>>in;
        Tnode *T=NULL;
        int len=strlen(pre);
        T=Create_Tree(T,pre,in,len);
        PostPrint(T);
        cout<<endl;
    }
    return 0;
}

NOTE:
难点:递归解决该问题:首先在前序序列中找根root,即前序序列第一个字母,然后在中序序列中找对应的字母,此时root将中序序列分为左根右三部分,保存root,再在左子树中递归,在右子树中递归,直到树的长度小于等于0;所以需要有一个长度变量,不仅提示是否退出递归,而且也容易区分左右子树的遍历区间;
1.由前序和中序序列重新建树时,忘了要写递归截止条件,即当长度<=0时退出递归;
2. char*和char[]的区别----前者表示元素char *ch; (ch)表示第一个字符
3. 主函数中定义前序序列preorder[],中序序列inorder[]为char型数组,直接分配空间,而不是char
型;

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是用 C 语言设计的程序实现任意输入前序+中序序列生成唯一的二叉树,并打印其后序序列的功能: ```c #include <stdio.h> #include <stdlib.h> //定义二叉树结构体 typedef struct TreeNode { char data; //节点数据 struct TreeNode* left; //左孩子指针 struct TreeNode* right; //右孩子指针 } TreeNode; //根据前序中序序列生成二叉树 TreeNode* createTree(char* preorder, char* inorder, int size) { if (size <= 0) { //序列为空 return NULL; } TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode)); //创建根节点 root->data = *preorder; //根节点的值为前序遍历序列的第一个元素 int pos = 0; while (pos < size && inorder[pos] != root->data) { //在中序遍历序列中找到根节点的位置 pos++; } if (pos == size) { //无法找到根节点 printf("Error: Invalid Input!\n"); return NULL; } root->left = createTree(preorder + 1, inorder, pos); //递归构造左子树 root->right = createTree(preorder + pos + 1, inorder + pos + 1, size - pos - 1); //递归构造右子树 return root; } //后序遍历二叉树并打印节点值 void postorder(TreeNode* root) { if (root == NULL) { //树为空 return; } postorder(root->left); //后序遍历左子树 postorder(root->right); //后序遍历右子树 printf("%c ", root->data); //输出当前节点的值 } //主函数 int main() { char preorder[] = {'A', 'B', 'D', 'E', 'C', 'F', 'G'}; //前序遍历序列 char inorder[] = {'D', 'B', 'E', 'A', 'F', 'C', 'G'}; //中序遍历序列 int size = sizeof(preorder) / sizeof(preorder[0]); //序列长度 TreeNode* root = createTree(preorder, inorder, size); //生成二叉树 if (root != NULL) { //二叉树生成成功 printf("Postorder: "); postorder(root); //后序遍历并打印二叉树 printf("\n"); } return 0; } ``` 程序的思路是:根据前序中序遍历序列来构造二叉树,然后后序遍历二叉树并打印节点值。程序中用到了递归的思想,具体解释如下: 1. 定义二叉树结构体 ```c typedef struct TreeNode { char data; //节点数据 struct TreeNode* left; //左孩子指针 struct TreeNode* right; //右孩子指针 } TreeNode; ``` 定义一个包含节点数据、左孩子指针和右孩子指针的结构体,表示二叉树的节点。 2. 根据前序中序序列生成二叉树 ```c TreeNode* createTree(char* preorder, char* inorder, int size) { if (size <= 0) { //序列为空 return NULL; } TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode)); //创建根节点 root->data = *preorder; //根节点的值为前序遍历序列的第一个元素 int pos = 0; while (pos < size && inorder[pos] != root->data) { //在中序遍历序列中找到根节点的位置 pos++; } if (pos == size) { //无法找到根节点 printf("Error: Invalid Input!\n"); return NULL; } root->left = createTree(preorder + 1, inorder, pos); //递归构造左子树 root->right = createTree(preorder + pos + 1, inorder + pos + 1, size - pos - 1); //递归构造右子树 return root; } ``` 在此函数中,首先判断序列是否为空,如果为空则返回 NULL。然后创建一个根节点,并将根节点的值设为前序遍历序列的第一个元素。接着在中序遍历序列中找到根节点的位置,如果无法找到根节点,则输出错误提示并返回 NULL。然后递归构造左子树和右子树,最后返回根节点。 3. 后序遍历二叉树并打印节点值 ```c void postorder(TreeNode* root) { if (root == NULL) { //树为空 return; } postorder(root->left); //后序遍历左子树 postorder(root->right); //后序遍历右子树 printf("%c ", root->data); //输出当前节点的值 } ``` 该函数用于后序遍历二叉树并打印节点值。首先判断树是否为空,如果为空则返回。然后递归后序遍历左子树和右子树,最后打印当前节点的值。 4. 主函数 ```c int main() { char preorder[] = {'A', 'B', 'D', 'E', 'C', 'F', 'G'}; //前序遍历序列 char inorder[] = {'D', 'B', 'E', 'A', 'F', 'C', 'G'}; //中序遍历序列 int size = sizeof(preorder) / sizeof(preorder[0]); //序列长度 TreeNode* root = createTree(preorder, inorder, size); //生成二叉树 if (root != NULL) { //二叉树生成成功 printf("Postorder: "); postorder(root); //后序遍历并打印二叉树 printf("\n"); } return 0; } ``` 在主函数中,定义前序遍历序列和中序遍历序列,计算序列长度,然后调用 createTree 函数生成二叉树,如果二叉树生成成功,则后序遍历并打印二叉树

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值