构造二叉树,并求解树的高度

一,问题描述

在控制台上输入一组数据,请按照输入的数据的格式来构造一棵二叉树,并打印出二叉树的高度。

输入的数据格式如下:

第一行为一个整数N(其实是二叉树中边的数目),表示接下来一共有N行输入,每行输入有两个数,左边的数表示父结点,右边的数表示父结点的孩子结点。示例如下:

6

0 1

0 2

1 3

2 4

2 5

4 6

从上面的输入可以看出:①根结点0 的左孩子为1,右孩子为2 。②结点1 只有一个孩子,即左孩子3

二,问题分析

问题的关键是根据上面的输入数据 构造一棵二叉树。

首先用一个Map<Integer, List<Integer>>保存上面的输入的数据。其中Key为父结点,Value为父结点的孩子结点。对于二叉树而言,父结点的孩子结点最多只有2个,故List长度最大为2.

然后,根据Map来构造二叉树即可。

对于Map中的每一个Entry,Entry的Key为父结点,找到父结点在树中的位置(findNode方法)。

Entry的Value为父结点的左右孩子,遍历Value,构造孩子结点。已知了父结点在树中的位置,又构造了孩子结点,只需要将父结点的左右指针指向左右孩子即可。

三,代码实现

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;

//按要求构造二叉树,假设头结点为0
public class BuildTree {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //<parent, childList>
        Map<Integer, List<Integer>> datas = new LinkedHashMap<Integer, List<Integer>>();
        while(sc.hasNextInt())
        {
            int edges = sc.nextInt();

            //将树的信息保存到hashmap<parent, childList>中
            for(int i = 0; i < edges; i++)
            {
                int parent = sc.nextInt();
                int child = sc.nextInt();

                if(!datas.containsKey(parent)){
                    List<Integer> childs = new ArrayList<Integer>();
                    childs.add(child);
                    datas.put(parent, childs);
                }else{
                    List<Integer> childs = datas.get(parent);
                    childs.add(child);
                }
            }//end for
            BinaryNode root = buildTree(datas);

            int height = height(root);
            System.out.println(height);
        }
        sc.close();
    }

    //求二叉树的高度
    private static int height(BinaryNode root){

        if(root == null)
            return 0;
        int leftHeight = height(root.left);
        int rightHeight = height(root.right);

        return 1 + (leftHeight > rightHeight ? leftHeight : rightHeight);
    }

    //构造二叉树
    private static BinaryNode buildTree(Map<Integer, List<Integer>> datas){
        BinaryNode root = null;

        BinaryNode current = null;
        List<Integer> childs = null;
        Set<Entry<Integer, List<Integer>>> entrySet = datas.entrySet();
        for (Entry<Integer, List<Integer>> entry : entrySet) {
            int parent = entry.getKey();
            current = findNode(parent, root);
            childs = datas.get(parent);
            if(current == null){//说明parent是根结点
                root = new BinaryNode(parent);
                createNode(root, childs);
            }else{
                createNode(current, childs);
            }
        }
        return root;
    }

    //创建parent结点的左右孩子结点
    private static void  createNode(BinaryNode parent, List<Integer> childs){
        if(childs.size() == 2){//说明有左右孩子
            BinaryNode leftChild = new BinaryNode(childs.get(0));
            BinaryNode rightChild = new BinaryNode(childs.get(1));
            parent.left = leftChild;
            parent.right = rightChild;
        }
        if(childs.size() == 1){//说明只有左孩子
            BinaryNode leftChild = new BinaryNode(childs.get(0));
            parent.left = leftChild;
        }
    }

    //查找树根为root的二叉树中 值为 nodeVal 的结点
    private static BinaryNode findNode(int nodeVal, BinaryNode root){
        //先序递归遍历查找 值为 nodeVal的结点
        BinaryNode target = null;

        if(root == null)
            return null;
        if(root.val == nodeVal)
            return root;
        target = findNode(nodeVal, root.left);//先在左子树中查找
        if(target == null)
            target = findNode(nodeVal, root.right);//左子树中未找到,则在右子树中查找
        return target;
    }

    private static class BinaryNode{
        int val;
        BinaryNode left;
        BinaryNode right;

        public BinaryNode(int val){
            this.val = val;
            left = right = null;
        }
    }
}

复杂度分析:由于 当构造父结点的左右孩子时,需要先查找父结点在二叉树中的位置,这个查找是用“先序遍历的思路”实现的。

故构造树的时间复杂度为O(1+2+3+……+N)=O(N^2)。有点大。

参考资料:二叉树的构造

时间: 2024-12-29 09:41:09

构造二叉树,并求解树的高度的相关文章

经典白话算法之二叉树中序前序序列(或后序)求解树

这种题一般有二种形式,共同点是都已知中序序列.如果没有中序序列,是无法唯一确定一棵树的. <1>已知二叉树的前序序列和中序序列,求解树. 1.确定树的根节点.树根是当前树中所有元素在前序遍历中最先出现的元素. 2.求解树的子树.找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边的所有元素就是右子树.若根节点左边或右边为空,则该方向子树为空:若根节点 边和右边都为空,则根节点已经为叶子节点. 3.递归求解树.将左子树和右子树分别看成一棵二叉树,重复1.2.3步,直到所有的节点完成定

二叉树先序序列和中序序列求解树

这种题一般有二种形式,共同点是都已知中序序列.如果没有中序序列,是无法唯一确定一棵树的. <1>已知二叉树的前序序列和中序序列,求解树. 1.确定树的根节点.树根是当前树中所有元素在前序遍历中最先出现的元素. 2.求解树的子树.找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边的所有元素就是右子树.若根节点左边或右边为空,则该方向子树为空:若根节点 边和右边都为空,则根节点已经为叶子节点. 3.递归求解树.将左子树和右子树分别看成一棵二叉树,重复1.2.3步,直到所有的节点完成定

Leetcode 106.从中序与后序遍历序列构造二叉树

从中序与后序遍历序列构造二叉树 根据一棵树的中序遍历与后序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 中序遍历 inorder = [9,3,15,20,7] 后序遍历 postorder = [9,15,7,20,3] 返回如下的二叉树: 3 / 9 20 / 15 7 解题思路: 已知中序遍历和后序遍历IN和Post,求还原二叉树. 后序遍历的最后一个数post[len-1]就是root节点. 搜索IN,如果IN[I]=post[len-1],那么 IN[I+1]-I

前序和中序构造二叉树

题目链接: 涉及知识:二叉树的遍历 分析: 二叉树的前序遍历:根节点 -> 左子树 -> 右子树 二叉树的中序遍历:左子树 -> 根节点 -> 右子树 由此可知:前序遍历中访问到的第一个元素便是根节点,通过该点便可以将中序遍历分成左右两部分,左部分的元素用来生成该二叉树的左子树,右部分用来生成二叉树的右子树. 同样,左右两部分的元素中,首先在前序遍历中出现的便是该子树的根节点,很明显符合递归的定义. 代码如下: /* * @lc app=leetcode.cn id=105 lan

【LeetCode】105. 从前序与中序遍历序列构造二叉树

题目 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder =?[3,9,20,15,7] 中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树: 3 / 9 20 / 15 7 思路:递归 同[剑指Offer]面试题07. 重建二叉树 关键在与正确定位左右子树范围. 代码 class Solution { public: TreeNode* buildTree(vector<int>& pre

通过二叉树的中序和后序遍历序列构造二叉树(非递归)

题目:通过二叉树的中序和后序遍历序列构造二叉树 同样,使用分治法来实现是完全可以的,可是在LeetCode中运行这种方法的代码,总是会报错: Memory Limit Exceeded ,所以这里还是用栈来实现二叉树的构建. 与用先序和后序遍历构造二叉树的方法类似,但还是要做一些改变: 如果从后往前处理中序和后序的序列,则处理就为如下所示的情况: Reverse_Post: 根-右子树-左子树 Reverse_In: 右子树-根-左子树 这样处理方式和先序-中序就差不多了,只是将添加左孩子的情况

Codevs 1501 二叉树的最大宽度和高度

1501 二叉树最大宽度和高度 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题目描述 Description 给出一个二叉树,输出它的最大宽度和高度. 输入描述 Input Description 第一行一个整数n. 下面n行每行有两个数,对于第i行的两个数,代表编号为i的节点所连接的两个左右儿子的编号.如果没有某个儿子为空,则为0. 输出描述 Output Description 输出共一行,输出二叉树的最大宽度和高度,用一个空格隔开. 样例输入 Sa

【LeetCode-面试算法经典-Java实现】【105-Construct Binary Tree from Preorder and Inorder Traversal(构造二叉树)】

[105-Construct Binary Tree from Preorder and Inorder Traversal(通过前序和中序遍历构造二叉树)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given preorder and inorder traversal of a tree, construct the binary tree. Note: You may assume that duplicates do not exist in the

【LeetCode-面试算法经典-Java实现】【106-Construct Binary Tree from Inorder and Postorder Traversal(构造二叉树II)】

[106-Construct Binary Tree from Inorder and Postorder Traversal(通过中序和后序遍历构造二叉树)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given inorder and postorder traversal of a tree, construct the binary tree. Note: You may assume that duplicates do not exist in th