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 }