1020. Tree Traversals

来源:互联网 发布:yum 安装pip 编辑:程序博客网 时间:2024/05/16 01:48

题目

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

基本思路

考察二叉树的建树,前序/中序/后续/层序遍历等基本操作。
1.通过后序序列和中序序列构造二叉树,然后层序遍历输出。层序遍历用BFS实现。需要注意的是,BFS中队列queue存放的是结点地址,即queue<node*> q ,而不是结点queue<node> q 。因为队列中存放的是原元素的一个副本,若队列中存放的是node型,那么当需要修改队首元素时,就无法修改原元素(修改的只是队列中的副本),因此让队列存放元素的地址(即node*型),这样可以通过访问地址去修改原元素。(虽然本题不涉及修改元素,只是简单的输出,但这个细节要重视,不然往后出现问题错哪里都搞不清楚)。

代码
#include<cstdio>#include<queue>using namespace std;const int maxn = 35;struct node{    int data;//数据域     node* lchild;    node* rchild;//指针域 };int in[maxn],post[maxn];//中序序列,后序序列int n;//结点个数 //由中序遍历序列和后续遍历序列建树//后续序列post[postL,postR],中序序列in[inL,inR] node* creat(int postL,int postR,int inL,int inR){    if(postL > postR) return NULL;    node* root = new node;//定义根结点     root->data = post[postR];    int k;    for(k=inL;k<=inR;k++){//确定中序序列中根结点的位置         if(in[k] == post[postR]){            break;        }    }       int numLeft = k - inL;//左子树的结点数     root->lchild = creat(postL,postL+numLeft-1,inL,k-1);//遍历左子树     root->rchild = creat(postL+numLeft,postR-1,k+1,inR);    return root;//返回根结点 } //层序遍历输出,用BFS实现int num = 0;//输出的个数 ,用于控制格式 void BFS(node* root){    queue<node*> q;//定义队列,存放的是结点的位置    q.push(root);//根结点入队     while(!q.empty()){        node* top = q.front();//取出队首元素        q.pop();        printf("%d",top->data);        num++;        if(num < n) printf(" ");//控制格式        if(top->lchild != NULL) q.push(top->lchild);        if(top->rchild != NULL) q.push(top->rchild);     }} int main(){    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 = creat(0,n-1,0,n-1);    BFS(root);    return 0;}
拓展

本题是通过后序序列中序序列构造二叉树,基本思路是:后序序列的最后一个元素为根结点,然后在中序序列中找到该根结点,中序序列左侧即为左子树,右侧即为右子树,然后分别进行递归;若是要通过前序序列中序序列 构造二叉树,原理完全是一样的,只是根结点在前序序列的第一个元素。那么,若要通过中序序列层序序列 构造二叉树呢,思路就有些不同了。分析如下:
1.层序序列的第一个元素是当前树的根结点,然后在中序序列中找到该根结点,根结点左侧即为左子树,右侧为右子树。
2.但是在层序序列中,左(右)子树的结点时分散开的,无法像前序/后序序列那样直接递归。因此,不妨开两个vector<int> layerLeft,layerRight ,每当在中序序列中确定一个根结点时,就遍历当前层序序列的所有结点,把左子树的结点push进layerLeft,右子树的结点push进layerRight,然后可利用layerLeft,layerRight进行递归。

代码
//通过层序遍历和中序遍历构造二叉树,当前层序遍历结点存放在layer,中序遍历序列为[inL,inR] node* creat(vector<int> layer,int inL,int inR){    if(layer.size() == 0) return NULL;    node* root = new node;//新建结点     root->data = layer[0];//根结点的值为层序序列的第一个元素     root->lchild = root->rchild = NULL;     int k;    for(int i=inL;i<=inR;i++){//在中序序列中找到根结点         if(in[i] == layer[0]){            k = i;            break;        }    }    vector<int> layerLeft,layerRight;//左右子树层序遍历的结点     for(int i=1;i<layer.size();i++){//遍历层序序列,找出分别属于左、右子树的结点         bool isLeft = false;        for(int j=inL;j<k;j++){//对于每个层序序列的元素,遍历中序序列的左子树,从而判断该结点是否属于左子树             if(layer[i] == in[j]){                isLeft = true;                break;             }        }         if(isLeft){//如果是左子树的结点            layerLeft.push_back(layer[i]);        }else{            layerRight.push_back(layer[i]);        }    }    root->lchild = creat(layerLeft,inL,k-1);//递归左子树    root->rchild = creat(layerRight,k+1,inR);    return root;//返回根结点地址}
0 0
原创粉丝点击