AVL树的删除操作:
删除操作分几种情况:
1.如果要删除的节点时NULL 则直接返回NULL。
2.如果删除的节点不为NULL,需要判断要删除的值是否等于当前节点。如果大于,则递归去删除当前节点的右子树。
3.如果删除的节点不为NULL,且要删除的值小于当前节点的值,则递归删除当前节点的左子树。
4.如果删除的节点不为NULL,如果要删除的值等于当前节点的值,则找到右子树的最小节点替换掉当前节点或者找到左子树的最大节点替换掉当前节点。
#include <iostream>
struct AVLNode {
int value;
int height;
AVLNode *left;
AVLNode *right;
};
// 计算节点的高度
int Height(AVLNode *node) {
if (node == 0)
return 0;
else
return node->height;
}
int Max(int a, int b) {
return a > b ? a : b;
}
AVLNode * FindMin(AVLNode *p) {
if (p == 0)
return 0;
if (p->left == 0)
return p;
else
return FindMin(p->left);
}
// 单方向的左旋操作
AVLNode * SingleTrunLeft(AVLNode *node) {
AVLNode *cache = node->right;
node->right = cache->left;
cache->left = node;
node->height = Max(Height(node->left), Height(node->right)) + 1;
cache->height = Max(Height(cache->left), Height(cache->right)) + 1;
return cache;
}
// 单方向的右旋操作
AVLNode * SingleTrunRight(AVLNode *node) {
AVLNode *cache = node->left;
node->left = cache->right;
cache->right = node;
node->height = Max(Height(node->left), Height(node->right)) + 1;
cache->height = Max(Height(cache->left), Height(cache->right)) + 1;
return cache;
}
// 双方向先左旋再右旋操作
AVLNode * DoubleTrunLeftRight(AVLNode *node) {
node->left = SingleTrunLeft(node->left);
return SingleTrunRight(node);
}
// 双方向的先右旋再左旋操作
AVLNode * DoubleTrunRightLeft(AVLNode *node) {
node->right = SingleTrunRight(node->right);
return SingleTrunLeft(node);
}
AVLNode * Fixed(AVLNode *node) {
if (Height(node->left) - Height(node->right) >= 2) {
if (Height(node->left->left) > Height(node->left->right))
node->left = SingleTrunRight(node->left);
else if (Height(node->left->left) < Height(node->left->right))
node = DoubleTrunLeftRight(node);
}
else if (Height(node->right) - Height(node->left) >= 2) {
if (Height(node->right->right) > Height(node->right->left))
node->right = SingleTrunLeft(node->right);
else if (Height(node->right->left) > Height(node->right->right))
node = DoubleTrunRightLeft(node);
}
return node;
}
AVLNode * InsertToTree(int v, AVLNode * node) {
// 如果node为空,直接赋值
if (node == 0)
{
node = new AVLNode();
node->value = v;
node->left = 0;
node->right = 0;
node->height = 0;
}
else if (v < node->value) { // 往左边插入时,需判断插入的是node的左节点的左边还是右边来控制单方向还是双方向
// 先插入到叶子节点上
node->left = InsertToTree(v, node->left);
node = Fixed(node);
}
else if (v > node->value){
node->right = InsertToTree(v, node->right);
node = Fixed(node);
}
node->height = Max(Height(node->left), Height(node->right)) + 1;
return node;
}
AVLNode * Delete(int v, AVLNode *node) {
if (node == 0)
return 0;
else if (v < node->value) {
node->left = Delete(v, node->left);
}
else if (v > node->value) {
node->right = Delete(v, node->right);
}
else if (node->right && node->left) {
AVLNode *p = FindMin(node->right);
node->value = p->value;
node->right = Delete(p->value, node->right);
}
else {
AVLNode *p = node;
if (node->right == 0)
node = node->left;
else if(node->left == 0)
node = node->right;
delete(p);
}
if (node)
{
node = Fixed(node);
node->height = Max(Height(node->left), Height(node->right)) + 1;
}
return node;
}
// 输出的时候假定根节点是最靠右边的,因为是中序遍历所以输出左节点之前先左进一个tab,
// 到输出根节点的时候右进一个tab,输出右节点时需要再左进一个tab,最后需要再右进一个tab用来给外层的递归使用。
void PrintAVLTree(AVLNode * tree, int &tabCount) {
if (tree == 0) return;
tabCount--;
PrintAVLTree(tree->left, tabCount);
tabCount++;
for (int i = 0; i < tabCount; i++) {
std::cout << '\t';
}
std::cout << tree->value << std::endl;
tabCount--;
PrintAVLTree(tree->right, tabCount);
tabCount++;
}
int main()
{
AVLNode *tree = 0;
tree = InsertToTree(1, tree);
tree = InsertToTree(290, tree);
tree = InsertToTree(3, tree);
tree = InsertToTree(42, tree);
tree = InsertToTree(5, tree);
tree = InsertToTree(61, tree);
tree = InsertToTree(7, tree);
tree = InsertToTree(8, tree);
tree = InsertToTree(91, tree);
tree = InsertToTree(10, tree);
tree = InsertToTree(111, tree);
tree = InsertToTree(125, tree);
tree = InsertToTree(13, tree);
tree = InsertToTree(82, tree);
tree = InsertToTree(32, tree);
tree = InsertToTree(1666, tree);
tree = InsertToTree(17, tree);
int tabCount = Height(tree);
PrintAVLTree(tree, tabCount);
Delete(91, tree);
std::cout << std::endl << "删除掉91这个节点之后的树:"<< std::endl;
PrintAVLTree(tree, tabCount);
system("Pause");
return 0;
}
来源:CSDN
作者:Cbee
链接:https://blog.csdn.net/cui240558023/article/details/103237167