根据莫里斯的顺序,这棵树的下一步是什么



就在我坐下来为莫里斯无序遍历编写代码之前,我尝试了这个例子,并且对它在这种特殊情况下的工作方式感到有些困惑:

       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;
        }
}

我遵循的莫里斯无序遍历代码。

为了直接回答您的问题,我认为该数字在您案例的第 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 */
}

最新更新