RedBlack Tree插入方法不起作用

时间:2016-09-18 10:42:33

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

我正在尝试实现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();
  }
}

此实现尚未完成,仅适用于左左侧情况(如主方法3,2,1),这意味着我必须进行正确的旋转。

预期输出应为:

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

而不是这个输出我得

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

有谁能告诉我在哪里犯错误?显然我不想发布整个代码,而只是建议如何解决这个问题,以及为什么它不起作用。

1 个答案:

答案 0 :(得分:0)

您应该首先执行一个二进制搜索树插入操作,然后修复插入操作,因为它现在可能不平衡。重新平衡时应考虑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;
                    }
                }
           }