二叉树的十种遍历方式

一、二叉树对象

public class Node {

    public Node left;
    public Node right;
    public String value;

    public Node() {
        super();
    }

    public Node(String value) {
        super();
        this.value = value;
    }

}

二、递归遍历

递归过程中每个节点到达三次,存在前中后三种顺序。时间复杂度O(N),空间复杂度O(N)

2.1 前序遍历

public static void preOrder(Node head) {
    if(head == null) {
        return;
    }
    System.out.print(head.value);
    preOrder(head.left);
    preOrder(head.right);
}

2.2 中序遍历

public static void midOrder(Node head) {
    if(head == null) {
        return;
    }
    midOrder(head.left);
    System.out.print(head.value);
    midOrder(head.right);
}

2.3 后续遍历

public static void afterOrder(Node head) {
    if(head == null) {
        return;
    }
    afterOrder(head.left);
    afterOrder(head.right);
    System.out.print(head.value);
}

三、非递归方式

前序遍历与中序遍历需要基于栈结构。后续遍历使用到两个栈结构。时间复杂度O(N),空间复杂度O(N)

3.1 前序遍历

    public static void preOrderByStack(Node head) {
        Stack<Node> stack = new Stack<>();
        stack.push(head);
        while(!stack.empty()) {
            Node node = stack.pop();
            System.out.print(node.value);
            if(node.right != null) {
                stack.push(node.right);
            }
            if(node.left != null) {
                stack.push(node.left);
            }
        }
    }

3.2 中序遍历

    public static void midOrderByStack(Node head) {
        Stack<Node> stack = new Stack<>();
        while(!stack.empty() || head != null) {
            if(head != null) {
                stack.push(head);
                head = head.left;
            } else {
                head = stack.pop();
                System.out.print(head.value);
                head = head.right;
            }
        }
    }

3.3 后续遍历

    public static void afterOrderByStack(Node head) {
        Stack<Node> stack = new Stack<>();
        Stack<Node> result = new Stack<>();
        stack.push(head);
        while (!stack.empty()) {
            head = stack.pop();
            result.push(head);
            if(head.left != null) {
                stack.push(head.left);
            }
            if(head.right != null) {
                stack.push(head.right);
            }
        }
        while (!result.empty()) {
            System.out.print(result.pop().value);
        }
    }

四、按层遍历

按层遍历使用到辅助队列,时间空间复杂度为O(N)

    public static String serialByLevel(Node head) {
        if (head == null) {
            return "#!";
        }
        String res = head.value + "!";
        Queue<Node> queue = new LinkedList<>();
        queue.offer(head);
        while (!queue.isEmpty()) {
            head = queue.poll();
            if (head.left != null) {
                res += head.left.value + "!";
                queue.offer(head.left);
            } else {
                res += "#!";
            }
            if (head.right != null) {
                res += head.right.value + "!";
                queue.offer(head.right);
            } else {
                res += "#!";
            }
        }
        return res;
    }

五、Morris遍历

Morris遍历时间复杂度O(N),空间复杂度O(1)

三条原则:

1、current节点如果没有左孩子,current向右移

2、current节点有左孩子,找到左子树的最右节点记为mostRight,如果mostRight的右指针为空,让其指向current,current向左移。

3、如果mostRight的右指针为current,让其为空,current向右移动。

5.1 前序遍历

    public static void morrisPre(Node head) {
		if (head == null) {
			return;
		}
		Node current = head;
		Node mostRight = null;
		while (current != null) {
			mostRight = current.left;
			if (mostRight != null) {
				while (mostRight.right != null && mostRight.right != current) {
					mostRight = mostRight.right;
				}
				if (mostRight.right == null) {
					mostRight.right = current;
					System.out.print(current.value + " ");
					current = current.left;
					continue;
				} else {
					mostRight.right = null;
				}
			} else {
				System.out.print(current.value + " ");
			}
			current = current.right;
		}
		System.out.println();
	}

5.2 中序遍历

    public static void morrisIn(Node head) {
		if (head == null) {
			return;
		}
		Node cur1 = head;
		Node cur2 = null;
		while (cur1 != null) {
			cur2 = cur1.left;
			if (cur2 != null) {
				while (cur2.right != null && cur2.right != cur1) {
					cur2 = cur2.right;
				}
				if (cur2.right == null) {
					cur2.right = cur1;
					cur1 = cur1.left;
					continue;
				} else {
					cur2.right = null;
				}
			}
			System.out.print(cur1.value + " ");
			cur1 = cur1.right;
		}
		System.out.println();
	}

5.3 后续遍历

    public static void morrisPos(Node head) {
		if (head == null) {
			return;
		}
		Node cur1 = head;
		Node cur2 = null;
		while (cur1 != null) {
			cur2 = cur1.left;
			if (cur2 != null) {
				while (cur2.right != null && cur2.right != cur1) {
					cur2 = cur2.right;
				}
				if (cur2.right == null) {
					cur2.right = cur1;
					cur1 = cur1.left;
					continue;
				} else {
					cur2.right = null;
					printEdge(cur1.left);
				}
			}
			cur1 = cur1.right;
		}
		printEdge(head);
		System.out.println();
	}

	public static void printEdge(Node head) {
		Node tail = reverseEdge(head);
		Node cur = tail;
		while (cur != null) {
			System.out.print(cur.value + " ");
			cur = cur.right;
		}
		reverseEdge(tail);
	}

	public static Node reverseEdge(Node from) {
		Node pre = null;
		Node next = null;
		while (from != null) {
			next = from.right;
			from.right = pre;
			pre = from;
			from = next;
		}
		return pre;
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值