• PAT Advanced 1020 Tree Traversals (25) [⼆叉树的遍历,后序中序转层序]


    题目

    Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, you are supposed to output the level order traversal sequence of the corresponding binary tree.
    Input Specification:
    Each input file contains one test case. For each case, the first line gives a positive integer N (<=30), the total number of nodes in the binary tree. The second line gives the postorder sequence and the third line gives the inorder sequence. All the numbers in a line are separated by a space.
    Output Specification:
    For each test case, print in one line the level order traversal sequence of the corresponding binary tree. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.
    Sample Input:
    7
    2 3 1 5 7 6 4 1 2 3 4 5 6 7
    Sample Output:
    4 1 6 3 5 7 2

    题目分析

    已知后序序列和中序序列,打印层序序列

    解题思路

    思路 01

    1. int in[n]记录中序序列,int post[n]记录后序序列
    2. 建树
      2.1 post[n-1]为当前根结点root,在in中序序列中找到当前根结点root的位置i,i左边的元素为root的左子树所有结点,i右边元素为root的右子树所有结点
      2.2 将root左子树所有结点作为后序序列继续查找其root和左右子树节点,将root右子树所有结点作为后序序列继续查找其root和左右子树结点
    3. 层序遍历树

    思路 02(最优)

    1. int in[n]记录中序序列,int post[n]记录后序序列,node结构体中增加index属性记录树使用数组存储时的节点下标
    2. 前序遍历(利用中序和后序序列,依次找出根节点和其左右子树节点),设置其index,若某根节点index=i,则其左子节点index=2*i+1,其右子节点index=2*i+2
    3. 排序:根据index升序对所有结点排序
    4. 打印排序后的所有结点

    思路 03

    思路02中的index换为记录层号,对层号进行排序
    注:不能使用sort,因为sort不稳定,导致同层顺序得不到保证,需要使用stable_sort()

    知识点

    1. 已知中序序列和前序、后序、层序中任意一个序列,可唯一确定一棵二叉树
    2. 后序序列最后一个节点为根节点,该根节点将中序序列一分为二,左边为根节点左子树,右边为根节点右子树
    3. 树的层序遍历(借助队列)
    4. 根据后序序列和中序序列建树
    5. bfs层级遍历时,可以使用数组存储树的特点(即节点存储在下标i,则其左子节点下标为2i+1,右子节点下标为2i+2),之后对下标进行升序排序,遍历即为层序序列;

    Code

    Code 01

    #include <iostream>
    #include <queue>
    using namespace std;
    const int maxn=30;
    int pre[maxn],in[maxn],post[maxn];
    int n; // the number of nodes
    struct node {
    	int data;
    	node* left;
    	node* right;
    };
    /*
     后序序列和中序序列建树 
    */ 
    node * create(int postL,int postR,int inL,int inR) {
    	if(postL>postR)return NULL;
    	node * root=new node;
    	root->data=post[postR];
    	// 找到当前根节点在中序遍历中的位置
    	int i;
    	for(i=inL; i<=inR; i++) {
    		if(post[postR]==in[i])
    			break;
    	}
    	int numLeft=i-inL;
    	root->left=create(postL,postL+numLeft-1,inL,inL+numLeft-1);//inL+numLeft=i
    	root->right=create(postL+numLeft,postR-1,inL+numLeft+1,inR);//inL+numLeft=i
    	return root;
    }
    /*
     树层序遍历
    */
    int num=0;
    void BFS(node * root) {
    	queue<node*> q;
    	q.push(root);
    	while(!q.empty()) {
    		node * now = q.front();
    		q.pop();
    		printf("%d",now->data);
    		num++;
    		if(num<n)printf(" ");
    		if(now->left!=NULL)q.push(now->left);
    		if(now->right!=NULL)q.push(now->right);
    	}
    }
    int main(int argc,char * argv[]) {
    	scanf("%d",&n);
    	for(int i=0; i<n; i++)
    		scanf("%d",&post[i]);
    	for(int i=0; i<n; i++)
    		scanf("%d",&in[i]);
    	node* root=create(0,n-1,0,n-1);
    	BFS(root);
    	return 0;
    }
    

    Code 02(最优)

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int maxn=30;
    int n,in[maxn],post[maxn];
    struct node {
    	int data;
    	int index;
    };
    vector<node> vns;
    bool cmp(node &n1,node &n2){
    	return n1.index<n2.index;
    }
    void pre(int root,int start,int end,int index) {
    	if(start>end)return;
    	vns.push_back({post[root],index});
    	int i;
    	while(i<end&&in[i]!=post[root])i++;
    	pre(root-(end-i)-1,start,i-1,2*index+1);
    	pre(root-1,i+1,end,2*index+2);
    }
    int main(int argc,char *argv[]) {
    	scanf("%d",&n);
    	for(int i=0; i<n; i++)
    		scanf("%d",&post[i]);
    	for(int i=0; i<n; i++)
    		scanf("%d",&in[i]);
    	pre(n-1,0,n-1,0);
    	sort(vns.begin(),vns.end(),cmp);
    	for(int i=0;i<vns.size();i++){
    		if(i!=0)printf(" ");
    		printf("%d",vns[i].data);
    	}
    	return 0;
    }
    

    Code 03

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int maxn=30;
    int n,in[maxn],post[maxn];
    struct node{
    	int d;
    	int l;
    };
    vector<node> pre;
    void t_pre(int pl,int pr,int il,int ir,int level){
    	if(il>ir)return;
    	pre.push_back({post[pr],level});
    	int k=il;
    	while(k<n&&in[k]!=post[pr])k++;
    	t_pre(pl,pl+k-il-1,il,k-1,level+1);
    	t_pre(pl+k-il,pr-1,k+1,ir,level+1);
    }
    bool cmp(const node &a,const node &b){
    	return a.l<b.l; 
    }
    int main(int argc,char * argv[]) {
    	scanf("%d",&n);
    	for(int i=0; i<n; i++)
    		scanf("%d",&post[i]);
    	for(int i=0; i<n; i++)
    		scanf("%d",&in[i]);
    	t_pre(0,n-1,0,n-1,1);
    	stable_sort(pre.begin(),pre.end(),cmp);
    	printf("%d",pre[0]);
    	for(int i=1;i<n;i++)
    		printf(" %d",pre[i].d);
    	return 0;
    }
    
  • 相关阅读:
    echarts onClick执行之前都要取消绑定一次
    echarts 打包完之后体积太大解决方案。
    saga处理多个loading最少0.5s
    SVN命令详解
    netfilter/iptables原理
    交换两个变量的值,不使用第三个变量的四种法方
    linux常用命令整理
    vi技巧
    linux进程管理的常用命令
    gcc常用命令
  • 原文地址:https://www.cnblogs.com/houzm/p/12314101.html
Copyright © 2020-2023  润新知