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


    一,问题描述

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

    输入的数据格式如下:

    第一行为一个整数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)。有点大。

    参考资料:二叉树的构造

  • 相关阅读:
    MySQL 数据恢复
    由 go orm 引发的探索
    beego 优雅重启
    2020年8月20日
    Linux 递归获取目录下所有满足条件的文件
    NET Core Kestrel部署HTTPS 一个服务器绑一个证书 一个服务器绑多个证书
    Flutter环境配置-windows
    Vue获取钉钉免登陆授权码(vue中的回调函数实践)
    【C#上位机必看】你们要的Iot物联网项目来了
    Windows Server系统部署MySQL数据库
  • 原文地址:https://www.cnblogs.com/hapjin/p/5903913.html
Copyright © 2020-2023  润新知