我有一个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);
}
}
}
以上是我的删除功能。
以下是崩溃发生的一些截图:
这些是我的旋转功能。它们似乎正常工作,因为每次我创建一棵树时,它总是被报告为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);
}
更新:不再崩溃,但删除后会留下一些不平衡。示例测试用例: