遍历二叉树的递归方法使用了函数栈,非递归方法使用了申请的栈,
两者的额外空间都与树的高度有关,所以空间复杂度为O(h),h为二叉树的高度。
可以使用二叉树叶子节点中大量指向null的指针实现空间复杂度O(1)的遍历。
Morris遍历的实质就是避免使用栈结构,让下层到上层有指针,
具体是通过让底层节点指向null的空闲指针指回上层的某个节点,从而完成下层到上层的移动。
先序中序后序主要基于两个主要步骤,然后输出的位置有所不同,以中序遍历为例。
中序遍历:
1、假设当前子树的头节点为h,让h的左子树中最右节点的right指针指向h,
然后h的左子树继续步骤1的处理过程,直到遇到某一个节点没有左子树时记为node,进入步骤2。
2、从node开始通过每个节点的right指针进行移动并以此打印,假设移动到的节点为cur。
对每一个cur节点都判断cur节点的左子树中最右节点是否指向cur。
Ⅰ 如果是,令cur节点的左子树中最右节点的right指针指向null,即恢复树的本来面貌,
然后打印cur,继续通过cur的right指针移动到下一个节点。重复步骤2。
Ⅱ 如果不是,以cur为头的子树重回步骤1执行。
public void morrisIn(TreeNode root) { if (root == null) return; TreeNode cur1 = root; TreeNode cur2 = null; while (cur1 != null) { cur2 = cur1.left; if (cur2 != null) { // 找到cur1左子树的最右节点 while (cur2.right != null && cur2.right != cur1) cur2 = cur2.right; // cur2.right == null 则往上链接 if (cur2.right == null) { cur2.right = cur1; cur1 = cur1.left; continue; } // cur2.right == cur1 则取消链接 else { cur2.right = null; } } System.out.println(cur1.val); cur1 = cur1.right; } }
先序遍历:
和中序遍历相比差别不大,调整了打印顺序。
public void morrisPre(TreeNode root) { if (root == null) return; TreeNode cur1 = root; TreeNode 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; System.out.println(cur1.val); cur1 = cur1.left; continue; } else { cur2.right = null; } } else { System.out.println(cur1.val); } cur1 = cur1.right; } }
后序遍历:
复杂一些,依次逆序打印所有节点的左子树的右边界,打印的时机放在步骤2的条件Ⅰ被触发的时候。
public void morrisPos(TreeNode root) { if (root == null) return; TreeNode cur1 = root; TreeNode 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(root); } public void printEdge(TreeNode root) { TreeNode tail = reverseEdge(root); TreeNode cur = tail; while (cur != null) { System.out.println(cur.val); cur = cur.right; } reverseEdge(tail); } public TreeNode reverseEdge(TreeNode from) { TreeNode pre = null; TreeNode next = null; while (from != null) { next = from.right; from.right = pre; pre = from; from = next; } return pre; }
全部代码含主函数
package tools; public class Morris { public class TreeNode { public int val; public TreeNode left; public TreeNode right; public TreeNode(int x) { this.val = x; } } public void morrisIn(TreeNode root) { if (root == null) return; TreeNode cur1 = root; TreeNode cur2 = null; while (cur1 != null) { cur2 = cur1.left; if (cur2 != null) { // 找到cur1左子树的最右节点 while (cur2.right != null && cur2.right != cur1) cur2 = cur2.right; // cur2.right == null 则往上链接 if (cur2.right == null) { cur2.right = cur1; cur1 = cur1.left; continue; } // cur2.right == cur1 则取消链接 else { cur2.right = null; } } System.out.println(cur1.val); cur1 = cur1.right; } } public void morrisPre(TreeNode root) { if (root == null) return; TreeNode cur1 = root; TreeNode 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; System.out.println(cur1.val); cur1 = cur1.left; continue; } else { cur2.right = null; } } else { System.out.println(cur1.val); } cur1 = cur1.right; } } public void morrisPos(TreeNode root) { if (root == null) return; TreeNode cur1 = root; TreeNode 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(root); } public void printEdge(TreeNode root) { TreeNode tail = reverseEdge(root); TreeNode cur = tail; while (cur != null) { System.out.println(cur.val); cur = cur.right; } reverseEdge(tail); } public TreeNode reverseEdge(TreeNode from) { TreeNode pre = null; TreeNode next = null; while (from != null) { next = from.right; from.right = pre; pre = from; from = next; } return pre; } public static void main(String[] args) { // TODO Auto-generated method stub Morris m = new Morris(); TreeNode t1 = m.new TreeNode(4); TreeNode t2 = m.new TreeNode(2); TreeNode t3 = m.new TreeNode(6); TreeNode t4 = m.new TreeNode(1); TreeNode t5 = m.new TreeNode(3); TreeNode t6 = m.new TreeNode(5); TreeNode t7 = m.new TreeNode(7); t1.left = t2; t1.right = t3; t2.left = t4; t2.right = t5; t3.left = t6; t3.right = t7; m.morrisPre(t1); m.morrisIn(t1); m.morrisPos(t1); } }
Morris.java
原文地址:https://www.cnblogs.com/wangkaipeng/p/9813856.html
时间: 2024-10-20 04:29:33