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

时间:2013-10-29 12:43:46

标签: algorithm binary-tree binary-search-tree traversal tree-traversal

就在我坐下来编写Morris inorder遍历的代码之前,我尝试了这个例子,并且对于它在这种特殊情况下如何工作有点困惑:

       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 inorder遍历的代码。

1 个答案:

答案 0 :(得分:2)

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

第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

有关详细信息,morris inorder遍历的代码如下所示。

假设我们有一个节点结构,如:

/* 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 */
}