L2-011. 玩转二叉树
给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。(我的分析:无非就是说把左子树当成右子树,把右子树当成左子树;没啥多的影响,就是输出的时候先左后右即可了)!这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N(<=30)(分析:假设它是一棵斜二叉树,它的深度上限将达到1e9! 数组是会炸的!),是二叉树中结点的个数。第二行给出其中序遍历序列。第三行给出其前序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树反转后的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:7 1 2 3 4 5 6 7 4 1 3 2 6 5 7输出样例:
4 6 1 7 5 3 2
大致思路:
1、先根据中序(左根右)和前序(根左右)来建树;
2.然后BFS层序遍历时,按照镜像原则——反着先右子树后左子树。
3.这题的数据真的严格,假设是一棵深度为30的二叉树,大约需要1000000000的数组大小来开! 试了几个都段错误了!在网上看了很多题解,大多都是用链表来写的!而我比较懒,又恰巧想到了一个真的简单的方法,于是乎就用数组进行实现了,并且就开到了100大!于是动手就实现了!
AC代码:
//注意,头文件私奔了!!!自行找回! #define inf 0x3f3f3f3f using namespace std; #define N 108 struct node{ int data; int l,r; }tree[N];//用Time方式来依次记录建立的节点的序号! int Time; vector<int>ans; void build_tree(int root,vector<int>a,vector<int>b){//a前序b中序 if(a.size()==0)return ;//递归调用结束的条件! int p=0; for(int i=0;i<(int)b.size();i++){ if(b[i]==a[0]){ p=i;break;//在中序b中的找当前根节点的下标 } } vector<int>al,ar,bl,br; for(int i=1;i<=p;i++) al.push_back(a[i]); for(int i=p+1;i<=(int)a.size()-1;i++) ar.push_back(a[i]); for(int i=0;i<=p-1;i++) bl.push_back(b[i]); for(int i=p+1;i<=(int)b.size()-1;i++) br.push_back(b[i]); tree[root].data=a[0];//确定根节点(立即存储),然后递归处理 tree[root].l=++Time; tree[root].r=++Time; build_tree(tree[root].l,al,bl); build_tree(tree[root].r,ar,br); } void bfs(){//层序遍历 queue<node>Q; Q.push(tree[1]); node now; while(Q.size()){ now=Q.front();Q.pop(); if(now.data==-1)continue;//到底了! ans.push_back(now.data); Q.push(tree[now.r]);//镜像结构层序遍历时,先右子树后左子树 Q.push(tree[now.l]); } } int main(){ int x; int n; vector<int>a,b; while(scanf("%d",&n)!=EOF){ a.clear();b.clear(); for(int i=1;i<=n;i++){ scanf("%d",&x);b.push_back(x); } for(int i=1;i<=n;i++){ scanf("%d",&x);a.push_back(x); } for(int i=0;i<N;i++) tree[i].data=-1; Time=0; build_tree(++Time,a,b); ans.clear();//存结果 bfs(); for(int i=0;i<=n-2;i++) printf("%d ",ans[i]); printf("%d ",ans[n-1]); } return 0; }