1. 程式人生 > 其它 >求一顆二叉樹的最大寬度(以及寬度遍歷)

求一顆二叉樹的最大寬度(以及寬度遍歷)

一、如何實現二叉樹的寬度遍歷

寬度遍歷用佇列(先進先出)

1)先把頭節點放入佇列中

2)每次彈出一個,列印

3)對於彈出的節點,先把彈出節點的節點放入佇列、再把其節點放入佇列(沒有左右節點就不放)

重複以上三個步驟

//寬度遍歷
    public static void w(Node head){
        if (head == null){
            return;
        }
        Queue<Node> queue = new LinkedList<>(); //java中,LinkedList就是佇列
        queue.add(head);
        
while(!queue.isEmpty()){ Node cur = queue.poll(); System.out.print(cur.value); if (cur.left != null){ queue.add(cur.left); } if (cur.right!= null){ queue.add(cur.right); } } }
寬度遍歷

二、求一個二叉樹的最大寬度

思路,在寬度遍歷的基礎上進行改進:

curLevel:記錄當前Node所在層數
curWidth:記錄當前層的寬度
maxWidth:記錄全域性最大層的寬度 

1、新增一個HashMap,用於記錄當前Node屬於哪一層
2、每次新增Node進佇列時,記錄當前Node所在層次
3、每次poll出一個Node時,在HashMap中獲取它屬於哪一層,如果屬於當前層,curWidth++。反之maxWidth = Math.max(maxWidth, curWidth) , curLevel++

//獲取二叉樹中最大層的寬度
    public static int getMaxWidth(Node head) {
        
if (head == null) { return 0; } Queue<Node> queue = new LinkedList<>(); //java中,LinkedList就是佇列 queue.add(head); HashMap<Node, Integer> levelMap = new HashMap<>();//記錄當前Node屬於第幾層 levelMap.put(head, 1); int curLevel = 1; //記錄當前在哪一層 int curWidth = 0; //記錄當前層的寬度(有幾個節點),因為head進去之後沒彈出,所以初始值為0 int maxWidth = -1; //記錄最大層的寬度,初始值 -1 while (!queue.isEmpty()) { Node cur = queue.poll(); //彈出一個Node int curNodeLevel = levelMap.get(cur); //記錄彈出的Node屬於哪一層(從HahsMap中獲取) //如果當前節點所遍歷的層和來到的想統計的層一樣, if (curNodeLevel == curLevel) { curWidth++; } else {//說明到下一層了 maxWidth = Math.max(maxWidth, curWidth); //統計當前Node之上所有層中最大層的節點數(做比較) curLevel++; //跳到下一層 curWidth = 1;//為什麼是1? 比如當前節點2屬於第2層(跳出第1層,不走if),走的是else // 但要統計第2層的節點數,所以初始值為1,下次再有第2層的節點被pop時,走正常的if流程 } //能夠進行以上操作前提是:知道每一個Node節點所在的層數 解決辦法:在進棧的時候記錄它的層 if (cur.left != null) { levelMap.put(cur.left, curNodeLevel + 1);//當前Node左節點的所在層數為當前Node所在層數加1 queue.add(cur.left); } if (cur.right != null) { levelMap.put(cur.right, curNodeLevel + 1);//當前Node右節點的所在層數為當前Node所在層數加1 queue.add(cur.right); } } maxWidth = Math.max(maxWidth, curWidth); return maxWidth; }
獲取二叉樹最大層的寬度

例項程式碼

package Algorithms;

/**
 * @author : zhang
 * @version : 1.0
 * @date : Create in 2021/8/12
 * @description :
 */

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;

public class TreeMaxWidth {

    public static void main(String[] args) {
        Node head = new Node(1);
        head.left = new Node(2);
        head.right = new Node(3);
        head.left.left = null;
        head.left.right = new Node(4);
        head.right.left = new Node(5);
        head.right.right = null;
        head.left.right.left = new Node(6);
        head.left.right.right = new Node(7);
        head.right.left.left = new Node(8);
        head.right.left.right = new Node(9);

        //測試寬度遍歷
        width(head); // 1 2 3 4 5 6 7 8 9

        //測試二叉樹最大層的寬度
        int maxWidth = getMaxWidth(head);
        System.out.println("二叉樹最大層的寬度為:" + maxWidth); // 二叉樹最大層的寬度為:4

    }

    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int data) {
            this.value = data;
        }
    }

    //寬度遍歷
    public static void width(Node head) {
        if (head == null) {
            return;
        }
        Queue<Node> queue = new LinkedList<>(); //java中,LinkedList就是佇列
        queue.add(head);
        while (!queue.isEmpty()) {
            Node cur = queue.poll();
            System.out.print(cur.value + " ");
            if (cur.left != null) {
                queue.add(cur.left);
            }
            if (cur.right != null) {
                queue.add(cur.right);
            }
        }
        System.out.println();
    }

    //獲取二叉樹中最大層的寬度
    public static int getMaxWidth(Node head) {
        if (head == null) {
            return 0;
        }
        Queue<Node> queue = new LinkedList<>(); //java中,LinkedList就是佇列
        queue.add(head);
        HashMap<Node, Integer> levelMap = new HashMap<>();//記錄當前Node屬於第幾層
        levelMap.put(head, 1);
        int curLevel = 1; //記錄當前在哪一層
        int curWidth = 0; //記錄當前層的寬度(有幾個節點),因為head進去之後沒彈出,所以初始值為0
        int maxWidth = -1;   //記錄最大層的寬度,初始值 -1
        while (!queue.isEmpty()) {
            Node cur = queue.poll(); //彈出一個Node
            int curNodeLevel = levelMap.get(cur); //記錄彈出的Node屬於哪一層(從HahsMap中獲取)
            //如果當前節點所遍歷的層和來到的想統計的層一樣,
            if (curNodeLevel == curLevel) {
                curWidth++;
            } else {//說明到下一層了
                maxWidth = Math.max(maxWidth, curWidth); //統計當前Node之上所有層中最大層的節點數(做比較)
                curLevel++; //跳到下一層
                curWidth = 1;//為什麼是1? 比如當前節點2屬於第2層(跳出第1層,不走if),走的是else
                // 但要統計第2層的節點數,所以初始值為1,下次再有第2層的節點被pop時,走正常的if流程
            }
            //能夠進行以上操作前提是:知道每一個Node節點所在的層數   解決辦法:在進棧的時候記錄它的層
            if (cur.left != null) {
                levelMap.put(cur.left, curNodeLevel + 1);//當前Node左節點的所在層數為當前Node所在層數加1
                queue.add(cur.left);
            }
            if (cur.right != null) {
                levelMap.put(cur.right, curNodeLevel + 1);//當前Node右節點的所在層數為當前Node所在層數加1
                queue.add(cur.right);
            }
        }
        maxWidth = Math.max(maxWidth, curWidth);
        return maxWidth;
    }

    //程式碼2
    public static int getMaxWidth2(Node head) {
        if (head == null) {
            return 0;
        }
        int maxWidth = 0;
        int curWidth = 0;
        int curLevel = 0;
        HashMap<Node, Integer> levelMap = new HashMap<>();
        levelMap.put(head, 1);
        LinkedList<Node> queue = new LinkedList<>();
        queue.add(head);
        Node node = null;
        Node left = null;
        Node right = null;
        while (!queue.isEmpty()) {
            node = queue.poll();
            left = node.left;
            right = node.right;
            if (left != null) {
                levelMap.put(left, levelMap.get(node) + 1);
                queue.add(left);
            }
            if (right != null) {
                levelMap.put(right, levelMap.get(node) + 1);
                queue.add(right);
            }
            if (levelMap.get(node) > curLevel) {
                curWidth = 0;
                curLevel = levelMap.get(node);
            } else {
                curWidth++;
            }
            maxWidth = Math.max(maxWidth, curWidth);
        }
        return maxWidth;
    }

}