C中的AVL树删除

时间:2016-02-19 14:08:26

标签: c avl-tree

我有一个AVL Tree实现,可以通过插入成功构建树。旋转等也很好。但是我的删除功能有问题。它很难平衡,有时会崩溃。对我来说,旋转是有意义的(我已经评论了适当的地方)但不知何故它不起作用。我该如何解决这个问题?

void delete_elem(node** t, int val, uint delete_flag) {
    if(!(*t))
        return;
    if((*t)->data < val)
        delete_elem(&(*t)->right, val, delete_flag);
    else if((*t)->data > val)
        delete_elem(&(*t)->left, val, delete_flag);
    else {                                                                  // found elem
                                                                            // if there's a duplicate, remove it
        if(delete_flag == DELETE_NO_FORCE && (*t)->dup_count)   {
            --(*t)->dup_count;
            printf("Duplicate element removed. %d left.\n", (*t)->dup_count);
        }
        else {                                                              // there were no duplicates
            node* del;
            if(!(*t)->left && (*t)->right) {                                // no left but right
                del = (*t);
                (*t) = (*t)->right;
                free(del);
            }
            else if(!(*t)->right && (*t)->left) {                           // no right but left
                del = (*t);
                (*t) = (*t)->left;
                free(del);
            }
            else if(!(*t)->left && !(*t)->right) {                          // additionally, you can use the is_leaf function we wrote before, in here
                free(*t);
                *t = NULL;
            }
            else {                                                          // has both children
                del = get_successor(*t, *t);                                // get the in-order successor in tree *t of *t
                printf("succ of %d is %d.\n", (*t)->data, del->data);
                (*t)->data = del->data;                                     // swap the successor's data with t's data
                (*t)->dup_count = del->dup_count;                           // IMPORTANT! We support duplicates! Duplicate count must also be swapped!
                delete_elem(&(*t)->right, del->data, DELETE_FORCE);         // We must now delete this guy forcefully!
            }

            if(!(*t))                                                       // if t was deleted and not needed anymore, don't bother. Update height if it exists
                return;

            (*t)->height = Max(get_height((*t)->left), get_height((*t)->right)) + 1;
            int bfactor = get_balance(*t);

            if(bfactor > 1 && get_balance((*t)->left) > 0)
                rotate_once_right(t);
            else if(bfactor > 1 && get_balance((*t)->left) < 0)
                rotate_twice_left(t);
            else if(bfactor < -1 && get_balance((*t)->right) > 0)
                rotate_once_left(t);
            else if(bfactor < -1 && get_balance((*t)->right) < 0)
                rotate_twice_right(t);
        }
    }
}

以上是我的删除功能。

以下是崩溃发生的一些截图:

Initial Tree

After first Deletion

Crash after 2nd Deletion

这些是我的旋转功能。它们似乎正常工作,因为每次我创建一棵树时,它总是被报告为AVL树。但是,以防万一:

void rotate_once_left(node** k1) {
    node* temp = (*k1)->left;
    (*k1)->left = temp->right;
    temp->right = *k1;

    (*k1)->height = Max(get_height((*k1)->left), get_height((*k1)->right)) + 1;
    temp->height = Max(get_height(temp->left), (*k1)->height) + 1;

    *k1 = temp;
}

void rotate_once_right(node** k1) {
    node* temp = (*k1)->right;
    (*k1)->right = temp->left;
    temp->left = *k1;

    (*k1)->height = Max(get_height((*k1)->left), get_height((*k1)->right)) + 1;
    temp->height = Max(get_height(temp->right), (*k1)->height) + 1;

    *k1 = temp;
}

void rotate_twice_left(node** k1) {
    rotate_once_right(&(*k1)->left);
    rotate_once_left(k1);
}

void rotate_twice_right(node** k1) {
    rotate_once_left(&(*k1)->right);
    rotate_once_right(k1);
}

更新:不再崩溃,但删除后会留下一些不平衡。示例测试用例:

This worked This didn't work

0 个答案:

没有答案