【算法】Moris遍历

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);   //逆序打印整棵树的右边界(后序)
	  
	  
  }





}
	
}

 

写的有点乱 太困了 明天继续!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值