二叉树——线索化遍历
1. Morris遍历
1.1. 思路
Morris遍历通过利用左子树前序遍历下的最后一个节点的right指针,来做到以时间复杂度为O(n)空间复杂度为O(1)的开销遍历一个二叉树。
1.2. 代码
public static void morrisPre(TreeNode root, Consumer consumer) {
TreeNode cur = root;
while (cur != null) {
if (cur.left != null) {
TreeNode leftLast = cur.left;
while (leftLast.right != null && leftLast.right != cur)
leftLast = leftLast.right;
if (leftLast.right == null) {
leftLast.right = cur;
} else {
leftLast.right = null;
cur = cur.right;
continue;
}
}
consumer.accept(cur.val);
cur = cur.left != null ? cur.left : cur.right;
}
}
public static void morrisMid(TreeNode root, Consumer consumer) {
TreeNode cur = root;
while (cur != null) {
if (cur.left != null) {
TreeNode leftLast = cur.left;
while (leftLast.right != null && leftLast.right != cur) {
leftLast = leftLast.right;
}
if (leftLast.right == null) {
leftLast.right = cur;
cur = cur.left;
continue;
} else {
leftLast.right = null;
}
}
consumer.accept(cur.val);
cur = cur.right;
}
}
public static void morrisPost(TreeNode root, Consumer consumer) {
TreeNode cur = root;
while (cur != null) {
if (cur.left != null) {
TreeNode leftLast = cur.left;
while (leftLast.right != null && leftLast.right != cur) {
leftLast = leftLast.right;
}
if (leftLast.right == null) {
leftLast.right = cur;
} else {
leftLast.right = null;
consumeRightBound(cur.left, consumer);
cur = cur.right;
continue;
}
}
cur = cur.left != null ? cur.left : cur.right;
}
consumeRightBound(root, consumer);
}
private static void consumeRightBound(TreeNode node, Consumer consumer) {
TreeNode pre = null;
TreeNode cur = node;
TreeNode next;
while (cur != null) {
next = cur.right;
cur.right = pre;
pre = cur;
cur = next;
}
cur = pre;
pre = null;
while (cur != null) {
consumer.accept(cur.val);
next = cur.right;
cur.right = pre;
pre = cur;
cur = next;
}
}