二叉樹的遍歷分為兩大類:
1、深度優先遍歷(前序遍歷、中序遍歷、后序遍歷)
2、廣度優先遍歷
3
2 8
9 10 null 4
package xiaohui; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Stack; /** * @author 忠哥 * @create 2021-10-24 **/ public class CreateBinaryTreeByLinkedList { /** * 構建二叉樹 * * @param linkedList 鏈表 * @return */ public static TreeNode createTreeNode(LinkedList<Integer> linkedList) { TreeNode node = null; if (linkedList == null || linkedList.isEmpty()) { return null; } //從鏈表中移除第一個並將其返回 Integer data = linkedList.removeFirst(); //如果元素為空,則不再遞歸 if (data != null) { node = new TreeNode(data); node.left = createTreeNode(linkedList); node.right = createTreeNode(linkedList); } return node; } /** * 前序遍歷 * * @param node */ public static void preOut(TreeNode node) { if (node == null) { return; } System.out.print(node.data + "\t"); preOut(node.left); preOut(node.right); } /** * 借助棧實現 前序遍歷 * * @param root */ public static void preOutStack(TreeNode root) { TreeNode treeNode = root; Stack<TreeNode> stack = new Stack<>(); while (treeNode != null || !stack.isEmpty()) { while (treeNode != null) { System.out.print(treeNode.data + "\t"); stack.push(treeNode); treeNode = treeNode.left; } if (!stack.isEmpty()) { treeNode = stack.pop(); treeNode = treeNode.right; } } } /** * 用非遞歸的方式實現二叉樹的先序遍歷(LeetCode144): * 1、申請一個棧stack,然后將頭節點壓入stack中。 * 2、從stack中彈出棧頂節點,打印,再將其右孩子節點(不為空的話)先壓入stack中,最后將其左孩子節點(不為空的話)壓入stack中。 * 3、不斷重復步驟2,直到stack為空,全部過程結束。 * * @param root */ private static void doPreOutStack(TreeNode root) { Stack<TreeNode> stack = new Stack<>(); if (root != null) { stack.push(root); while (!stack.empty()) { TreeNode node = stack.pop(); System.out.print(node.data + "\t"); if (node.right != null) { stack.push(node.right); } if (node.left != null) { stack.push(node.left); } } } } /** * 中序遍歷 * * @param node */ public static void midOut(TreeNode node) { if (node == null) { return; } midOut(node.left); System.out.print(node.data + "\t"); midOut(node.right); } /** * 用非遞歸的方式實現二叉樹的中序遍歷(LeetCode94): * 1、申請一個棧stack,初始時令cur=head * 2、先把cur壓入棧中,依次把左邊界壓入棧中,即不停的令cur=cur.left,重復步驟2 * 3、不斷重復2,直到為null,從stack中彈出一個節點,記為node,打印node的值,並令cur=node.right,重復步驟2 * 4、當stack為空且cur為空時,整個過程停止。 * * @param root */ private static void doMidOutStack(TreeNode root) { Stack<TreeNode> stack = new Stack<>(); if (root != null) { while (root != null || !stack.isEmpty()) { if (root != null) { stack.push(root); root = root.left; } else { root = stack.pop(); System.out.print(root.data + "\t"); root = root.right; } } } } /** * 后序遍歷 * * @param node */ public static void lastOut(TreeNode node) { if (node == null) { return; } lastOut(node.left); lastOut(node.right); System.out.print(node.data + "\t"); } /** * 用非遞歸的方式實現二叉樹的后序遍歷(LeetCode145): * 用非遞歸的方式實現后序遍歷有點麻煩。 * 1、申請一個棧s1,然后將頭節點壓入棧s1中。 * 2、從s1中彈出的節點記為cur,然后依次將cur的左孩子節點和右孩子節點壓入s1中。 * 3、在整個過程中,每一個從s1中彈出的節點都放進s2中。 * 4、不斷重復步驟2和步驟3,直到s1為空,過程停止。 * 5、從s2中依次彈出節點並打印,打印的順序就是后序遍歷的順序。 * * @param root */ private static void doLastOutStack(TreeNode root) { Stack<TreeNode> stack1 = new Stack<>(); Stack<TreeNode> stack2 = new Stack<>(); if (root != null) { stack1.push(root); while (!stack1.isEmpty()) { root = stack1.pop(); stack2.push(root); if (root.left != null) { stack1.push(root.left); } if (root.right != null) { stack1.push(root.right); } } while (!stack2.isEmpty()) { System.out.print(stack2.pop().data + "\t"); } } } /** * 二叉樹廣度優先遍歷(層序遍歷) * * @param root */ private static void levelOrderTraversal(TreeNode root) { Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()) { TreeNode node = queue.poll(); System.out.print(node.data + "\t"); if (node.left != null) { queue.offer(node.left); } if (node.right != null) { queue.offer(node.right); } } } public static void main(String[] args) { LinkedList linkedList = new LinkedList<Integer>(Arrays.asList(new Integer[]{3, 2, 9, null, null, 10, null, null, 8, null, 4})); TreeNode node = createTreeNode(linkedList); System.out.println("前序遍歷..."); preOut(node); System.out.println(); System.out.println("借助棧實現前序遍歷01..."); preOutStack(node); System.out.println(); System.out.println("借助棧實現前序遍歷02..."); doPreOutStack(node); System.out.println(); System.out.println("中序遍歷..."); midOut(node); System.out.println(); System.out.println("中序遍歷Stack..."); doMidOutStack(node); System.out.println(); System.out.println("后序遍歷..."); lastOut(node); System.out.println(); System.out.println("后序遍歷Stack..."); doLastOutStack(node); System.out.println(); System.out.println("廣度優先遍歷..."); levelOrderTraversal(node); } }
執行結果如下:
前序遍歷...
3 2 9 10 8 4
借助棧實現前序遍歷01...
3 2 9 10 8 4
借助棧實現前序遍歷02...
3 2 9 10 8 4
中序遍歷...
9 2 10 3 8 4
中序遍歷Stack...
9 2 10 3 8 4
后序遍歷...
9 10 2 4 8 3
后序遍歷Stack...
9 10 2 4 8 3
廣度優先遍歷...
3 2 8 9 10 4
