参考
算法
通过插入标志符,来标记需要输出哪个元素。
- 确定输出顺序。首次遍历结点A时,将A和其左右子结点按照遍历顺序插入到栈中,A结点后需要插入标志符。
- 输出结点元素。如果当前栈顶元素是标志符,说明A结点该输出了,输出A结点即可。
参考博文1中,用null作为标志符,这在要求输出空结点时不可行,标志符和空结点会发生冲突。要解决冲突,只需自定义标识符即可,详见下述代码。如果空结点需要区分左空结点和右空结点,可以再自定义两个标识符来处理。
前序遍历
public void preOrderTraverse3(ListNode<String> root) {
System.out.println("前根遍历-非递归");
Stack<ListNode<String>> stack = new Stack<>();
stack.push(root);
ListNode<String> cur;
ListNode<String> flag = new ListNode<>("0");//标识符
while (!stack.isEmpty()) {
cur = stack.pop();
if (cur == null) {
System.out.printf("^");
} else if (cur == flag) {
cur = stack.pop();
System.out.printf(cur.val);
} else {
stack.push(cur.right);//右
stack.push(cur.left);//左
stack.push(cur);//中
stack.push(flag);
}
}
System.out.printf("\n");
}
中序遍历
public void inOrderTraverse3(ListNode<String> root) {
System.out.println("中根遍历-非递归");
Stack<ListNode<String>> stack = new Stack<>();
stack.push(root);
ListNode<String> cur;
ListNode<String> flag = new ListNode<>("0");//标识符
while (!stack.isEmpty()) {
cur = stack.pop();
if (cur == null) {
System.out.printf("^");
} else if (cur == flag) {
cur = stack.pop();
System.out.printf(cur.val);
} else {
stack.push(cur.right);//右
stack.push(cur);//中
stack.push(flag);
stack.push(cur.left);//左
}
}
System.out.printf("\n");
}
后序遍历
public void postOrderTraverse3(ListNode<String> root) {
System.out.println("后根遍历-非递归");
Stack<ListNode<String>> stack = new Stack<>();
stack.push(root);
ListNode<String> cur;
ListNode<String> flag = new ListNode<>("0");//标识符
while (!stack.isEmpty()) {
cur = stack.pop();
if (cur == null) {
System.out.printf("^");
} else if (cur == flag) {
cur = stack.pop();
System.out.printf(cur.val);
} else {
stack.push(cur);//中
stack.push(flag);
stack.push(cur.right);//右
stack.push(cur.left);//左
}
}
System.out.printf("\n");
}