二叉樹的層次遍歷(列印)
阿新 • • 發佈:2019-02-03
一:按層列印
按層列印原本是十分基礎的內容,本例將同一層的節點列印在同一行上,並輸出行號。關鍵問題是換行的時機。只需要用兩個node型別的變數last和nLast即可解決這個問題。
last變量表示正在列印的當前行的最右節點,nLast表示下一行的最右節點。假設我們每一層都做從左到右的寬度優先遍歷,如果發現遍歷到的節點等於last,說明該換行了。換行之後只要令last = nLast,就可以繼續下一行的列印過程。
import java.util.LinkedList; import java.util.Queue; public class LevelTravel { public static void main(String[] args) { Node node1 = new Node(1); Node node2 = new Node(2); Node node3 = new Node(3); Node node4 = new Node(4); Node node5 = new Node(5); Node node6 = new Node(6); Node node7 = new Node(7); Node node8 = new Node(8); node1.left = node2; node1.right = node3; node2.left = node4; node3.left = node5; node3.right = node6; node5.left = node7; node5.right = node8; levelTravel(node1); } public static void levelTravel(Node root) { if(root == null) { return; } Queue<Node> queue = new LinkedList<Node>(); int level = 1; Node last = root;//當前行的最右節點 Node nLast = null;//下一行的最右節點 queue.offer(root); System.out.print("Level " + (level++) + " : "); while(!queue.isEmpty()) { root = queue.poll(); System.out.print(root.value + " "); if(root.left != null) { queue.offer(root.left); nLast = root.left; } if(root.right != null) { queue.offer(root.right); nLast = root.right; } //遍歷到當前行的最右節點,換行 if(root == last && !queue.isEmpty()) { System.out.print("\nLevel " + (level++) + " : "); last = nLast;//記錄下一行的最右節點,繼續下一行的列印 } } } }
二:之字形列印
原則一:如果是從左到右,一律從dq的頭部彈出節點,如果彈出的節點沒有孩子節點,不用放任何節點到dq中,如果當前節點有孩子節點,先讓左孩子從尾部進入dq,再讓右孩子從尾部進入dq。
原則二:如果是從右到左,一律從dq的尾部彈出節點,如果彈出的節點沒有孩子節點,不用放任何節點到dq中,如果當前節點有孩子節點,先讓右孩子從頭部進入dq,再讓左孩子從頭部進入dq。
用原則一和原則二的切換,即可完成之字形列印,現在只剩一個問題,如何確定切換原則1和原則2的時機,其實還是確定每一層最後一個節點的問題。在列印過程中,下一層最後一個節點是當前層有孩子的節點中最先進入dq的孩子節點。
import java.util.Deque; import java.util.LinkedList; public class ZigZagTravel { public static void main(String[] args) { Node node1 = new Node(1); Node node2 = new Node(2); Node node3 = new Node(3); Node node4 = new Node(4); Node node5 = new Node(5); Node node6 = new Node(6); Node node7 = new Node(7); Node node8 = new Node(8); node1.left = node2; node1.right = node3; node2.left = node4; node3.left = node5; node3.right = node6; node5.left = node7; node5.right = node8; zigZagTravel(node1); } public static void zigZagTravel(Node root) { if(root == null) { return; } Deque<Node> deque = new LinkedList<Node>(); int level = 1; boolean lr = true; Node last = root; Node nLast = null; deque.offerFirst(root); printLevelAndDirection(lr, level++); while(!deque.isEmpty()) { if(lr) { root = deque.pollFirst(); if(root.left != null) { nLast = nLast == null ? root.left : nLast;//下一層最後列印的節點是當前層有孩子節點的最先進入deque的孩子節點 deque.offerLast(root.left); } if(root.right != null) { nLast = nLast == null ? root.right : nLast; deque.offerLast(root.right); } } else { root = deque.pollLast(); if(root.right != null) { nLast = nLast == null ? root.right : nLast; deque.offerFirst(root.right); } if(root.left != null) { nLast = nLast == null ? root.left : nLast; deque.offerFirst(root.left); } } System.out.print(root.value + " "); if(root == last && !deque.isEmpty()) { lr = !lr;//到當前層最後一個節點,換方向 last = nLast;//記錄下一行最後一個節點,繼續下一行的列印 nLast = null;//清空nLast, System.out.println(); printLevelAndDirection(lr, level++); } } } public static void printLevelAndDirection(boolean lr, int level) { System.out.print("Level: " + level + " from "); System.out.print(lr ? "left to right: " : "right to left: "); } }