题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1136
题目描述:给定一个按照(左子树-右子树-根)(即先序)遍历序列的树,求其按照 右子树-左子树-根 遍历的结果。(每个数都不同)
题目思路:按照题目意思其实构造的是一个二叉查找树,满足左子树元素都不大于当前根的元素,右子树元素都不小于当前根的元素。
而且二叉查找树按照 中序遍历 的结果是元素按照递增顺序输出(二叉查找树的性质)。所以实际上又告诉了你中序遍历的结果(即把所给元素递增排序的结果)。
所以只要按照它给的后序遍历和隐含的中序遍历的序列,递归构造并输出就可以了。
如果不熟悉二叉树,这是几篇不错的教程:
http://blog.csdn.net/hinyunsin/article/details/6315502(评论指出了原文中的错误)
http://blog.csdn.net/pegasuswang_/article/details/10169397
http://www.slyar.com/blog/c-preord-inord-tree.html这个版本的代码比较容易理解
本题代码:
#include <iostream> #include <algorithm> #include <cstdio> const int M = 3010; int postord[M], inord[M]; //后序和中序遍历序列 void build(int n, int *postord, int *inord) { if (n <= 0) return; int p = std::find(inord, inord + n, postord[n-1]) - inord; //计算根节点在中序遍历中的位置 build(n - p - 1, postord + p, inord + p + 1); //递归构造右子树的(右-左-根)遍历 build(p, postord, inord); //递归构造左子树的(右-左-根)遍历 printf("%d ", postord[n-1]); //输出根节点 } int main() { int n; scanf("%d", &n); for (int i = 0; i < n; ++i) { scanf("%d", postord + i); inord[i] = postord[i]; } std::sort(inord, inord + n); build(n, postord, inord); return 0; }
几点说明:如果不理解代码,就找简单数据在纸上试试。要不看代码是不容易理解的。
这一题我直接在构造的时候就输出了,比较简练。
int p = std::find(inord, inord + n, postord[n-1]) - inord; //计算根节点在中序遍历中的位置
build(n - p - 1, postord + p, inord + p + 1); //递归构造右子树的遍历
build(p, postord, inord); //递归构造左子树的遍历
printf("%d ", postord[n-1]); //输出根节点
这几句是关键代码:
build(n - p - 1, postord + p, inord + p + 1); //递归构造右子树的遍历
参数n-p-1是 右 子树的结点个数,用来控制递归深度:post+p是新的 右子树 在 后序遍历 中的位置;inord+p+1是新的 右子树 在 中序遍历 中的位置。
build(p, postord, inord); //递归构造左子树的遍历
参数n-p-1是 左 子树的结点个数,用来控制递归深度:post+p是新的 左子树 在 后序遍历 中的位置;inord+p+1是新的 左子树 在 中序遍历 中的位置。
最后输出根节点就行了。
调整三句的位置就可以实现任意六种遍历的次序。
当然也可以先构造,再输出,不过麻烦点。
代码来自/*gaoshangbo*/
//给定后序遍历和中序遍历,求先遍历右子树, 左子树, 根的序列 #include <iostream> #include <stdio.h> #include <algorithm> using namespace std; int s[3005], t[3005]; typedef struct node { int data; node *l; node *r; }node; node *Creat(int *s,int *t,int n) { int *p; node *q; int k; if(n<=0) return NULL; q=new node; q->data=*s; for(p=t;p<t+n;p++) if(*p==*s) break; k=p-t; q->l=Creat(s-n+k,t,k); q->r=Creat(s-1,t+k+1,n-k-1); return q; } void print(node *root) { if(root==NULL) return ; print(root->r); print(root->l); printf("%d ",root->data); } int main() { node *root; int n, i; scanf("%d", &n); for(i = 0; i < n; i ++) { scanf("%d", &s[i]); t[i] = s[i]; } sort(t, t+n); root = Creat(s+n-1,t,n); print(root); printf(" "); return 0; }