二叉树的莫里斯遍历

二叉树常规的遍历方法是用递归来实现的,这种方法一般都需要O(n)的空间复杂度和O(n)的时间复杂度。而Morris方法实现的是O(1)的空间复杂度和O(n)的时间复杂度。
我们知道,遍历二叉树时,最大的难点在于,遍历到子节点的时候怎样重新返回到父节点(假设节点中没有指向父节点的p指针),由于不能用栈作为辅助空间。为了解决这个问题,Morris方法用到了线索二叉树(threaded binary tree)的概念。在Morris方法中不需要为每个节点额外分配指针指向其前驱(predecessor)和后继节点(successor),只需要利用叶子节点中的左右空指针指向某种顺序遍历下的前驱节点或后继节点就可以了

一、中序遍历的Morris方法

步骤:

  1. 如果当前节点的左孩子为空,则输出当前节点并将其右孩子作为当前节点。

  2. 如果当前节点的左孩子不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点。

    a) 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点。当前节点更新为当前节点的左孩子。

    b) 如果前驱节点的右孩子为当前节点,将它的右孩子重新设为空(恢复树的形状)。输出当前节点。当前节点更新为当前节点的右孩子。

  3. 重复以上1、2直到当前节点为空。

    二叉树的莫里斯遍历_第1张图片

    复杂度分析
    空间上只使用了两个辅助指针,所以复杂度为O(1)。直觉上,认为它的复杂度是O(nlgn),因为找单个节点的前驱节点与树的高度有关。但事实上,寻找所有节点的前驱节点只需要O(n)时间。n个节点的二叉树中一共有n-1条边,整个过程中每条边最多只走2次,一次是为了定位到某个节点,另一次是为了寻找上面某个节点的前驱节点,如下图所示,其中红色是为了定位到某个节点,黑色线是为了找到前驱节点。所以复杂度为O(n)。

至于Morris的前序算法,和中序算法基本一样,只是输出的时机不同而已。

你可能感兴趣的:(二叉树的莫里斯遍历)