首页 > 试题广场 >

Tree Traversals (25)

[编程题]Tree Traversals (25)
  • 热度指数:1673 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
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.

输入描述:
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.


输出描述:
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.
示例1

输入

7<br/>2 3 1 5 7 6 4<br/>1 2 3 4 5 6 7

输出

4 1 6 3 5 7 2
先建立二叉树再层次遍历,理解起来比较简单一点

#include<stdio.h>

#include<iostream>

#include<string>

#include<queue>

using namespace std;

struct Node

{

    int data;

    Node *left;

    Node *right;

};


Node* find(int N,int *postorder,int *inorder,int postorderRoot,int inorderfirst,int inorderlast)

{

    //找到这个数再中序中的位置

    if(inorderfirst>inorderlast||inorderfirst<0||inorderlast>N-1)

    {

        return NULL;

    }else if(inorderfirst==inorderlast)

    {

        Node *tmp = new Node();

        tmp->data = inorder[inorderfirst];

        return tmp;

    }

    int inorderIndex = -1;

    for(int i=0;i<N;i++)

    {

        if(postorder[postorderRoot]==inorder[i])

        {

            inorderIndex=i;

            break;

        }

    }

    if(inorderIndex==-1)

        return NULL;

    Node *tmp = new Node();

    tmp->data = postorder[postorderRoot];

    tmp->left = find(N,postorder,inorder,postorderRoot-(inorderlast-inorderIndex+1),inorderfirst,inorderIndex-1);

    tmp->right = find(N,postorder,inorder,postorderRoot-1,inorderIndex+1,inorderlast);

    return tmp;

}




void cengcibianli(Node *root)

{

    queue<Node*> queue;

    queue.push(root);

    bool isFirst = true;

    while(!queue.empty())

    {

        Node *tmp = queue.front();

        if(!isFirst){

            cout<<" ";

        }

        isFirst=false;

        cout<<tmp->data;

        if(tmp->left!=NULL)

            queue.push(tmp->left);

        if(tmp->right!=NULL)

            queue.push(tmp->right);

        queue.pop();

    }

    cout<<endl;

}


int main()

{

    int N;

    scanf("%d",&N);

    int *postorder = new int[N];

    int *inorder = new int[N];

    for(int i=0;i<N;i++)

    {

        scanf("%d",&postorder[i]);

    }

    for(int i=0;i<N;i++)

    {

        scanf("%d",&inorder[i]);

    }


    Node *root = find(N,postorder,inorder,N-1,0,N-1);

    cengcibianli(root);

    return 0;

}


发表于 2018-02-27 21:44:21 回复(0)
如果是后续中序求前序的话,不需要重构二叉树
求层序遍历的话,本人只能想到重构。
如果有更好解法,欢迎讨论

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

/**
 * 1020. Tree Traversals (25)
 * 
 * @author Jacob
 *
 */
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] postorder = new int[n];
        int[] inorder = new int[n];
        for (int i = 0; i < n; i++)
            postorder[i] = sc.nextInt();
        for (int i = 0; i < n; i++)
            inorder[i] = sc.nextInt();

        Node root = rebuild(postorder, 0, n - 1, inorder, 0, n - 1);
        Queue<Node> queue = new LinkedList<Node>();
        queue.offer(root);
        ArrayList<Integer> res = new ArrayList<Integer>();
        while (!queue.isEmpty()) {
            Node node = queue.poll();
            res.add(node.value);
            if (node.left != null)
                queue.offer(node.left);
            if (node.right != null)
                queue.offer(node.right);
        }
        System.out.print(res.get(0));
        for (int i = 1; i < res.size(); i++) {
            System.out.print(" " + res.get(i));
        }
        sc.close();

    }

    private static Node rebuild(int[] postorder, int postLeft, int postRight, int[] inorder, int inLeft, int inRight) {
//        System.out.println("hhhhhhhhhhh:"+postLeft+" "+postRight+" "+inLeft+" "+inRight);
        if (postLeft > postRight)
            return null;
        Node root = new Node(postorder[postRight]);
        int index = 0;
        for (int i = inLeft; i <= inRight; i++) {
            if (inorder[i] == postorder[postRight])
                index = i;
        }
        int leftNum = index - inLeft;

        root.left = rebuild(postorder, postLeft, postLeft + leftNum - 1, inorder, inLeft, index - 1);
        root.right = rebuild(postorder, postLeft + leftNum, postRight - 1, inorder, index + 1, inRight);
        return root;
    }

    /*
     * 构造树节点类
     */
    static class Node {
        public Node(int value) {
            this.value = value;
        }

        int value;
        Node left;
        Node right;
    }
}

发表于 2017-10-16 20:58:44 回复(0)
#include <iostream>
#include <queue>
#include <cmath>
using namespace std;
#define maxn 35
struct node{                                                     //定义树的结点(静态实现)
    int data,lchild,rchild;
}Node[maxn];
int post[maxn],in[maxn],n,num=0;
int create(int inL,int inR,int postL,int postR){
    if(postL>postR) return -1;                                   //若后序序列长度小于等于0
    int root=num++;
    Node[root].data=post[postR];                                 //后序最后一个结点即为根结点
    int mid;
    for(mid=inL;mid<=inR;mid++){                                 //在中序中找到根结点
        if(in[mid]==post[postR]) break;
    }
    Node[root].lchild=create(inL,mid-1,postL,postL+(mid-inL)-1); //返回右子树根结点地址(数组下标)
    Node[root].rchild=create(mid+1,inR,postL+(mid-inL),postR-1);
    return root;
}
void layerOrder(int root){                                       //层次遍历
    queue<int> q;
    q.push(root);
    while(!q.empty()){
        int now=q.front();
        q.pop();
        cout<<Node[now].data;
        if(Node[now].lchild!=-1) q.push(Node[now].lchild);
        if(Node[now].rchild!=-1) q.push(Node[now].rchild);
        if(!q.empty()) cout<<" ";
    }
}
int main(){
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>post[i];
    for(int i=0;i<n;i++)
        cin>>in[i];
    int root=create(0,n-1,0,n-1);                               //构建二叉树并返回根结点地址
    layerOrder(root);
    return 0;
} 

编辑于 2019-01-12 23:52:20 回复(0)
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;

const int maxn = 30;
int in_order[maxn], post_order[maxn];
int n, root, lch[maxn], rch[maxn];	//n为树的结点个数
vector<int> level;

void read_list(int *a){
	int x;
	for(int i=0;i<n;i++){
		cin >> x;
		a[i] = x;
	}
}

//把in_order[L1 ... R1] 和 post_order[L2 ... R2] 建成一棵二叉树
int build(int L1, int R1, int L2, int R2){
	if(L1 > R1) return  0;
	int proot = post_order[R2], pos;
	for(int i=0;i<n;i++){
		if(in_order[i] == proot){
			pos = i;
			break;
		}
	}
	int l_num = pos - L1; //左子树的结点个数
	lch[proot] = build(L1, pos-1, L2, L2+l_num-1);
	rch[proot] = build(pos+1, R1, L2+l_num, R2-1);
	return proot;
}

void level_order(int proot){
	queue<int> q;
	q.push(proot);
	while(!q.empty()){
		int u = q.front();
		q.pop();
		level.push_back(u);
		if(lch[u]) q.push(lch[u]);
		if(rch[u]) q.push(rch[u]);
	}
}

int main(){
	cin >> n;
	memset(lch, 0, sizeof(lch));
	memset(rch, 0, sizeof(rch));
	read_list(post_order);
	read_list(in_order);
	build(0, n-1, 0, n-1);
	level_order(post_order[n-1]);
	cout << level[0];
	for(unsigned int i=1;i<level.size();i++)
		cout << " " << level[i];
	return 0;
}

发表于 2017-08-08 01:01:06 回复(0)

算是比较典型吧

#include<cstdio>
#include<queue>
using namespace std;
struct Node {
    int data;
    Node *l;
    Node *r;
};
int p[31], i[31],c[31],cnt=0;
Node *root;
queue<Node*> q;
Node* create(int pl, int pr, int il, int ir) {
    if (pl > pr || il > ir) {
        return NULL;
    }
    Node* root = new Node;
    root->data = p[pr];
    int k;
    for (k = il;k<=ir; k++) {
        if (i[k] == p[pr])
            break;
    }
    int nl = k - il;
    root->l = create(pl, pl + nl - 1, il, k - 1);
    root->r = create(pl + nl, pr - 1, k + 1, ir);
    return root;
}
void BFS(Node *n) {
    q.push(n);
    while (!q.empty()) {
        Node *temp = q.front();
        q.pop();
        c[cnt++] = temp->data;
        if (temp->l != NULL)
            q.push(temp->l);
        if (temp->r != NULL)
            q.push(temp->r);
    }
}
int main() {
    int N;
    scanf("%d", &N);
    for (int i = 1; i <= N; i++) {
        scanf("%d", &p[i]);
    }
    for (int j = 1; j <= N; j++) {
        scanf("%d", &i[j]);
    }
    root=create(1,N,1,N);
    BFS(root);
    for (int i = 0; i < N; i++) {
        printf("%d", c[i]);
        if (i < N - 1)
            printf(" ");
    }
    return 0;
}
发表于 2018-01-31 17:22:36 回复(0)
#include<bits/stdc++.h>
using namespace std;

struct node {
	int data;
	node* lchild;
	node* rchild;
	node(int a):data(a),lchild(NULL),rchild(NULL) {
	}
};

const int Max=50;
int n,P[Max],I[Max];

node* create(int p1,int p2,int i1,int i2) {
	if(p1>p2) {
		return NULL;
	}
	node* root=new node(P[p2]);
	int k;
	for(k=i1; k<=i2; k++) {
		if(I[k]==P[p2]) {
			break;
		}
	}
	int num=k-i1;
	root->lchild=create(p1,p1+num-1,i1,k-1);
	root->rchild=create(p1+num,p2-1,k+1,i2);
	return root;
}

int num=0;
void BFS(node* root) {
	queue<node*> q;
	q.push(root);
	while(!q.empty()) {
		node* now=q.front();
		q.pop();
		cout<<now->data;
		num++;
		if(num<n) cout<<" ";
		if(now->lchild!=NULL) {
			q.push(now->lchild);
		}
		if(now->rchild!=NULL) {
			q.push(now->rchild);
		}
	}
}

int main() {
	while(cin>>n) {
		for(int i=0; i<n; i++) {
			cin>>P[i];
		}
		for(int i=0; i<n; i++) {
			cin>>I[i];
		}
		node* root=create(0,n-1,0,n-1);
		BFS(root);
	}
	return 0;
}

发表于 2022-10-26 19:58:51 回复(2)

思路:不构建二叉树,使用队列+下标逐级分解二叉树
1、后序遍历最后一节点为根节点
2、中序二叉树中根节点的位置可以确定左右子树的中序遍历对应的节点数
3、根据节点数,可以在后序遍历中得到左右子树的后序遍历

#include<iostream>
using namespace std;

int main()
{
    int n, post[35], in[35], i;
    int s1[35], e1[35], s2[35], e2[35], front, end;
    cin >> n;
    for (i = 0; i < n; ++i)
        cin >> post[i];
    for (i = 0; i < n; ++i)
        cin >> in[i];
    front = -1, end = 0;
    s1[end] = s2[end] = 0;
    e1[end] = e2[end] = n-1;
    while(end != front)
    {
        if (front != -1)
            cout << " ";
        cout << post[e1[++front]];
        for (i = s2[front]; i <= e2[front]; ++i)
            if (in[i] == post[e1[front]])
                break;
        if (s1[front] != e1[front])
        {
            if (i > s2[front])
            {
                s1[++end] = s1[front];
                e1[end] = s1[front]+i-s2[front]-1;
                s2[end] = s2[front];
                e2[end] = i-1;
            }
            if (i < e2[front])
            {
                s1[++end] = s1[front]+i-s2[front];
                e1[end] = e1[front]-1;
                s2[end] = i+1;
                e2[end] = e2[front];
            }
        } 
    }
    return 0;
}
发表于 2022-05-14 01:50:26 回复(0)
别的大佬的一个不需要重构的方法,利用了层次遍历的性质
#include <cstdio>
#include <vector>
#include <map>
using namespace std;
vector<int> post, in;
map<int, int> level;
void pre(int root, int start, int end, int index) {
    if(start > end) return ;
    int i = start;
    while(i < end && in[i] != post[root]) i++;
    level[index] = post[root];
    pre(root - 1 - end + i, start, i - 1, 2 * index + 1);
    pre(root - 1, i + 1, end, 2 * index + 2);
}
int main() {
    int n;
    scanf("%d", &n);
    post.resize(n);
    in.resize(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);
    auto it = level.begin();
    printf("%d", it->second);
    while(++it != level.end()) printf(" %d", it->second);
    return 0;
}

发表于 2021-12-22 14:43:46 回复(0)
这道题我采取了另一种思路来构建二叉树,因为后序遍历的性质,根永远是后序遍历数组最后一个元素,另外后序遍历是左右根的顺序,所以在创建树的时候,取当前范围内最大下标做根节点,然后先递归创建右子树,后创建左子数
#include<bits/stdc++.h>
using namespace std;
struct Tree{
    int data;
    Tree* left;
    Tree* right;
};
Tree* createTree(int a[],int b[],int l1,int h1,int l2,int h2){
    //a是后序遍历数组,b是中序遍历数组,l1,h1为后序第一个和最后一个下标,l2和h2是中序第一个和最后一个下标
    Tree* root=new Tree;
    if(h1>=0){      
        root->data=a[h1];   
    }
    int i;
    for(i=l2;b[i]!=root->data;i++);
    //cout<<i<<endl;
    int llen=i-l2;
    int rlen=h2-i;
 
    if(rlen>0){
        root->right=createTree(a,b,h1-rlen,h1-1,h2-rlen+1,h2);
    }else{
        root->right=NULL;
    }
    if(llen>0){
        root->left=createTree(a,b,l1,l1+llen-1,l2,l2+llen-1);
    }else{
        root->left=NULL;
    }
    return root;
    
}
void BFS(Tree* root,int n){
    queue<Tree*> q;
    int count=0;
    q.push(root);
    while(!q.empty()){
        Tree* temp=q.front();
        q.pop();
        printf("%d",temp->data);
        count<n?printf(" "):printf("\n");
        if(temp->left!=NULL)q.push(temp->left);
        if(temp->right!=NULL)q.push(temp->right);
        }
 
}
int main(){
    int n;
    while(~scanf("%d",&n)){
        int a[31],b[31];
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=0;i<n;i++){
            scanf("%d",&b[i]);
        }
        Tree* t=createTree(a,b,0,n-1,0,n-1);
        BFS(t,n);
    }
    return 0;
}


发表于 2020-03-30 11:47:13 回复(0)
#include<iostream>
(720)#include<cstdio>
#include<stack>
(850)#include<queue>
using namespace std;
struct node{
	int data;
	node* left;
	node* right;
	node(int x):data(x),left(NULL),right(NULL){}
};
int pre[35];
int in[35];
int post[35];

node* create(int postl,int postr,int inl,int inr){
	if(postl>postr){
		return NULL;
	}
	node* root=new node(post[postr]);
	int i;
	for(i=inl;i<=inr;i++){
		if(in[i]==post[postr])
		break;
	}
	root->left=create(postl,postl+i-inl-1,inl,i-1);
	root->right=create(postl+i-inl,postr-1,i+1,inr);
//	cout<<"complete!!!"<<endl;
	return root;
}
void BFS(node* root){
	queue<node*> res;
	res.push(root);
	while(!res.empty()){
		node* cur=res.front();
		int temp=cur->data;
		cout<<temp<<" ";
		res.pop();
		if(cur->left){
			res.push(cur->left);
		}
		if(cur->right){
			res.push(cur->right);
		}
	}
}

int main(){
	int count;
	cin>>count;
	for(int i=0;i<count;i++){
		cin>>post[i];
	}
	for(int i=0;i<count;i++){
		cin>>in[i];
	}
	node* root=create(0,count-1,0,count-1);
	BFS(root);
	return 0;    
}//幼儿园级别的代码水平,参考了算法笔记
发表于 2020-03-04 01:19:25 回复(0)
input()
d,m,p = {},[],0
a,d[0] = input().split()[::-1],[input().split()[::-1]]
try:
    while a:
        for i in range(len(d[p])):
            if len(d[p][i]) <= 1:continue
            for j in a:
                if j in d[p][i]:
                    a.remove(j)
                    break
            for k in range(len(d[p][i])):
                if d[p][i][k] == j:
                    break
            try:
                d[p + 1].extend([d[p][i][:k],d[p][i][1 + k:]])
            except:
                d[p + 1] = [d[p][i][:k],d[p][i][1 + k:]]
            d[p][i] = [j]
        p += 1
except:
    for i in d:
        try:
            while True:
                d[i].remove([])
        except:
            pass

for i in d:
    for j in d[i][::-1]:
        m += [j[0]]
print(' '.join(' '.join(m).split()))

发表于 2020-03-02 18:15:52 回复(0)
#include <iostream>
#include <string>
#include <queue>
using namespace std;


//1020 Tree Traversals 
//二叉树,给定先序和中序,输出层序

class node {
public:
    int id;
    node *lchild;
    node *rchild;
};



node* create(int* s1, int* s2, int n) {
    //s1为后序,s2为中序,n为元素个数
    if (n == 0) return NULL;

    //后序的最后一个点为根
    node* ptr = (node*)malloc(sizeof(node));
    ptr->id = s1[n-1];
    //这两行初始化一定要写,不写默认值会报错
    ptr->lchild = NULL;
    ptr->rchild = NULL;

    //找到根在s2中的位置
    size_t pos = -1;
    for (int i = 0; i < n; ++i) {
        if (s2[i] == s1[n-1]) {
            pos = i; break;
        }
    }
    //s2中[0,pos)为中序左子树,(pos,n-1]为中序右子树
    //根据等长关系,s1中[0,pos)为后序左子树,[pos,n-1)为后序右子树

    if (pos > 0) {
        //pos=0,表示没有左子树
        ptr->lchild = create(s1,s2, pos);
    
    if(pos<n-1){
        //pos=n-1,表示没有右子树
        ptr->rchild = create(s1 + pos, s2 + pos + 1, n - 1 - pos); 
    }

    return ptr;
}

int main() {
    int n;//n<=30
    int postorder[31] = {};
    int inorder[31] = {};

    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> postorder[i];
    }
    for (int i = 0; i < n; ++i) {
        cin >> inorder[i];
    }

    //重构树
    node* ptr = create(postorder, inorder, n);


    //层序遍历
    queue<node*> q;
    q.push(ptr);
    int flag = 0;
    while (!q.empty()) {
        ptr = q.front();
        q.pop();
        if (flag == 0) { cout << ptr->id; flag = 1; }
        else { cout << " " << ptr->id; }
        if (ptr->lchild)
            q.push(ptr->lchild);
        if (ptr->rchild)
            q.push(ptr->rchild);
    }

    return 0;
}
发表于 2019-01-23 13:19:25 回复(0)
#define _CRT_SECURE_NO_WARNINGS  
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<stack>
#include<string>
#include<map>
#include<queue>
using namespace std;

int n=0;
vector<int> post;
vector<int> in;

struct node
{
    int num;
    struct node *left=NULL;
    struct node *right=NULL;
    node(int num = 0, struct node *left = NULL, struct node *right = NULL) {
        this->num = num;
        this->left = left;
        this->right = right;
    }
};

int findpos(int a) {
    for (int i = 0; i < n; i++) {
        if (in[i] == a) {
            return i;
        }
    }
    return 0;
}

struct node *buildtree(int lowpost, int highpost, int lowin, int highin)
{
    //int pos = findpos(post[highpost]);
    ////cout << lowpost << ' ' << highpost << ' ' << lowin << ' ' << highin <<' '<<pos<< endl;
    ////getchar();
    //struct node newnode = {0,NULL,NULL};

    //newnode.num = post[highpost];
    ////cout << newnode.num << endl;
    //if (lowin <= pos - 1) {
    //    newnode.left = buildtree(lowpost, lowpost + pos - lowin-1, lowin, pos - 1);
    //}
    //if (pos + 1 <= highin) {
    //    newnode.right = buildtree(highpost - 1 - (highin - pos-1), highpost - 1, pos + 1, highin);
    //}
    //cout << (int)&newnode << endl;
    //cout << newnode.num<<endl;
    //return &newnode;

    int pos = findpos(post[highpost]);
    //cout << lowpost << ' ' << highpost << ' ' << lowin << ' ' << highin <<' '<<pos<< endl;
    //getchar();
    struct node *newnode =new struct node;
    newnode->num = post[highpost];
    //cout << newnode.num << endl;
    if (lowin <= pos - 1) {
        newnode->left = buildtree(lowpost, lowpost + pos - lowin - 1, lowin, pos - 1);
    }
    if (pos + 1 <= highin) {
        newnode->right = buildtree(highpost - 1 - (highin - pos - 1), highpost - 1, pos + 1, highin);
    }
    //cout << (int)newnode << endl;
    //cout << newnode->num << endl;
    return newnode;
}


int main()
{
    freopen("data.txt", "r", stdin);
    cin >> n;
    for (int i = 0; i < n; i++) {
        int a;
        cin >> a;
        post.push_back(a);
    }
    for (int i = 0; i < n; i++) {
        int a;
        cin >> a;
        in.push_back(a);
    }
    freopen("CON", "r", stdin);

    struct node * root;
    //节点数一定大于零
    root=buildtree(0, n - 1, 0, n - 1);//该子树后续开始结束,中序开始结束,返回建立好的子树的根指针
    //cout << (int)root << endl;
    //cout << root->num << endl;
    //cout << (int)root->left << endl;



    //层序遍历打印
    queue<struct node*> q;
    q.push(root);
    bool isfirst = true;
    while (q.empty() != true) {
        if (isfirst == true) {
            printf("%d", q.front()->num);
            isfirst = false;
        }
        else {
            printf(" %d", q.front()->num);
        }
        if (q.front()->left != NULL) {
            q.push(q.front()->left);
        }
        if (q.front()->right != NULL) {
            q.push(q.front()->right);
        }
        q.pop();
    }


    
    getchar();
    return 0;
}


问一下buildtree注释部分的新节点声明有什么问题呢? 
buildtree中使用new来初始化节点是可以的,直接调用构造函数却不对

编辑于 2018-05-28 11:13:26 回复(0)
啥头像
重建二叉树
层序遍历二叉树
class TreeNode(object):
    def __init__(self, data=0, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right

def parseTree(po, ino, n):
    if n == 0:
        return None
    idx = ino.index(po[n-1])
    root = TreeNode(po[n-1])
    root.left = parseTree(po[:idx], ino[:idx], idx)
    root.right = parseTree(po[idx:n-1], ino[idx+1:], n-idx-1)
    return root

def levelTraverse(root):
    queue = []; rlt = []
    queue.append(root)
    while queue:
        node = queue.pop(0)
        rlt.append(node.data)
        if node.left:
            queue.append(node.left)
        if node.right:
            queue.append(node.right)
    return rlt
N = input()
po = map(int, raw_input().strip().split())
ino = map(int, raw_input().strip().split())
root = parseTree(po, ino, N)
rlt = levelTraverse(root)
rlt = map(str, rlt)
print(' '.join(rlt)) 


发表于 2016-02-23 12:17:31 回复(1)