问题:以非递归方式遍历二叉树(先序遍历 后序遍历 中序遍历)
思路:模拟递归方式的调用,为每个节点创建堆栈Flash,在pop时候判断当前节点是第几次访问,然后决定是否打印当前节点值以及为左右子节点创建堆栈Flash并入栈
// 模拟递归调用函数栈
static class Flash{
private Node node;
private boolean visited;
private int count;
public Flash(Node node, boolean visited) {
this.node = node;
this.visited = visited;
}
public void setCount(int count){
this.count = count;
}
}
// 完全模拟递归调用 先序遍历
public static void fun(Node head){
if(head == null)
return;
Flash flash = new Flash(head, false);
flash.count = 1;
Stack<Flash> stack = new Stack<>();
stack.push(flash);
while (!stack.isEmpty()){
Flash cur = stack.pop();
// 这里使用 visited 替代count
// 第二次
/*if(cur.visited){
if(cur.node.right!=null){
stack.push(new Flash(cur.node.right,false));
}
}else{
// 第一次
System.out.println(cur.node.value);
cur.visited = true;
stack.push(cur);
if(cur.node.left != null){
stack.push(new Flash(cur.node.left,false));
}
}*/
// another
if(cur.count == 1){
// 第一次访问
System.out.println(cur.node.value);
cur.count++;
stack.push(cur);
if(cur.node.left != null){
Flash flash1 = new Flash(cur.node.left, false);
flash1.count = 1;
stack.push(flash1);
}
}else if (cur.count == 2){
// 第二次访问
// 递归方法中,递归调用cur.node.right并返回后,没有后续其他操作,所以这里不用将当前node对应的Flash再次塞入stack
if(cur.node.right!=null){
Flash flash1 = new Flash(cur.node.right, false);
flash1.count = 1;
stack.push(flash1);
}
}else {
// 第三次访问
// 线序遍历永远不会到这里
}
}
}
// 中序遍历
public static void processin(Node head){
if(head == null)
return;
Stack<Flash> stack = new Stack<>();
Flash h = new Flash(head, false);
stack.add(h);
while (!stack.isEmpty()){
Flash cur = stack.pop();
if(!cur.visited){
cur.visited = true;
stack.push(cur);
if(cur.node.left != null){
stack.push(new Flash(cur.node.left,false));
}
}else{
System.out.print(cur.node.value+" ");
if(cur.node.right!=null){
stack.push(new Flash(cur.node.right,false));
}
}
}
}
// 后续遍历
public static void funpost(Node head){
if(head == null)
return;
Stack<Flash> stack = new Stack<>();
Flash h = new Flash(head, false);
h.setCount(1);
stack.add(h);
while (!stack.isEmpty()){
Flash cur = stack.pop();
if(cur.count == 1){
// 第一次访问该节点
cur.count ++;
stack.push(cur);
if(cur.node.left != null){
Flash flash = new Flash(cur.node.left, false);
flash.count = 1;
stack.push(flash);
}
} else if(cur.count == 2){
// 第二次访问当前节点
cur.count++;
stack.push(cur);
if(cur.node.right != null){
Flash flash = new Flash(cur.node.right, false);
flash.count = 1;
stack.push(flash);
}
} else{
// 第三次访问当前节点
System.out.println(cur.node.value);
}
}
}
// 另外一种遍历方式
public static void pre(Node head) {
System.out.print("pre-order: ");
if (head != null) {
Stack<Node> stack = new Stack<Node>();
stack.add(head);
while (!stack.isEmpty()) {
head = stack.pop();
System.out.print(head.value + " ");
if (head.right != null) {
stack.push(head.right);
}
if (head.left != null) {
stack.push(head.left);
}
}
}
System.out.println();
}
public static void in(Node cur) {
System.out.print("in-order: ");
if (cur != null) {
Stack<Node> stack = new Stack<Node>();
while (!stack.isEmpty() || cur != null) {
if (cur != null) {
stack.push(cur);
cur = cur.left;
} else {
cur = stack.pop();
System.out.print(cur.value + " ");
cur = cur.right;
}
}
}
System.out.println();
}
public static void pos1(Node head) {
System.out.print("pos-order: ");
if (head != null) {
Stack<Node> s1 = new Stack<Node>();
Stack<Node> s2 = new Stack<Node>();
s1.push(head);
while (!s1.isEmpty()) {
head = s1.pop(); // 头 右 左
s2.push(head);
if (head.left != null) {
s1.push(head.left);
}
if (head.right != null) {
s1.push(head.right);
}
}
// 左 右 头
while (!s2.isEmpty()) {
System.out.print(s2.pop().value + " ");
}
}
System.out.println();
}
public static void pos2(Node h) {
System.out.print("pos-order: ");
if (h != null) {
Stack<Node> stack = new Stack<Node>();
stack.push(h);
Node c = null;
while (!stack.isEmpty()) {
c = stack.peek();
if (c.left != null && h != c.left && h != c.right) {
stack.push(c.left);
} else if (c.right != null && h != c.right) {
stack.push(c.right);
} else {
System.out.print(stack.pop().value + " ");
h = c;
}
}
}
System.out.println();
}