構造二叉樹,並求解樹的高度


一,問題描述

在控制台上輸入一組數據,請按照輸入的數據的格式來構造一棵二叉樹,並打印出二叉樹的高度。

輸入的數據格式如下:

第一行為一個整數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)。有點大。

 

參考資料:二叉樹的構造

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM