【问题标题】:RedBlack Tree insertion method does not work红黑树插入方法不起作用
【发布时间】:2017-01-26 04:11:54
【问题描述】:

我正在尝试实现 RedBlack 树插入方法,但它没有按预期工作。这是源代码。

插入方法:

void insert( int key ) { root = insert( null, root, key ); root.color = BLACK; }
  private Node insert( Node parent, Node root, int key )
  {

    //STEP 1 : Classic BST insertion
    if ( root == null )
      return ( new Node( parent, key, RED ) );

    boolean isLeft;
    if ( key < root.key )
    {
      root.left = insert( root, root.left, key);
      isLeft = true;
    }
    else
    {
      root.right = insert( root, root.right, key);
      isLeft = false;
    }

    //STEP2: Self balancing the tree.
    if ( isLeft )
    {
      if ( root.color == RED && root.left.color == RED )
      {
        Node sibling = findSibling( root );
        if ( ! isRed( sibling ) )
        {
          if ( isLeftChild( root ) )
          {
            return rightRotate( root, true );
          }
          else
          {
            //recolore( root );
          }
        }
      }
    }
    else
    {
      // mirror case
      // yet to do
    }

    return root;
  }

RightRotate 方法 + 其他使用的方法:

 private Node rightRotate( Node newRoot, boolean changeColor )
      {
        Node oldRoot = newRoot.parent;
        oldRoot.left = newRoot.right;
        newRoot.right = oldRoot;
        newRoot.parent = oldRoot.parent;
        oldRoot.parent = newRoot;

        if ( changeColor )
        {
          root.color = BLACK;
          root.parent.color = RED;
        }
        return newRoot;
      }

private Node findSibling( Node root )
  {
    Node parent = root.parent;
    if ( parent.left == root )
      return parent.right;
    return parent.left;
  }

  private boolean isRed( Node root )
  {
    if ( root == null )
      return false;
    return root.color == RED;
  }

  private boolean isLeftChild( Node root )
  {
    if ( root.parent == null )
      return false;

    if ( root.parent.left == root )
      return true;

    return false;
  }

树的主 + 前置打印:

void preOrder() { preOrder( root ); }
  private void preOrder( Node root )
  {
    if ( root != null )
    {
      System.out.print( " | " + ( root.color ? "RED" : "BLACK" ) + " " + root.key + " |" );
      preOrder( root.left );
      preOrder( root.right );
    }
  }

}

class Main
{
  public static void main( String[] args )
  {
    RedBlackBST tree = new RedBlackBST();
    tree.insert( 3 );
    tree.insert( 2 );
    tree.insert( 1 );

    tree.preOrder();
  }
}

这个实现还没有完成,应该只适用于 Left Left 情况(如在主要方法 3,2,1 中),这意味着我必须进行右旋转。

预期的输出应该是:

| BLACK 2 | | RED 1 | | RED 3 |

我得到的不是这个输出

 | BLACK 3 | | BLACK 2 | | RED 1 | | BLACK 3 | | BLACK 2 | | RED 1 | ... // infinity loop

谁能告诉我哪里出错了?显然,我不希望您发布整个代码,而只是提出如何解决该问题以及为什么它不起作用的建议。

【问题讨论】:

    标签: java data-structures red-black-tree


    【解决方案1】:

    您应该首先执行二叉搜索树插入,然后修复插入,因为它现在可能不平衡,重新平衡时应该考虑 4 种不同的情况,以下代码显示了它们。这是C#中的代码(应该很容易转换成java) 在下面的代码中,T1是树节点中键的类型,T2是树节点中值的类型。实现是通用的。

        public RedBlackTreeNode<T1, T2> Insert(RedBlackTreeNode<T1, T2> root, RedBlackTreeNode<T1, T2> newNode)
                {
                    root = Insert_BST(root, newNode); /* is normal bst insert.*/
                    Insert_Repair(root, newNode);
    
                    root = newNode;
                    while (root.Parent != null)
                    {
                        root = root.Parent;
                    }
                    return root;
                }
     private void Insert_Repair(RedBlackTreeNode<T1, T2> root, RedBlackTreeNode<T1, T2> newNode)
            {   
               if (newNode.Parent == null && newNode.Color == Color.Red) /* Property: the root is black. */
                    {
                        newNode.FlipColor();
                    }
                    else if (newNode.Parent != null && newNode.Parent.Color == Color.Red) /* If this holds it means that both the new node and its parent are red, and in a red-black tree this is not allowed. Children of a red node should be black.*/
                    {
                        var uncle = newNode.GetUncle();
    
                        if (uncle != null && uncle.Color == Color.Red) /* Both the parent and uncle of the new node are red. Note that a null uncle is considered black. */
                        {
                            newNode.Parent.Color = Color.Black;
                            uncle.Color = Color.Black;
                            newNode.GetGrandParent().Color = Color.Red;
                            Insert_Repair(root, newNode.GetGrandParent()); /* Repeat repair on the grandparent, as by the re-coloring the previous layers could have been messed up. */
                        }
                        else if (uncle == null || uncle.Color == Color.Black)
                        {`enter code here`
                            if (newNode.FormsTriangle() && newNode.IsLeftChild())
                            {
                                RotateRight(newNode.Parent);
                                newNode = newNode.RightChild; /* After rotation new node has become the parent of its former parent.*/
                                /* Triangle is transformed to a line.*/
                            }
                            else if (newNode.FormsTriangle() && newNode.IsRightChild())
                            {
                                RotateLeft(newNode.Parent);
                                newNode = newNode.LeftChild; /* After rotation new node has become the parent of its former parent.*/
                                /* Triangle is transformed to a line.*/
                            }
    
                            /* When reaching at this point, we might or might not have gone through above two triangle forms, as the alignment could have already been a line.*/
                            var grandParent = newNode.GetGrandParent();
                            if (newNode.IsRightChild())
                            {
                                RotateLeft(grandParent);
                            }
                            else if (newNode.IsLeftChild())
                            {
                                RotateRight(grandParent);
                            }
                            newNode.Parent.Color = Color.Black;
                            if (grandParent != null)
                                grandParent.Color = Color.Red;
                        }
                    }
               }
    

    【讨论】:

      猜你喜欢
      • 2015-01-07
      • 2018-11-06
      • 2013-11-17
      • 2020-07-25
      • 2018-05-30
      • 1970-01-01
      • 2017-12-23
      • 2013-02-28
      相关资源
      最近更新 更多