二叉樹廣度優先遍歷和深度優先遍歷
阿新 • • 發佈:2019-02-17
二叉樹的遍歷方式:
1、深度優先:遞迴,非遞迴實現方式
1)先序遍歷:先訪問根節點,再依次訪問左子樹和右子樹
2)中序遍歷:先訪問左子樹,再訪問根節點嗎,最後訪問右子樹
3)後序遍歷:先訪問左子樹,再訪問右子樹,最後訪問根節點
2、廣度優先
按照樹的深度,一層一層的訪問樹的節點
package Solution; import java.util.LinkedList; import java.util.Queue; import java.util.Stack; public class BinaryTree { // 二叉樹節點 public static class BinaryTreeNode { int value; BinaryTreeNode left; BinaryTreeNode right; public BinaryTreeNode(int value) { this.value = value; } public BinaryTreeNode(int value, BinaryTreeNode left, BinaryTreeNode right) { super(); this.value = value; this.left = left; this.right = right; } } // 訪問樹的節點 public static void visit(BinaryTreeNode node) { System.out.println(node.value); } /** 遞迴實現二叉樹的先序遍歷 */ public static void preOrder(BinaryTreeNode node) { if (node != null) { visit(node); preOrder(node.left); preOrder(node.right); } } /** 遞迴實現二叉樹的中序遍歷 */ public static void inOrder(BinaryTreeNode node) { if (node != null) { inOrder(node.left); visit(node); inOrder(node.right); } } /** 遞迴實現二叉樹的後序遍歷 */ public static void postOrder(BinaryTreeNode node) { if (node != null) { postOrder(node.left); postOrder(node.right); visit(node); } } /** 非遞迴實現二叉樹的先序遍歷 */ public static void iterativePreorder(BinaryTreeNode node) { Stack<BinaryTreeNode> stack = new Stack<>(); if (node != null) { stack.push(node); while (!stack.empty()) { node = stack.pop(); // 先訪問節點 visit(node); // 把右子結點壓入棧 if (node.right != null) { stack.push(node.right); } // 把左子結點壓入棧 if (node.left != null) { stack.push(node.left); } } } } /** 非遞迴實現二叉樹的中序遍歷 */ public static void iterativeInOrder(BinaryTreeNode root) { Stack<BinaryTreeNode> stack = new Stack<>(); BinaryTreeNode node = root; while (node != null || stack.size() > 0) { // 把當前節點的所有左側子結點壓入棧 while (node != null) { stack.push(node); node = node.left; } // 訪問節點,處理該節點的右子樹 if (stack.size() > 0) { node = stack.pop(); visit(node); node = node.right; } } } /** 非遞迴使用單棧實現二叉樹後序遍歷 */ public static void iterativePostOrder(BinaryTreeNode root) { Stack<BinaryTreeNode> stack = new Stack<>(); BinaryTreeNode node = root; // 訪問根節點時判斷其右子樹是夠被訪問過 BinaryTreeNode preNode = null; while (node != null || stack.size() > 0) { // 把當前節點的左側節點全部入棧 while (node != null) { stack.push(node); node = node.left; } if (stack.size() > 0) { BinaryTreeNode temp = stack.peek().right; // 一個根節點被訪問的前提是:無右子樹或右子樹已被訪問過 if (temp == null || temp == preNode) { node = stack.pop(); visit(node); preNode = node;// 記錄剛被訪問過的節點 node = null; } else { // 處理右子樹 node = temp; } } } } /** 非遞迴使用雙棧實現二叉樹後序遍歷 */ public static void iterativePostOrderByTwoStacks(BinaryTreeNode root) { Stack<BinaryTreeNode> stack = new Stack<>(); Stack<BinaryTreeNode> temp = new Stack<>(); BinaryTreeNode node = root; while (node != null || stack.size() > 0) { // 把當前節點和其右側子結點推入棧 while (node != null) { stack.push(node); temp.push(node); node = node.right; } // 處理棧頂節點的左子樹 if (stack.size() > 0) { node = stack.pop(); node = node.left; } } while (temp.size() > 0) { node = temp.pop(); visit(node); } } /** 二叉樹廣度優先遍歷——層序遍歷 */ public static void layerTraversal(BinaryTreeNode root) { Queue<BinaryTreeNode> queue = new LinkedList<>(); if (root != null) { queue.add(root); while (!queue.isEmpty()) { BinaryTreeNode currentNode = queue.poll(); visit(currentNode); if (currentNode.left != null) { queue.add(currentNode.left); } if (currentNode.right != null) { queue.add(currentNode.right); } } } } public static void main(String[] args) { // 構造二叉樹 // 1 // / \ // 2 3 // / / \ // 4 5 7 // \ / // 6 8 BinaryTreeNode root = new BinaryTreeNode(1); BinaryTreeNode node2 = new BinaryTreeNode(2); BinaryTreeNode node3 = new BinaryTreeNode(3); BinaryTreeNode node4 = new BinaryTreeNode(4); BinaryTreeNode node5 = new BinaryTreeNode(5); BinaryTreeNode node6 = new BinaryTreeNode(6); BinaryTreeNode node7 = new BinaryTreeNode(7); BinaryTreeNode node8 = new BinaryTreeNode(8); root.left = node2; root.right = node3; node2.left = node4; node3.left = node5; node3.right = node7; node5.right = node6; node7.left = node8; System.out.println("二叉樹先序遍歷"); preOrder(root); System.out.println("二叉樹先序遍歷非遞迴"); iterativePreorder(root); System.out.println("二叉樹中序遍歷"); inOrder(root); System.out.println("二叉樹中序遍歷非遞迴"); iterativeInOrder(root); System.out.println("二叉樹後序遍歷"); postOrder(root); System.out.println("二叉樹單棧非遞迴後序遍歷"); iterativePostOrder(root); System.out.println("二叉樹雙棧非遞迴後序遍歷"); iterativePostOrderByTwoStacks(root); System.out.println("二叉樹層樹序遍歷"); layerTraversal(root); } }