博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Morris算法-----二叉树遍历
阅读量:6711 次
发布时间:2019-06-25

本文共 3976 字,大约阅读时间需要 13 分钟。

一、算法介绍

  Morris算法充分利用了二叉树叶子节点下的空间,从而可以在时间复杂度为O(N),空间复杂度为O(1)的条件下,前中后序遍历二叉树(不是完全二叉树也可以使用)。

  而常见的遍历二叉树的方法为递归和栈迭代,这两种方法的时间复杂度虽然也为O(N),但是空间复杂度需要O(N),因此Morris算法可以极大节省空间。

二、算法原理

  首先来到当前节点记为cur。

  1.如果cur无左孩子,cur向右移动。

  2.如果cur有左孩子,那么找到cur左子树的最右的节点,记为mostRight。

    2.1如果mostRight的right指针指向空,则让其指向cur,然后cur向左移动

    2.2如果mostRight的right指针指向cur,让其指回空,然后cur向右移动。

三、算法实现

  1.前序遍历

1 public static void morrisPre(Node head) { 2         if (head == null) { 3             return; 4         } 5         Node cur = head; 6         Node mostRight = null; 7         while (cur != null) { 8             mostRight = cur.left; 9             if (mostRight != null) {
//当cur有左孩子10 while (mostRight.right != null && mostRight.right != cur) {11 mostRight = mostRight.right;//找到左子树最右的孩子节点12 }13 if (mostRight.right == null) {
//如果指向空则让其指向cur,cur左移14 mostRight.right = cur;15 System.out.print(cur.value + " ");16 cur = cur.left;17 continue;18 } else {19 mostRight.right = null;//否则让其指向空20 }21 } else {22 System.out.print(cur.value + " ");23 }24 cur = cur.right;//右移25 }26 System.out.println();27 }

  2.中序遍历

1     public static void morrisIn(Node head){ 2         if(head==null){ 3             return; 4         } 5         Node cur = head; //当前节点 6         Node mostRight = null; //左子树的最右节点 7         while(cur!=null){ 8             mostRight = cur.left; 9             if(mostRight!=null){
//当cur的有左孩子10 while(mostRight.right!=null&&mostRight.right!=cur){
//找到左子树最右孩子11 mostRight = mostRight.right;12 }13 if(mostRight.right==null){
//如果指向空则让其指向cur,cur左移14 mostRight.right = cur;15 cur = cur.left;16 continue;17 }else{18 mostRight.right=null;19 }20 }21 System.out.print(cur.value+" ");22 cur = cur.right;23 }24 System.out.println();25 }

  3.后序遍历

  前序遍历和中序遍历本质上并没有太大的区别,但Morris的后序遍历有较大的改动。

  由于递归等版本的遍历二叉树后序遍历是在第三次到达节点的时候打印本次节点,但是Morris遍历只能到达一个节点两次。

  因此可以采用到达该节点第二次的时候打印该节点左子树的逆序右边界的方法来打印后序遍历。

  例如有一颗二叉树     4

         2    6

      1    3  5  7    

  其中右边界分别为1  ,  3     2   ,   5   ,  7     6    4

  其中要用到

  

  反转链表

1 public static Node reverseEdge(Node from){ 2         Node pre = null; 3         Node next = null; 4         while(from!=null){ 5             next = from.right; 6             from.right = pre; 7             pre = from; 8             from = next; 9         }10         return pre;11     }

  

  打印边界函数

1 public static void printEdge(Node head){2         Node tail = reverseEdge(head);3         Node cur = tail;4         while(cur!=null){5             System.out.print(cur.value+" ");6             cur = cur.right;7         }8         reverseEdge(tail);9     }

  

  后序遍历函数

1     public static void morrisPos(Node head){ 2         if(head==null){ 3             return; 4         } 5         Node cur = head; 6         Node mostRight = null; 7         while(cur!=null){ 8             mostRight = cur.left; 9             if(mostRight!=null){10                 while(mostRight.right!=null&&mostRight.right!=cur){11                     mostRight = mostRight.right;12                 }13                 if(mostRight.right==null){  //第一次到达14                     mostRight.right = cur;15                     cur = cur.left;16                     continue;17                 }else{  //第二次到达18                     mostRight.right = null;19                     printEdge(cur.left);20                 }21             }22             cur = cur.right;23         }24         printEdge(head);//最后再单独打印最右边界25         System.out.println();26     }

 

   

转载于:https://www.cnblogs.com/blzm742624643/p/10021388.html

你可能感兴趣的文章
【Machine Learning in Action --4】朴素贝叶斯过滤网站的恶意留言
查看>>
Ubuntu+Eclipse+ADT+Genymotion+VirtualBox开发环境搭建
查看>>
Android 学习之 开源项目PullToRefresh的使用
查看>>
Matplot中文乱码完美解决方式
查看>>
tomcat的webappclassloader中一个奇怪的异常信息
查看>>
漫谈程序猿系列:群星闪耀的黄金时代
查看>>
2016百度编程题:蘑菇阵
查看>>
webpack系列之一总览
查看>>
如何打造BCH使用的刚性需求?
查看>>
一个小需求引发的思考
查看>>
慎用System.nanoTime()
查看>>
算法的时间复杂度
查看>>
基础设施即代码:Terraform和AWS无服务器
查看>>
反模式的经典 - Mockito设计解析
查看>>
Visual Studio 15.7预览版4改进Git、C++支持
查看>>
微软宣布支持基于虚拟机的Azure IOT Edge服务
查看>>
来自社区的Visual Studio Code使用体验和教程
查看>>
[deviceone开发]-cnodejs论坛移动端App
查看>>
智能指针shared_ptr(effective modern c++笔记)
查看>>
NSDate格式化小例
查看>>