03-树3 Tree Traversals Again

    技术2026-01-19  9

    测试了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(" "); } } }

    )

    Processed: 0.030, SQL: 9