03-树3 Tree Traversals Again

在这里插入图片描述

测试了30个元素的斜二叉树结果是对的,但是oj仍然有问题
在这里插入图片描述在这里插入图片描述

希望有大佬能够解答!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MaxSize 30
#define Null -1

/**
入栈顺序即先序遍历顺序,出栈顺序即中序遍历顺序

已知先序遍历和中序遍历求后续遍历:
    1 先+中 得到树的结构
    2 后续遍历树

注意,可以不用得出树的结构数组再得到后序遍历:
    根据递归,每次根节点为后序遍历数组(最后)的元素
    右子树根节点要比左子树根节点更靠后

先+中 得到树结构:
    由 先 中 可得到 (子)树根节点 以及左右子树
    接着递归左右子树的 先 中 即可
*/

typedef struct TreeNode {
    int data;
    int left;
    int right;
} TNode;

int pre[MaxSize], in[MaxSize];

TNode T[MaxSize]; //存放树结点的结构数组

void BulidTree(int prel, int inl, int N, int Root);

void PostOrderTraversal(int Root);

int main() {
    int N;
    scanf("%d\n",&N);

    char operation[5];
    char *Push="Push";

    int stack[MaxSize];
    int top=-1;

    int num;
    int prel, inl, postl;
    prel=inl=postl=0;

    for(int i=0; i<2*N; i++) {
        scanf("%s",operation);
        if(strncmp(operation,Push,2)==0) {
            scanf("%d",&num);
            stack[++top]=num;
            pre[prel++]=num;
        } else {
            num=stack[top--];
            in[inl++]=num;
        }
    }

    int Root=0;
    //按照先序遍历的顺序将树的结构数组中data部分赋值,指针都初始化为Null
    for(int i=0; i<N; i++) {
        T[i].data=pre[i];
        T[i].left=Null;
        T[i].right=Null;
    }

//        printf("---------------------------------\n");
//    for(int i=0; i<N; i++) {
//        printf("%d %d %d\n",T[i].data,T[i].left,T[i].right);
//    }
//        printf("---------------------------------\n");
//    for(int i=0; i<N; i++) {
//        printf("%d\n",pre[i]);
//    }
//        printf("---------------------------------\n");
//    for(int i=0; i<N; i++) {
//        printf("%d\n",in[i]);
//    }


    //还原树的结构,需要递归求解
    prel=inl=postl=0;
    BulidTree(prel, inl, N, Root);

//    printf("---------------------------------\n");
//    for(int i=0; i<N; i++) {
//        printf("%d %d %d\n",T[i].data,T[i].left,T[i].right);
//    }

    //后序遍历
    PostOrderTraversal(Root);

    return 0;
}

void BulidTree(int prel, int inl, int N, int Root) {
    if(N==0) {
        return;
    }

    int L=0; //分开左子树,左子树的元素个数
    int R=0; //分开右子树,右子树的元素个数


    int i;
    for(i=inl; i<N; i++) {
        if(pre[prel]==in[i]) //此时in[i]为(子)树的根节点
            break;
        L++; //L为左子树的元素个数
    }

    R=N-L-1; //R为右子树元素个数

    //判断左右子树的根节点与pre[prel]的位置关系
    if(L!=0) {
        T[Root].left=prel+1;  //先序遍历左子树部分的根节点即根的左孩子
    }
    if(R!=0) {
        T[Root].right=prel+L+1; //先序遍历右子树部分的根节点即根的右孩子
    }

    /**
    难点在于如何递归:
        根据先序,中序能够划分左右子树,
        因此,递归左子树与右子树即可
                  先序起始      中序起始  子树元素个数  子树根下标
        左子树   pre+1(L!=0)       i-L         L           pre+1(L!=0)
        右子树   pre+L+1(R!=0)     i+1         R           pre+L+1(R!=0)
    */
    if(L!=0)
        BulidTree(prel+1, i-L, L, prel+1); //递归左子树
    if(R!=0)
        BulidTree(prel+L+1, i+1, R, prel+L+1); //递归右子树

    return;
}

void PostOrderTraversal(int Root) {
    if(Root!=Null) {
        PostOrderTraversal(T[Root].left);
        PostOrderTraversal(T[Root].right);
        printf("%d",T[Root].data);
        if(Root!=0) { //后续遍历最后一个肯定是T[0]
            printf(" ");
        }
    }
}

在这里插入图片描述)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值