在不使用堆栈或递归的情况下解释Morris有序树遍历

头脑敏捷

有人可以在不使用堆栈或递归的情况下帮助我了解以下Morris有序树遍历算法吗?我试图理解它是如何工作的,但是它只是在逃避我。

 1. Initialize current as root
 2. While current is not NULL
  If current does not have left child     
   a. Print current’s data
   b. Go to the right, i.e., current = current->right
  Else
   a. In current's left subtree, make current the right child of the rightmost node
   b. Go to this left child, i.e., current = current->left

我知道树的修改方式current noderight child,将max nodein做成in,right subtree并使用此属性进行有序遍历。但是除此之外,我迷路了。

编辑:找到了此随附的c ++代码。我很难理解修改后的树是如何还原的。魔术在于else子句,一旦修改了正确的叶子,该子句就会被击中。有关详细信息,请参见代码:

/* Function to traverse binary tree without recursion and
   without stack */
void MorrisTraversal(struct tNode *root)
{
  struct tNode *current,*pre;

  if(root == NULL)
     return; 

  current = root;
  while(current != NULL)
  {
    if(current->left == NULL)
    {
      printf(" %d ", current->data);
      current = current->right;
    }
    else
    {
      /* Find the inorder predecessor of current */
      pre = current->left;
      while(pre->right != NULL && pre->right != current)
        pre = pre->right;

      /* Make current as right child of its inorder predecessor */
      if(pre->right == NULL)
      {
        pre->right = current;
        current = current->left;
      }

     // MAGIC OF RESTORING the Tree happens here: 
      /* Revert the changes made in if part to restore the original
        tree i.e., fix the right child of predecssor */
      else
      {
        pre->right = NULL;
        printf(" %d ",current->data);
        current = current->right;
      } /* End of if condition pre->right == NULL */
    } /* End of if condition current->left == NULL*/
  } /* End of while */
}
塔隆尼

如果我没看错算法,这应该是其工作方式的一个示例:

     X
   /   \
  Y     Z
 / \   / \
A   B C   D

首先,X是根,因此将其初始化为currentX有一个左孩子,所以X它成为X左子树的最右孩子-X有序遍历的直接前任这样X就做成了正确的孩子B,然后current设置为Y树现在看起来像这样:

    Y
   / \
  A   B
       \
        X
       / \
     (Y)  Z
         / \
        C   D

(Y)上面提到了Y及其所有子项,由于递归问题而将其省略。无论如何,重要的部分都会列出。现在树已链接回X,遍历继续...

 A
  \
   Y
  / \
(A)  B
      \
       X
      / \
    (Y)  Z
        / \
       C   D

然后A输出,因为它没有左子,然后current返回YA在上一次迭代中将其作为右子。在下一次迭代中,Y有两个孩子。但是,循环的双重条件使其在到达自身时停止,这表明它的左子树已被遍历。因此,它会自行打印,并继续其右侧的子树B

B进行打印,然后current变为X,它经过与检查相同的检查过程Y,还意识到它的左子树已被遍历,并继续Z树的其余部分遵循相同的模式。

不需要递归,因为返回到(sub)tree根的链接不再依赖于通过堆栈的回溯,而是移动到了在递归有序树遍历算法中无论如何都将被访问的点-左子树已完成。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在不使用“return”语句的情况下递归构造树?

在不使用递归的情况下遍历目录?

是否可以在不使用递归或堆栈/队列的情况下获得二叉树的高度?

在给定有序和预序遍历的情况下,如何导出该公式的证明以使二叉树成为正确的子代?

二叉搜索树的递归有序遍历

帮助我了解不使用递归的有序遍历

如何在不使用递归方法的情况下查找二叉搜索树的节点

如何在c中不使用任何递归函数的情况下遍历目录?

在不使用 Java API 的情况下反转堆栈

有没有办法在不使用 CTE 的情况下进行递归 SQL 查询?

在不使用数组的情况下递归创建所有子集

在不使用循环的情况下遍历列表

在不使用递归的情况下刷新javascript的功能

使用迭代器和堆栈的二进制搜索树有序遍历-空间复杂度O(log N)?怎么样?

有序二叉树遍历(使用Python)

简单的有序树遍历提供了一个非终止循环。(使用数组)

尝试使用有序遍历在Haskell中展平一棵树

Python中树的有序遍历返回列表

在“有序树遍历”中查找特定节点

显示二叉树的有序遍历

二叉搜索树的有序遍历

有没有办法在不使用pairs()的情况下循环遍历一个数组?

在没有完整树遍历的情况下遍历树叶节点

有没有办法在不使用递归的情况下获取参数包中的值?

如何理解Java中BST的递归有序遍历?

从 BST 中递归删除和有序遍历

在没有-R的情况下递归使用`ls`

如何从有序遍历和预遍历遍历生成二叉树

如何在不使用分号的情况下打印 1 到 N?解释这段代码