求一顆二叉樹的最大寬度(以及寬度遍歷)
阿新 • • 發佈:2021-08-12
一、如何實現二叉樹的寬度遍歷
寬度遍歷用佇列(先進先出)
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; } }