AVL Delete方法很奇怪,C ++

时间:2014-12-03 00:31:15

标签: c++ debugging avl-tree

所以我用C ++实现了一个AVL。 当我测试树函数时,当我尝试执行以下操作时,特定测试失败:

  1. 将60插入树
  2. 将100插入树中 **现在树应该是这样的:

      100(root)
    60
    
  3. 从树中删除60

  4. **我们期望发生的事情:

        60(root)
    

    但相反,我得到一个段错误。 此外,当我尝试删除100,一切都很好! 这些是被调用的方法:

    void AVL<T, Compare>::Delete(const T& key) {
      Node<T>* node = find(key);
      if (!node) {
        return;
      }
      Node<T>* parent = node->getParent();
      if (node->isLeaf() == 1) {
        leafRemove(node);
        fixBalance(parent);
      } else {
        if ((node->getRight()) && (node->getLeft())) {
          oneChildRemove(node);
        } else {
          twoChildrenRemove(node);
        }
      }
    }
    

    加:

    void AVL<T, Compare>::twoChildrenRemove(Node<T>* node) {
      Node<T>* swapped = getNodeSuccessor(node);
      Node<T>* ancestor = node->getParent();
      swapNodes(node, swapped);
      if (!(swapped->getLeft()) && (!swapped->getRight())) {
        leafRemove(swapped);
      } else {
        oneChildRemove(swapped);
      }
      if (!ancestor) {
        fixBalance(node);
      } else {
        fixBalance(ancestor);
      }
      return;
    }
    

    template<class T, class Compare>
    void AVL<T, Compare>::oneChildRemove(Node<T>* node) {
      Node<T>* ancestor = node->getParent(); //=100
      Node<T>* branch;
      if (node->getLeft()) {
        branch = node->getLeft(); 
      }
      if (node->getRight()) {
        branch = node->getRight();
      }
      swapNodes(node, branch);
      leafRemove(branch);
      if (!ancestor) {
        fixBalance(node);
      } else {
        fixBalance(ancestor);
      }
    }
    

    你能发现问题吗?

1 个答案:

答案 0 :(得分:1)

您对AVL Tree的理解是错误的。

删除节点时,您的算法应满足以下条件,

1) If x has no children, delete x.
2) If x has one child, delete x and link x's parent to x's child
3) If x has two children, 
      -find x's successor z [the leftmost node in the rightsubtree of x]
      -replace x's contents with z's contents, and 
      -delete z.
      (Note: z does not have a left child, but may have a right child)
      [since z has at most one child, so we use case (1) or (2) to delete z]

我会告诉你这个概念,然后你从那里发展。

void AVL<T, Compare>::oneChildRemove(Node<T>* node) {
      Node<T>* swapped= node->getNodeSuccessor(node); //Get the only child
      Node<T>* ancestor = node->getParent();
      swapNodes(ancestor, swapped); //copy child node(swapped) to point to parent(ancestor)
      leafRemove(node);//Delete the node child
}

void AVL<T, Compare>::twoChildrenRemove(Node<T>* node) {
      Node<T>* ancestor = node->getParent();//Get Parent Node of the node to be deleted.
      Node<T>* rightChild = getRightSuccessor(node);//Get Right Child of the node to be deleted
      Node<T>* leftMostRigthChild = GetLeftMostRightChild(rightChild);//Get Left most child of the right child.
      swapNodes(leftMostRigthChild , ancestor);//copy leftmostrightchild to point to parent

      if (!leftMostRigthChild ->getRight()) { //If no right child for the leftMostRigthChild its leaf node.
           leafRemove(leftMostRigthChild); //So delete it.
      } else {
           oneChildRemove(leftMostRigthChild); //Else it is have one right child and hence call oneChildRemove for the leftMostRigthChild.
      }
      return;
 }