二叉树的基本遍历方法
2012-07-09 17:16 coodoing 阅读(291) 评论(0) 编辑 收藏 举报View Code
1 package Tree; 2 3 import java.util.Stack; 4 public class BinaryTreeTraversal { 5 protected Node root; 6 7 public BinaryTreeTraversal(Node root) { 8 this.root = root; 9 } 10 11 public Node getRoot() { 12 return root; 13 } 14 15 /** 构造树 */ 16 public static Node init() { 17 Node a = new Node('A'); 18 Node b = new Node('B', null, a); 19 Node c = new Node('C'); 20 Node d = new Node('D', b, c); 21 Node e = new Node('E'); 22 Node f = new Node('F', e, null); 23 Node g = new Node('G', null, f); 24 Node h = new Node('H', d, g); 25 return h;// root 26 } 27 28 /** 访问节点 */ 29 public static void visit(Node p) { 30 System.out.print(p.getKey() + " "); 31 } 32 33 /** 递归实现前序遍历 */ 34 protected static void preorder(Node p) { 35 if (p != null) { 36 visit(p); 37 preorder(p.getLeft()); 38 preorder(p.getRight()); 39 } 40 } 41 42 /** 递归实现中序遍历 */ 43 protected static void inorder(Node p) { 44 if (p != null) { 45 inorder(p.getLeft()); 46 visit(p); 47 inorder(p.getRight()); 48 } 49 } 50 51 /** 递归实现后序遍历 */ 52 protected static void postorder(Node p) { 53 if (p != null) { 54 postorder(p.getLeft()); 55 postorder(p.getRight()); 56 visit(p); 57 } 58 } 59 60 /**********************************************************************************************/ 61 /** 非递归实现前序遍历 */ 62 protected static void iterativePreorder(Node p) { 63 Stack<Node> stack = new Stack<Node>(); 64 if (p != null) { 65 stack.push(p); 66 while (!stack.empty()) { 67 p = stack.pop(); 68 visit(p); 69 //为什么p.getLeft() 在后,getRight()在前应为while 循环第一句就是pop visit所以要把left放上,先访问。之中方法是即压即访问法。 70 if (p.getRight() != null) 71 stack.push(p.getRight()); 72 if (p.getLeft() != null) 73 stack.push(p.getLeft()); 74 } 75 } 76 } 77 78 /** 非递归实现中序遍历 */ 79 //思路与上面iterativePreorder 一致。 80 protected static void iterativeInorder(Node p) { 81 Stack<Node> stack = new Stack<Node>(); 82 while (p != null) { 83 while (p != null) { 84 if (p.getRight() != null) 85 stack.push(p.getRight());// 当前节点右子入栈 86 stack.push(p);// 当前节点入栈 87 p = p.getLeft(); 88 } 89 p = stack.pop(); 90 while (!stack.empty() && p.getRight() == null) { 91 visit(p); 92 p = stack.pop(); 93 } 94 visit(p); 95 if (!stack.empty()) 96 p = stack.pop(); 97 else 98 p = null; 99 } 100 } 101 102 /*******************************************************************************************/ 103 104 /*******************************************************************************************/ 105 /** 非递归实现前序遍历2 */ 106 protected static void iterativePreorder2(Node p) { 107 Stack<Node> stack = new Stack<Node>(); 108 Node node = p; 109 while (node != null || stack.size() > 0) { 110 while (node != null) {//压入所有的左节点,压入前访问它。左节点压入完后pop访问右节点。像这样算法时思考规律性的东西在哪。不管哪个节点都要压所节点判断右节点。 111 visit(node); 112 stack.push(node); 113 node = node.getLeft(); 114 } 115 if (stack.size() > 0) {// 116 node = stack.pop(); 117 node = node.getRight(); 118 } 119 } 120 } 121 122 /** 非递归实现中序遍历2 */ 123 protected static void iterativeInorder2(Node p) { 124 Stack<Node> stack = new Stack<Node>(); 125 Node node = p; 126 while (node != null || stack.size() > 0) { 127 while (node != null) { 128 stack.push(node); 129 node = node.getLeft(); 130 } 131 if (stack.size() > 0) { 132 node = stack.pop(); 133 visit(node); //与iterativePreorder2比较只有这句话的位置不一样,弹出时再访问。 134 node = node.getRight(); 135 } 136 } 137 } 138 139 /*******************************************************************************************/ 140 141 /** 非递归实现后序遍历 */ 142 protected static void iterativePostorder(Node p) { 143 Node q = p; 144 Stack<Node> stack = new Stack<Node>(); 145 while (p != null) { 146 // 左子树入栈 147 for (; p.getLeft() != null; p = p.getLeft()) 148 stack.push(p); 149 // 当前节点无右子或右子已经输出 150 while (p != null && (p.getRight() == null || p.getRight() == q)) { 151 visit(p); 152 q = p;// 记录上一个已输出节点 153 if (stack.empty()) 154 return; 155 p = stack.pop(); 156 } 157 // 处理右子 158 stack.push(p); 159 p = p.getRight(); 160 } 161 } 162 163 /** 非递归实现后序遍历 双栈法 */ 164 protected static void iterativePostorder2(Node p) { 165 //理解左子树 右子树 根递归性质,把它运用到循环当中去。 166 Stack<Node> lstack = new Stack<Node>();//左子树栈 167 Stack<Node> rstack = new Stack<Node>();//右子树栈 168 Node node = p, right; 169 do { 170 while (node != null) { 171 right = node.getRight(); 172 lstack.push(node); 173 rstack.push(right); 174 node = node.getLeft(); 175 } 176 node = lstack.pop(); 177 right = rstack.pop(); 178 // 前面已经保证node节点无左节点了 179 if (right == null) { 180 visit(node); 181 } else { 182 lstack.push(node); 183 rstack.push(null);//??? 184 } 185 node = right; //继续访问右子树 186 } while (lstack.size() > 0 || rstack.size() > 0); 187 } 188 189 /** 非递归实现后序遍历 单栈法*/ 190 protected static void iterativePostorder3(Node p) { 191 Stack<Node> stack = new Stack<Node>(); 192 Node node = p, prev = p; 193 while (node != null || stack.size() > 0) { 194 while (node != null) { 195 stack.push(node); 196 node = node.getLeft(); 197 } 198 if (stack.size() > 0) { 199 Node temp = stack.peek().getRight(); 200 if (temp == null || temp == prev) { 201 node = stack.pop(); 202 visit(node); 203 prev = node; 204 node = null; 205 } else { 206 node = temp; 207 } 208 } 209 210 } 211 } 212 213 /** 非递归实现后序遍历4 双栈法*/ 214 protected static void iterativePostorder4(Node p) { 215 Stack<Node> stack = new Stack<Node>(); 216 Stack<Node> temp = new Stack<Node>(); 217 Node node = p; 218 while (node != null || stack.size() > 0) { 219 while (node != null) { 220 temp.push(node); 221 stack.push(node); 222 node = node.getRight(); 223 } 224 if (stack.size() > 0) { 225 node = stack.pop(); 226 node = node.getLeft(); 227 } 228 } 229 while (temp.size() > 0) {//把插入序列都插入到了temp。 230 node = temp.pop(); 231 visit(node); 232 } 233 } 234 235 /** 236 * @param args 237 */ 238 public static void main(String[] args) { 239 BinaryTreeTraversal tree = new BinaryTreeTraversal(init()); 240 System.out.print(" 递归遍历 \n"); 241 System.out.print(" Pre-Order:"); 242 preorder(tree.getRoot()); 243 244 System.out.print(" \n In-Order:"); 245 inorder(tree.getRoot()); 246 247 System.out.print("\n Post-Order:"); 248 postorder(tree.getRoot()); 249 250 System.out.print(" \n非递归遍历"); 251 System.out.print(" \n Pre-Order:"); 252 iterativePreorder(tree.getRoot()); 253 254 System.out.print("\n Pre-Order2:"); 255 iterativePreorder2(tree.getRoot()); 256 257 System.out.print(" \n In-Order:"); 258 iterativeInorder(tree.getRoot()); 259 260 System.out.print("\n In-Order2:"); 261 iterativeInorder2(tree.getRoot()); 262 263 System.out.print("\n Post-Order:"); 264 iterativePostorder(tree.getRoot()); 265 266 System.out.print("\n Post-Order2:"); 267 iterativePostorder2(tree.getRoot()); 268 269 System.out.print("\n Post-Order3:"); 270 iterativePostorder3(tree.getRoot()); 271 272 System.out.print("\n Post-Order4:"); 273 iterativePostorder4(tree.getRoot()); 274 275 } 276 277 } 278 279 class Node { 280 private char key; 281 private Node left, right; 282 283 public Node(char key) { 284 this(key, null, null); 285 } 286 287 public Node(char key, Node left, Node right) { 288 this.key = key; 289 this.left = left; 290 this.right = right; 291 } 292 293 public char getKey() { 294 return key; 295 } 296 297 public void setKey(char key) { 298 this.key = key; 299 } 300 301 public Node getLeft() { 302 return left; 303 } 304 305 public void setLeft(Node left) { 306 this.left = left; 307 } 308 309 public Node getRight() { 310 return right; 311 } 312 313 public void setRight(Node right) { 314 this.right = right; 315 } 316 }