面试题6:重建二叉树

来源:互联网 发布:php 博客系统 编辑:程序博客网 时间:2024/04/30 09:01

题目描述:online judge

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的后序遍历序列。

输入:

输入可能包含多个测试样例,对于每个测试案例,

输入的第一行为一个整数n(1<=n<=1000):代表二叉树的节点个数。

输入的第二行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的前序遍历序列。

输入的第三行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的中序遍历序列。

输出:

对应每个测试案例,输出一行:

如果题目中所给的前序和中序遍历序列能构成一棵二叉树,则输出n个整数,代表二叉树的后序遍历序列,每个元素后面都有空格。

如果题目中所给的前序和中序遍历序列不能构成一棵二叉树,则输出”No”。

样例输入:
81 2 4 7 3 5 6 84 7 2 1 5 3 8 681 2 4 7 3 5 6 84 1 2 7 5 3 8 6
样例输出:
7 4 2 5 8 6 3 1 No

问题分析:

性质:二叉树的前序遍历中第一个数字总是根节点的值,中序遍历中根节点把遍历序列分为左右两颗子树。利用者两个特性我们可以重建二叉树。具体如何重建,笔者建议读者自己在草稿纸上举几个例子。弄清楚重建的过程,然后在开始编码。


java代码:

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.StreamTokenizer;public class Problem_06 {private int[] preorder;private int[] inorder;private BinaryTreeNode root;private boolean isTree = true;private StringBuilder sb;public Problem_06(int[] preorder, int[] inorder){this.preorder = preorder;this.inorder = inorder;root = construct(preorder, inorder);sb = new StringBuilder();}private BinaryTreeNode construct(int[] preorder, int[] inorder) {if(preorder.length == 0 || inorder.length == 0){isTree = false;return null;}return constructCore(0, preorder.length - 1, 0, inorder.length -1);}private BinaryTreeNode constructCore(int startPreorder, int endPreorder, int startInorder, int endInorder) {int rootValue = preorder[startPreorder];BinaryTreeNode root = new BinaryTreeNode();root.value = rootValue;if(startPreorder == endPreorder){if(startInorder == endInorder && preorder[startPreorder] == inorder[startInorder]){return root;}else{isTree = false;return null;}}//从中序遍历中找到根节点int rootInorder = startInorder;while(rootInorder <= endInorder && inorder[rootInorder] != rootValue){++rootInorder;}if(rootInorder > endInorder ||(rootInorder == endInorder && inorder[rootInorder] != rootValue)){isTree = false;return null;}int leftLength = rootInorder - startInorder;int leftPreorder = startPreorder + leftLength;if(leftLength > 0 && isTree){root.left = constructCore(startPreorder + 1, leftPreorder, startInorder, rootInorder -1 );}if(leftLength < endPreorder - startPreorder && isTree){root.right = constructCore(leftPreorder + 1, endPreorder, rootInorder + 1, endInorder);}return root;}private void postTree(BinaryTreeNode root) {if (root.left != null)postTree(root.left);if (root.right != null)postTree(root.right);sb.append(root.value+" ");}public void showTree() {if (isTree) {postTree(root);System.out.println(sb.toString());} else {System.out.println("No");}}class BinaryTreeNode{int value;BinaryTreeNode left;BinaryTreeNode  right;}public static void main(String[] args) throws IOException {BufferedReader buf = new BufferedReader( new InputStreamReader(System.in));StreamTokenizer str = new StreamTokenizer(buf);while(str.nextToken() != StreamTokenizer.TT_EOF){//元素录入int length = (int)str.nval;int preorder[] = new int[length];int inorder[] = new int[length];for(int i = 0; i < preorder.length; i ++){str.nextToken();preorder[i] = (int)str.nval;}for(int i = 0; i < inorder.length; i ++){str.nextToken();inorder[i] = (int)str.nval;}new Problem_06(preorder,inorder).showTree();}}}

C++代码:

#include<iostream>#include<stdio.h>using namespace std; #define N 10000 struct BinaryTreeNode{    int m_nValue;    BinaryTreeNode *m_pLeft;    BinaryTreeNode *m_pRight;}; bool bo; BinaryTreeNode *ConstructCore(int *startPreorder, int *endPreorder, int *startInorder, int *endInorder){    int rootValue = startPreorder[0];    BinaryTreeNode *root = new BinaryTreeNode();    root->m_nValue = rootValue;    root->m_pLeft = root->m_pRight = NULL;         if(startPreorder == endPreorder)    {        if(startInorder == endInorder && *startPreorder == *startInorder)        return root;        else        {            bo = false;            return NULL;        }    }          int *rootInorder = startInorder;    while(rootInorder <= endInorder && *rootInorder != rootValue)    {        rootInorder++;    }    if(rootInorder == NULL || *rootInorder != rootValue)    {        bo = false;        return NULL;    }         int leftLength = rootInorder - startInorder;    int *leftPreorderEnd = startPreorder + leftLength;    if(leftLength > 0)    {        root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, startInorder, rootInorder - 1);    }    if(endPreorder - startPreorder > leftLength)    {        root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder, rootInorder + 1, endInorder);    }         return root;}   BinaryTreeNode *Construct(int *preorder, int *inorder, int length){    if(preorder == NULL || inorder == NULL || length <= 0)    {        bo = false;        return NULL;    }    return ConstructCore(preorder, preorder + length -1, inorder, inorder + length -1);}  void tailPrint(BinaryTreeNode *root){    if(root->m_pLeft != NULL)    tailPrint(root->m_pLeft);    if(root->m_pRight != NULL)    tailPrint(root->m_pRight);    printf("%d ", root->m_nValue);} int main(){    int n;    while(scanf("%d", &n) != EOF)    {        bo = true;        if(n <= 0)        {            printf("No\n");            return 0;        }                 int a[N], b[N];        for(int i = 0; i < n; i++)        {            scanf("%d", &a[i]);        }           for(int j = 0; j < n; j++)        {            scanf("%d", &b[j]);        }                 BinaryTreeNode *c = Construct(a, b, n);        if(bo == true && c != NULL)        {            tailPrint(c);            printf("\n");        }        else printf("No\n");    }    return 0;}

C代码:

#define  _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>  #define TRUE 1#define FALSE 0 typedef struct Node{    int i;    struct Node* left;    struct Node* right;}Node; int isNotTree=FALSE; Node* RebuildTree(int* preOrder,int* inOrder,int length){         int i=0;         if(isNotTree)        return NULL;    Node* result=(Node*)malloc(sizeof(Node));    result->left=NULL;    result->right=NULL;    if(length==0)        return NULL;    if(length==1)    {        if(*preOrder!=*inOrder)        {            isNotTree=TRUE;            return NULL;        }         result->i=*preOrder;        return result;    }          for(;*preOrder!=inOrder[i];++i);     result->i=*preOrder;    result->left=RebuildTree(preOrder+1,inOrder,i);    result->right=RebuildTree(preOrder+i+1,inOrder+i+1,length-i-1);     return result;} void printTree(Node* root){    if(root!=NULL)    {        printTree(root->left);        printTree(root->right);        printf("%d ",root->i);    } } int main(){    int length;    int *preOrder,*inOrder;    int i=0;    struct Node* root=NULL;    while(scanf("%d",&length)!=EOF)    {        preOrder=(int*)malloc(length*sizeof(int));        inOrder=(int*)malloc(length*sizeof(int));         for(i=0;i<length;++i)            scanf("%d",&preOrder[i]);        for(i=0;i<length;++i)            scanf("%d",&inOrder[i]);         root=RebuildTree(preOrder,inOrder,length);        if(isNotTree==TRUE)        {            printf("No");            isNotTree=FALSE;        }        else            printTree(root);        printf("\n");        free(preOrder);        free(inOrder);    }     return 0;}

测试用例:

普通二叉树(完全二叉树,不完全二叉树)

特殊二叉树(所有结点都没有左结点或右结点的树,只有一个结点的二叉树)

特殊输入测试(二叉树结点为null,输入前序和中序不匹配)


体会:

本人最先开始学的是C语言,对于指针在java中的一些类似功能不是特别熟悉,java
 生成的对象不要人为管理,而C和C++需要人为销毁。所以java对于实现树和图等结构比C和C++更加容易。

0 0
原创粉丝点击