Moris遍历
Morris方法用到了线索二叉树(threaded binary tree)的概念。在Morris方法中不需要为每个节点额外分配指针指向其前驱(predecessor)和后继节点(successor),只需要利用叶子节点中的左右空指针指向某种顺序遍历下的前驱节点或后继节点就可以了。
只需要O(1)的空间 时间复杂度O(n)
当前节点为cur (引用)
(1)如果cur无左孩子,cur向右移动(cur=cur.right)
(2)如果cur有左孩子 找到cur左子树上最右的节点,记为mostright
如果mostright的右指针指向空 让其指向cur cur向左移动
如果mostright的右指针指向cur,让其指回空,cur向右移动
下面贴出代码:(中序遍历)
public class Solution {
public static void morrisIn(Node head)
{
if(head==null)
{
return;
}
Node cur=head;
Node mostRight=null;
while(cur!=null)
{
mostRight=cur.left;
if(mostRight!=null) //cur有左孩子
{
//找到cur左子树上的最右的节点 记为mostRight
while(mostRight.right!=null&& mostRight.right!=cur)
{
mostRight=mostRight.right;
}
if(mostRight.right==null) //右指针为空 让其指向cur cur向左移动
{
mostRight.right=cur;
cur=cur.left;
continue;
}
else
{
mostRight.right=null; //右指针指向cur,让其指回空,cur向右移动
}
}
System.out.print(cur.value+" ");
cur=cur.right; //cur无左孩子 向右移动
}
}
正好刷到了LeetCode上的第99题 恢复二叉树 题目是这样子的:
利用Moris遍历(贴了个Leetcode上的代码 参考一下)
public static void recoverTree(TreeNode root) {
if (null == root) {
return;
}
TreeNode node1 = null;
TreeNode node2 = null;
TreeNode mostRight = null;
TreeNode cur = root;
TreeNode pre = null;
while (cur != null) {
mostRight = cur.left;
if (mostRight != null) {
while (mostRight.right != null && mostRight.right != cur) {
mostRight = mostRight.right;
}
if (mostRight.right == null) {
mostRight.right = cur;
cur = cur.left;
continue;
} else { // 第二次遍历到了
mostRight.right = null;
}
}
if (pre != null && pre.val > cur.val) {
node1 = node1 == null ? pre : node1;
node2 = cur;
}
pre = cur;
cur = cur.right;
}
int temp = node1.val;
node1.val = node2.val;
node2.val = temp;
}
作者:begoogler
链接:https://leetcode-cn.com/problems/recover-binary-search-tree/solution/java-morrisxu-lie-by-begoogler/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
前序遍历与中序遍历相似,代码上只有一行不同,不同就在于输出的顺序。
后序遍历: 后序遍历 逆序打印第二次来的结点的左子树的右边界 再单独打印整棵树的右边界
public class Solution {
public static void morrisIn(Node head)
{
if(head==null)
{
return;
}
Node cur=head;
Node mostRight=null;
while(cur!=null)
{
mostRight=cur.left;
if(mostRight!=null) //cur有左孩子
{
//找到cur左子树上的最右的节点 记为mostRight
while(mostRight.right!=null&& mostRight.right!=cur)
{
mostRight=mostRight.right;
}
if(mostRight.right==null) //右指针为空 让其指向cur cur向左移动
{
mostRight.right=cur;
System.out.print(cur.value+" "); //中序打印
cur=cur.left;
continue;
}
else
{
mostRight.right=null; //右指针指向cur,让其指回空,cur向右移动
printEdge(mostRight.left); //逆序打印可以经过两次的左子树的右边界(后序)
}
// else
// {
// System.out.print(cur.value+" ");
// }
}
System.out.print(cur.value+" ");
cur=cur.right; //cur无左孩子 向右移动
}
printEdge(head); //逆序打印整棵树的右边界(后序)
}
}
}
写的有点乱 太困了 明天继续!