1. 程式人生 > >二叉樹的廣度優先遍歷、深度優先遍歷的遞歸和非遞歸實現方式

二叉樹的廣度優先遍歷、深度優先遍歷的遞歸和非遞歸實現方式

root 中序遍歷 queue push stack pop pac imp current

二叉樹的遍歷方式:

1、深度優先:遞歸,非遞歸實現方式

  1)先序遍歷:先訪問根節點,再依次訪問左子樹和右子樹

  2)中序遍歷:先訪問左子樹,再訪問根節點嗎,最後訪問右子樹

  3)後序遍歷:先訪問左子樹,再訪問右子樹,最後訪問根節點

2、廣度優先

按照樹的深度,一層一層的訪問樹的節點

  1 package Solution;
  2 
  3 import java.util.LinkedList;
  4 import java.util.Queue;
  5 import java.util.Stack;
  6 
  7 
  8 public class BinaryTree {
9 10 // 二叉樹節點 11 public static class BinaryTreeNode { 12 int value; 13 BinaryTreeNode left; 14 BinaryTreeNode right; 15 16 public BinaryTreeNode(int value) { 17 this.value = value; 18 } 19 20 public BinaryTreeNode(int value, BinaryTreeNode left,
21 BinaryTreeNode right) { 22 super(); 23 this.value = value; 24 this.left = left; 25 this.right = right; 26 } 27 28 } 29 30 // 訪問樹的節點 31 public static void visit(BinaryTreeNode node) { 32 System.out.println(node.value);
33 } 34 35 /** 遞歸實現二叉樹的先序遍歷 */ 36 public static void preOrder(BinaryTreeNode node) { 37 if (node != null) { 38 visit(node); 39 preOrder(node.left); 40 preOrder(node.right); 41 } 42 } 43 44 /** 遞歸實現二叉樹的中序遍歷 */ 45 public static void inOrder(BinaryTreeNode node) { 46 if (node != null) { 47 inOrder(node.left); 48 visit(node); 49 inOrder(node.right); 50 } 51 } 52 53 /** 遞歸實現二叉樹的後序遍歷 */ 54 public static void postOrder(BinaryTreeNode node) { 55 if (node != null) { 56 postOrder(node.left); 57 postOrder(node.right); 58 visit(node); 59 } 60 } 61 62 /** 非遞歸實現二叉樹的先序遍歷 */ 63 public static void iterativePreorder(BinaryTreeNode node) { 64 Stack<BinaryTreeNode> stack = new Stack<>(); 65 if (node != null) { 66 stack.push(node); 67 while (!stack.empty()) { 68 node = stack.pop(); 69 // 先訪問節點 70 visit(node); 71 // 把右子結點壓入棧 72 if (node.right != null) { 73 stack.push(node.right); 74 } 75 // 把左子結點壓入棧 76 if (node.left != null) { 77 stack.push(node.left); 78 } 79 } 80 } 81 } 82 83 /** 非遞歸實現二叉樹的中序遍歷 */ 84 public static void iterativeInOrder(BinaryTreeNode root) { 85 Stack<BinaryTreeNode> stack = new Stack<>(); 86 BinaryTreeNode node = root; 87 while (node != null || stack.size() > 0) { 88 // 把當前節點的所有左側子結點壓入棧 89 while (node != null) { 90 stack.push(node); 91 node = node.left; 92 } 93 // 訪問節點,處理該節點的右子樹 94 if (stack.size() > 0) { 95 node = stack.pop(); 96 visit(node); 97 node = node.right; 98 } 99 } 100 } 101 102 /** 非遞歸使用單棧實現二叉樹後序遍歷 */ 103 public static void iterativePostOrder(BinaryTreeNode root) { 104 Stack<BinaryTreeNode> stack = new Stack<>(); 105 BinaryTreeNode node = root; 106 // 訪問根節點時判斷其右子樹是夠被訪問過 107 BinaryTreeNode preNode = null; 108 while (node != null || stack.size() > 0) { 109 // 把當前節點的左側節點全部入棧 110 while (node != null) { 111 stack.push(node); 112 node = node.left; 113 } 114 if (stack.size() > 0) { 115 BinaryTreeNode temp = stack.peek().right; 116 // 一個根節點被訪問的前提是:無右子樹或右子樹已被訪問過 117 if (temp == null || temp == preNode) { 118 node = stack.pop(); 119 visit(node); 120 preNode = node;// 記錄剛被訪問過的節點 121 node = null; 122 } else { 123 // 處理右子樹 124 node = temp; 125 } 126 } 127 } 128 } 129 130 /** 非遞歸使用雙棧實現二叉樹後序遍歷 */ 131 public static void iterativePostOrderByTwoStacks(BinaryTreeNode root) { 132 Stack<BinaryTreeNode> stack = new Stack<>(); 133 Stack<BinaryTreeNode> temp = new Stack<>(); 134 BinaryTreeNode node = root; 135 while (node != null || stack.size() > 0) { 136 // 把當前節點和其右側子結點推入棧 137 while (node != null) { 138 stack.push(node); 139 temp.push(node); 140 node = node.right; 141 } 142 // 處理棧頂節點的左子樹 143 if (stack.size() > 0) { 144 node = stack.pop(); 145 node = node.left; 146 } 147 } 148 while (temp.size() > 0) { 149 node = temp.pop(); 150 visit(node); 151 } 152 } 153 154 /** 二叉樹廣度優先遍歷——層序遍歷 */ 155 public static void layerTraversal(BinaryTreeNode root) { 156 Queue<BinaryTreeNode> queue = new LinkedList<>(); 157 158 if (root != null) { 159 queue.add(root); 160 while (!queue.isEmpty()) { 161 BinaryTreeNode currentNode = queue.poll(); 162 visit(currentNode); 163 if (currentNode.left != null) { 164 queue.add(currentNode.left); 165 } 166 167 if (currentNode.right != null) { 168 queue.add(currentNode.right); 169 } 170 171 } 172 } 173 } 174 175 public static void main(String[] args) { 176 177 // 構造二叉樹 178 // 1 179 // / 180 // 2 3 181 // / / 182 // 4 5 7 183 // \ / 184 // 6 8 185 BinaryTreeNode root = new BinaryTreeNode(1); 186 BinaryTreeNode node2 = new BinaryTreeNode(2); 187 BinaryTreeNode node3 = new BinaryTreeNode(3); 188 BinaryTreeNode node4 = new BinaryTreeNode(4); 189 BinaryTreeNode node5 = new BinaryTreeNode(5); 190 BinaryTreeNode node6 = new BinaryTreeNode(6); 191 BinaryTreeNode node7 = new BinaryTreeNode(7); 192 BinaryTreeNode node8 = new BinaryTreeNode(8); 193 194 root.left = node2; 195 root.right = node3; 196 node2.left = node4; 197 node3.left = node5; 198 node3.right = node7; 199 node5.right = node6; 200 node7.left = node8; 201 System.out.println("二叉樹先序遍歷"); 202 preOrder(root); 203 System.out.println("二叉樹先序遍歷非遞歸"); 204 iterativePreorder(root); 205 System.out.println("二叉樹中序遍歷"); 206 inOrder(root); 207 System.out.println("二叉樹中序遍歷非遞歸"); 208 iterativeInOrder(root); 209 System.out.println("二叉樹後序遍歷"); 210 postOrder(root); 211 System.out.println("二叉樹單棧非遞歸後序遍歷"); 212 iterativePostOrder(root); 213 System.out.println("二叉樹雙棧非遞歸後序遍歷"); 214 iterativePostOrderByTwoStacks(root); 215 System.out.println("二叉樹層樹序遍歷"); 216 layerTraversal(root); 217 } 218 }

二叉樹的廣度優先遍歷、深度優先遍歷的遞歸和非遞歸實現方式