二叉樹——線索化遍歷
阿新 • • 發佈:2022-05-10
1. Morris遍歷
1.1. 思路
Morris遍歷通過利用左子樹前序遍歷下的最後一個節點的right指標,來做到以時間複雜度為O(n)空間複雜度為O(1)的開銷遍歷一個二叉樹。
1.2. 程式碼
public static <T> void morrisPre(TreeNode<T> root, Consumer<T> consumer) { TreeNode<T> cur = root; while (cur != null) { if (cur.left != null) { TreeNode<T> 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 <T> void morrisMid(TreeNode<T> root, Consumer<T> consumer) { TreeNode<T> cur = root; while (cur != null) { if (cur.left != null) { TreeNode<T> 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 <T> void morrisPost(TreeNode<T> root, Consumer<T> consumer) { TreeNode<T> cur = root; while (cur != null) { if (cur.left != null) { TreeNode<T> 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 <T> void consumeRightBound(TreeNode<T> node, Consumer<T> consumer) { TreeNode<T> pre = null; TreeNode<T> cur = node; TreeNode<T> 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; } }