0

就在我坐下来为 morris 中序遍历编写代码之前,我尝试了这个示例,但对于它在这种特殊情况下的工作方式有点困惑:

       80
    /      \
  60        100
    \       /
     70    90
    /
   65
  / 
 63
  \
   64

步骤1:

   60
    \
     70
   /    \
  65     80
 /        \
63        100
 \         /
  64      90

据我了解,下一步70的算法将成为65的右孩子,那么60会发生什么?我很确定我错过了一些微不足道的东西,但不幸的是无法将其放在首位。

public void MorrisInorder() {
    BSTNode<T> p = root, tmp;
    while (p != null)
        if (p.left == null) {
             visit(p);
             p = p.right;
        }
        else {
             tmp = p.left;
             while (tmp.right != null && // go to the rightmost node of
                    tmp.right != p)  // the left subtree or
                  tmp = tmp.right;   // to the temporary parent of p;
             if (tmp.right == null) {// if 'true' rightmost node was
                  tmp.right = p;     // reached, make it a temporary
                  p = p.left;        // parent of the current root,
             }
             else {                  // else a temporary parent has been
                  visit(p);          // found; visit node p and then cut
                  tmp.right = null;  // the right pointer of the current
                  p = p.right;       // parent, whereby it ceases to be
             }                       // a parent;
        }
}

我正在遵循 morris 中序遍历的代码。

4

1 回答 1

2

为了直接回答您的问题,我认为您案例的第 1 步中的数字并不准确,因为不应删除从节点“80”到节点“60”的边。步骤1中唯一的变化只是将节点“70”的右点重定向到节点“80”(见步骤1),这表示算法经过节点“80”的左子树后的返回路径。

步骤1:

      80
    / ^    \
   60 |    100
    \ |    /
    70   90
    /
   65
  / 
 63
  \
  64

添加从节点“70”到节点“80”的返回路径后,由于当前节点“60”的左点为NULL,则将当前节点设置为节点“70”。同时,节点“65”的右点将被重定向到节点“70”

第2步:

      80
    / ^    \
   60 |    100
    \ |    /
    70   90
    /^
   / |
   65
  / 
 63
  \
  64

更详细的莫里斯中序遍历代码如下。

假设我们有一个像这样的节点结构:

/* A binary tree tNode has data, pointer to left child
and a pointer to right child */
struct tNode
{
   int data;
   struct tNode* left;
   struct tNode* right;
};

遍历是:

/* 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)
  {
    /* This means there is no left sub-tree for current node,
       then just print current node, and go to the right "child" node.
       The right "child" node may be either its true child node,
       or the returning path for "60" sub-tree (like "70" to "80") */
    if(current->left == NULL)
    {
      printf(" %d ", current->data);
      current = current->right;      
    }    
    else
    {
      /* before going to the left sub-tree, we need to find a returning path
         to current node (such as when current node is "80", and we want to 
         go to "60", so we need to save the returning path from left sub-tree 
         to "80"). It is easy to imagine that we need to return to the current
         node when we arriving the right-most node of current left sub-tree.
         Therefore, we just go to the right-most node (the first condition in
         while) and set the returning path at "pre->right == NULL" block, as
         well as updating the current node. Another situation is that when we
         arrive at the left-most leaf node (if not exist, it means current->left
         is NULL, and we won't go into this block), we have already set the right
         point of left-most leaf node as the returning node (it un-satisfies the
         second condition of while loop), and then we will recover the right
         point of this leaf node in the next "else" block.
          */
      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;
      }

      /* Revert the changes made in if part to restore the original 
        tree i.e., fix the right child of predecssor */   
      else `enter code here`
      {
        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 */
}
于 2013-10-29T13:57:16.087 回答