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

一,问题描述

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

输入的数据格式如下:

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

 

参考资料:二叉树的构造

 

posted @ 2016-09-26 17:35  大熊猫同学  阅读(3859)  评论(1编辑  收藏  举报