Мой алгоритм работает неправильно, если удалять несбалансированный корневой элемент, потому что в этом случае не происходит балансировка, так как у него нет родителей. Делал вроде по классическому алгоритму, но не уверен что манипулирую правильно указателями при замещении... Хочется сделать элегантно, без многочисленных условий.
Код:
// удаление узла из дерева
TTree removeNode(TTree T, int key, bool* reduced) {
TTree Q;
TKey bkey;
if (T == NULL)
return NULL;
if (key == T->key) {
if (T->left == NULL) {
Q = T->right;
_release(T);
*reduced = TRUE;
return Q;
}
else if (T->right == NULL) {
Q = T->left;
_release(T);
*reduced = TRUE;
return Q;
}
// здесь идет замена. в зависимости баланса удаляемого узла, выбирается симметричный ей узел в левом или правом поддереве
if (T->balance == L) {
Q = getRightNode(T->left);
bkey = Q->key;
Q->key = T->key;
T->key = bkey;
T->left = removeNode(Q, key, reduced);
T->balance = Q->balance;
return T;
}
else {
Q = getLeftNode(T->right);
bkey = Q->key;
Q->key = T->key;
T->key = bkey;
T->right = removeNode(Q, key, reduced);
T->balance = Q->balance;
return T;
}
}
if (key < T->key) {
T->left = removeNode(T->left, key, reduced);
if (*reduced == TRUE) {
switch (T->balance) {
case B:
T->balance = R;
*reduced = FALSE;
break;
case L:
T->balance = B;
break;
case R:
if (T->right->balance == L)
T = leftBigRot(T);
else
T = leftSmallRot(T);
T->balance = B;
};
}
}
if (key > T->key) {
T->right = removeNode(T->right, key, reduced);
if (*reduced == TRUE) {
switch (T->balance) {
case B:
T->balance = L;
*reduced = FALSE;
break;
case R:
T->balance = B;
break;
case L:
if (T->left->balance == R)
T = rightBigRot(T);
else
T = rightSmallRot(T);
T->balance = B;
};
}
}
return T;
}
День на это потратил, обидно не разобраться!